| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #ifndef GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_ | |
| #define GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_ | |
| #include <stddef.h> | |
| #include <stdint.h> | |
| #include <memory> | |
| #include "base/compiler_specific.h" | |
| #include "base/macros.h" | |
| #include "gpu/command_buffer/client/ring_buffer.h" | |
| #include "gpu/command_buffer/common/buffer.h" | |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" | |
| #include "gpu/gpu_export.h" | |
| namespace base { | |
| class SharedMemoryHandle; | |
| } // namespace base | |
| namespace gpu { | |
| class CommandBufferHelper; | |
| // Interface for managing the transfer buffer. | |
| class GPU_EXPORT TransferBufferInterface { | |
| public: | |
| TransferBufferInterface() { } | |
| virtual ~TransferBufferInterface() { } | |
| // Returns the shared memory's handle when the back end is base::SharedMemory. | |
| // Otherwise, this returns an invalid handle. | |
| virtual base::SharedMemoryHandle shared_memory_handle() const = 0; | |
| virtual bool Initialize( | |
| unsigned int buffer_size, | |
| unsigned int result_size, | |
| unsigned int min_buffer_size, | |
| unsigned int max_buffer_size, | |
| unsigned int alignment, | |
| unsigned int size_to_flush) = 0; | |
| virtual int GetShmId() = 0; | |
| virtual void* GetResultBuffer() = 0; | |
| virtual int GetResultOffset() = 0; | |
| virtual void Free() = 0; | |
| virtual bool HaveBuffer() const = 0; | |
| // Allocates up to size bytes. | |
| virtual void* AllocUpTo(unsigned int size, unsigned int* size_allocated) = 0; | |
| // Allocates size bytes. | |
| // Note: Alloc will fail if it can not return size bytes. | |
| virtual void* Alloc(unsigned int size) = 0; | |
| virtual RingBuffer::Offset GetOffset(void* pointer) const = 0; | |
| virtual void DiscardBlock(void* p) = 0; | |
| virtual void FreePendingToken(void* p, unsigned int token) = 0; | |
| virtual unsigned int GetSize() const = 0; | |
| virtual unsigned int GetFreeSize() const = 0; | |
| virtual void ShrinkLastBlock(unsigned int new_size) = 0; | |
| }; | |
| // Class that manages the transfer buffer. | |
| class GPU_EXPORT TransferBuffer : public TransferBufferInterface { | |
| public: | |
| TransferBuffer(CommandBufferHelper* helper); | |
| ~TransferBuffer() override; | |
| // Overridden from TransferBufferInterface. | |
| base::SharedMemoryHandle shared_memory_handle() const override; | |
| bool Initialize(unsigned int default_buffer_size, | |
| unsigned int result_size, | |
| unsigned int min_buffer_size, | |
| unsigned int max_buffer_size, | |
| unsigned int alignment, | |
| unsigned int size_to_flush) override; | |
| int GetShmId() override; | |
| void* GetResultBuffer() override; | |
| int GetResultOffset() override; | |
| void Free() override; | |
| bool HaveBuffer() const override; | |
| void* AllocUpTo(unsigned int size, unsigned int* size_allocated) override; | |
| void* Alloc(unsigned int size) override; | |
| RingBuffer::Offset GetOffset(void* pointer) const override; | |
| void DiscardBlock(void* p) override; | |
| void FreePendingToken(void* p, unsigned int token) override; | |
| unsigned int GetSize() const override; | |
| unsigned int GetFreeSize() const override; | |
| void ShrinkLastBlock(unsigned int new_size) override; | |
| // These are for testing. | |
| unsigned int GetCurrentMaxAllocationWithoutRealloc() const; | |
| unsigned int GetMaxAllocation() const; | |
| private: | |
| // Tries to reallocate the ring buffer if it's not large enough for size. | |
| void ReallocateRingBuffer(unsigned int size); | |
| void AllocateRingBuffer(unsigned int size); | |
| CommandBufferHelper* helper_; | |
| std::unique_ptr<RingBuffer> ring_buffer_; | |
| // size reserved for results | |
| unsigned int result_size_; | |
| // default size. Size we want when starting or re-allocating | |
| unsigned int default_buffer_size_; | |
| // min size we'll consider successful | |
| unsigned int min_buffer_size_; | |
| // max size we'll let the buffer grow | |
| unsigned int max_buffer_size_; | |
| // alignment for allocations | |
| unsigned int alignment_; | |
| // Size at which to do an async flush. 0 = never. | |
| unsigned int size_to_flush_; | |
| // Number of bytes since we last flushed. | |
| unsigned int bytes_since_last_flush_; | |
| // the current buffer. | |
| scoped_refptr<gpu::Buffer> buffer_; | |
| // id of buffer. -1 = no buffer | |
| int32_t buffer_id_; | |
| // address of result area | |
| void* result_buffer_; | |
| // offset to result area | |
| uint32_t result_shm_offset_; | |
| // false if we failed to allocate min_buffer_size | |
| bool usable_; | |
| }; | |
| // A class that will manage the lifetime of a transferbuffer allocation. | |
| class GPU_EXPORT ScopedTransferBufferPtr { | |
| public: | |
| ScopedTransferBufferPtr( | |
| unsigned int size, | |
| CommandBufferHelper* helper, | |
| TransferBufferInterface* transfer_buffer) | |
| : buffer_(NULL), | |
| size_(0), | |
| helper_(helper), | |
| transfer_buffer_(transfer_buffer) { | |
| Reset(size); | |
| } | |
| // Constructs an empty and invalid allocation that should be Reset() later. | |
| ScopedTransferBufferPtr(CommandBufferHelper* helper, | |
| TransferBufferInterface* transfer_buffer) | |
| : buffer_(NULL), | |
| size_(0), | |
| helper_(helper), | |
| transfer_buffer_(transfer_buffer) {} | |
| ~ScopedTransferBufferPtr() { | |
| Release(); | |
| } | |
| bool valid() const { | |
| return buffer_ != NULL; | |
| } | |
| unsigned int size() const { | |
| return size_; | |
| } | |
| int shm_id() const { | |
| return transfer_buffer_->GetShmId(); | |
| } | |
| RingBuffer::Offset offset() const { | |
| return transfer_buffer_->GetOffset(buffer_); | |
| } | |
| void* address() const { | |
| return buffer_; | |
| } | |
| void Release(); | |
| void Discard(); | |
| void Reset(unsigned int new_size); | |
| // Shrinks this transfer buffer to a given size. | |
| void Shrink(unsigned int new_size); | |
| private: | |
| void* buffer_; | |
| unsigned int size_; | |
| CommandBufferHelper* helper_; | |
| TransferBufferInterface* transfer_buffer_; | |
| DISALLOW_COPY_AND_ASSIGN(ScopedTransferBufferPtr); | |
| }; | |
| template <typename T> | |
| class ScopedTransferBufferArray : public ScopedTransferBufferPtr { | |
| public: | |
| ScopedTransferBufferArray( | |
| unsigned int num_elements, | |
| CommandBufferHelper* helper, TransferBufferInterface* transfer_buffer) | |
| : ScopedTransferBufferPtr( | |
| num_elements * sizeof(T), helper, transfer_buffer) { | |
| } | |
| T* elements() { | |
| return static_cast<T*>(address()); | |
| } | |
| unsigned int num_elements() const { | |
| return size() / sizeof(T); | |
| } | |
| }; | |
| } // namespace gpu | |
| #endif // GPU_COMMAND_BUFFER_CLIENT_TRANSFER_BUFFER_H_ |