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