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#ifndef GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_
6#define GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_
7
8#include "base/compiler_specific.h"
9#include "base/memory/scoped_ptr.h"
10#include "gpu/command_buffer/client/ring_buffer.h"
11#include "gpu/command_buffer/common/buffer.h"
12#include "gpu/command_buffer/common/gles2_cmd_utils.h"
13#include "gpu/gpu_export.h"
14
15namespace gpu {
16
17class CommandBufferHelper;
18
19// Interface for managing the transfer buffer.
20class GPU_EXPORT TransferBufferInterface {
21 public:
22  TransferBufferInterface() { }
23  virtual ~TransferBufferInterface() { }
24
25  virtual bool Initialize(
26      unsigned int buffer_size,
27      unsigned int result_size,
28      unsigned int min_buffer_size,
29      unsigned int max_buffer_size,
30      unsigned int alignment,
31      unsigned int size_to_flush) = 0;
32
33  virtual int GetShmId() = 0;
34  virtual void* GetResultBuffer() = 0;
35  virtual int GetResultOffset() = 0;
36
37  virtual void Free() = 0;
38
39  virtual bool HaveBuffer() const = 0;
40
41  // Allocates up to size bytes.
42  virtual void* AllocUpTo(unsigned int size, unsigned int* size_allocated) = 0;
43
44  // Allocates size bytes.
45  // Note: Alloc will fail if it can not return size bytes.
46  virtual void* Alloc(unsigned int size) = 0;
47
48  virtual RingBuffer::Offset GetOffset(void* pointer) const = 0;
49
50  virtual void FreePendingToken(void* p, unsigned int token) = 0;
51};
52
53// Class that manages the transfer buffer.
54class GPU_EXPORT TransferBuffer : public TransferBufferInterface {
55 public:
56  TransferBuffer(CommandBufferHelper* helper);
57  virtual ~TransferBuffer();
58
59  // Overridden from TransferBufferInterface.
60  virtual bool Initialize(
61      unsigned int default_buffer_size,
62      unsigned int result_size,
63      unsigned int min_buffer_size,
64      unsigned int max_buffer_size,
65      unsigned int alignment,
66      unsigned int size_to_flush) OVERRIDE;
67  virtual int GetShmId() OVERRIDE;
68  virtual void* GetResultBuffer() OVERRIDE;
69  virtual int GetResultOffset() OVERRIDE;
70  virtual void Free() OVERRIDE;
71  virtual bool HaveBuffer() const OVERRIDE;
72  virtual void* AllocUpTo(
73      unsigned int size, unsigned int* size_allocated) OVERRIDE;
74  virtual void* Alloc(unsigned int size) OVERRIDE;
75  virtual RingBuffer::Offset GetOffset(void* pointer) const OVERRIDE;
76  virtual void FreePendingToken(void* p, unsigned int token) OVERRIDE;
77
78  // These are for testing.
79  unsigned int GetCurrentMaxAllocationWithoutRealloc() const;
80  unsigned int GetMaxAllocation() const;
81
82 private:
83  // Tries to reallocate the ring buffer if it's not large enough for size.
84  void ReallocateRingBuffer(unsigned int size);
85
86  void AllocateRingBuffer(unsigned int size);
87
88  CommandBufferHelper* helper_;
89  scoped_ptr<RingBuffer> ring_buffer_;
90
91  // size reserved for results
92  unsigned int result_size_;
93
94  // default size. Size we want when starting or re-allocating
95  unsigned int default_buffer_size_;
96
97  // min size we'll consider successful
98  unsigned int min_buffer_size_;
99
100  // max size we'll let the buffer grow
101  unsigned int max_buffer_size_;
102
103  // alignment for allocations
104  unsigned int alignment_;
105
106  // Size at which to do an async flush. 0 = never.
107  unsigned int size_to_flush_;
108
109  // Number of bytes since we last flushed.
110  unsigned int bytes_since_last_flush_;
111
112  // the current buffer.
113  scoped_refptr<gpu::Buffer> buffer_;
114
115  // id of buffer. -1 = no buffer
116  int32 buffer_id_;
117
118  // address of result area
119  void* result_buffer_;
120
121  // offset to result area
122  uint32 result_shm_offset_;
123
124  // false if we failed to allocate min_buffer_size
125  bool usable_;
126};
127
128// A class that will manage the lifetime of a transferbuffer allocation.
129class GPU_EXPORT ScopedTransferBufferPtr {
130 public:
131  ScopedTransferBufferPtr(
132      unsigned int size,
133      CommandBufferHelper* helper,
134      TransferBufferInterface* transfer_buffer)
135      : buffer_(NULL),
136        size_(0),
137        helper_(helper),
138        transfer_buffer_(transfer_buffer) {
139    Reset(size);
140  }
141
142  ~ScopedTransferBufferPtr() {
143    Release();
144  }
145
146  bool valid() const {
147    return buffer_ != NULL;
148  }
149
150  unsigned int size() const {
151    return size_;
152  }
153
154  int shm_id() const {
155    return transfer_buffer_->GetShmId();
156  }
157
158  RingBuffer::Offset offset() const {
159    return transfer_buffer_->GetOffset(buffer_);
160  }
161
162  void* address() const {
163    return buffer_;
164  }
165
166  void Release();
167
168  void Reset(unsigned int new_size);
169
170 private:
171  void* buffer_;
172  unsigned int size_;
173  CommandBufferHelper* helper_;
174  TransferBufferInterface* transfer_buffer_;
175  DISALLOW_COPY_AND_ASSIGN(ScopedTransferBufferPtr);
176};
177
178template <typename T>
179class ScopedTransferBufferArray : public ScopedTransferBufferPtr {
180 public:
181  ScopedTransferBufferArray(
182      unsigned int num_elements,
183      CommandBufferHelper* helper, TransferBufferInterface* transfer_buffer)
184      : ScopedTransferBufferPtr(
185          num_elements * sizeof(T), helper, transfer_buffer) {
186  }
187
188  T* elements() {
189    return static_cast<T*>(address());
190  }
191
192  unsigned int num_elements() const {
193    return size() / sizeof(T);
194  }
195};
196
197}  // namespace gpu
198
199#endif  // GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_
200