diff options
Diffstat (limited to 'chromium/gpu/command_buffer/client/ring_buffer.h')
-rw-r--r-- | chromium/gpu/command_buffer/client/ring_buffer.h | 198 |
1 files changed, 198 insertions, 0 deletions
diff --git a/chromium/gpu/command_buffer/client/ring_buffer.h b/chromium/gpu/command_buffer/client/ring_buffer.h new file mode 100644 index 00000000000..d1f70a26c69 --- /dev/null +++ b/chromium/gpu/command_buffer/client/ring_buffer.h @@ -0,0 +1,198 @@ +// 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. + +// This file contains the definition of the RingBuffer class. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_ +#define GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_ + +#include <deque> + +#include "gpu/command_buffer/common/logging.h" +#include "gpu/command_buffer/common/types.h" +#include "gpu/gpu_export.h" + +namespace gpu { +class CommandBufferHelper; + +// RingBuffer manages a piece of memory as a ring buffer. Memory is allocated +// with Alloc and then a is freed pending a token with FreePendingToken. Old +// allocations must not be kept past new allocations. +class GPU_EXPORT RingBuffer { + public: + typedef unsigned int Offset; + + // Creates a RingBuffer. + // Parameters: + // base_offset: The offset of the start of the buffer. + // size: The size of the buffer in bytes. + // helper: A CommandBufferHelper for dealing with tokens. + RingBuffer( + Offset base_offset, unsigned int size, CommandBufferHelper* helper); + + ~RingBuffer(); + + // Allocates a block of memory. If the buffer is out of directly available + // memory, this function may wait until memory that was freed "pending a + // token" can be re-used. + // + // Parameters: + // size: the size of the memory block to allocate. + // + // Returns: + // the offset of the allocated memory block. + Offset Alloc(unsigned int size); + + // Frees a block of memory, pending the passage of a token. That memory won't + // be re-allocated until the token has passed through the command stream. + // + // Parameters: + // offset: the offset of the memory block to free. + // token: the token value to wait for before re-using the memory. + void FreePendingToken(Offset offset, unsigned int token); + + // Gets the size of the largest free block that is available without waiting. + unsigned int GetLargestFreeSizeNoWaiting(); + + // Gets the size of the largest free block that can be allocated if the + // caller can wait. Allocating a block of this size will succeed, but may + // block. + unsigned int GetLargestFreeOrPendingSize() { + return size_; + } + + private: + enum State { + IN_USE, + PADDING, + FREE_PENDING_TOKEN + }; + // Book-keeping sturcture that describes a block of memory. + struct Block { + Block(Offset _offset, unsigned int _size, State _state) + : offset(_offset), + size(_size), + token(0), + state(_state) { + } + Offset offset; + unsigned int size; + unsigned int token; // token to wait for. + State state; + }; + + typedef std::deque<Block> Container; + typedef unsigned int BlockIndex; + + void FreeOldestBlock(); + + CommandBufferHelper* helper_; + + // Used blocks are added to the end, blocks are freed from the beginning. + Container blocks_; + + // The base offset of the ring buffer. + Offset base_offset_; + + // The size of the ring buffer. + Offset size_; + + // Offset of first free byte. + Offset free_offset_; + + // Offset of first used byte. + // Range between in_use_mark and free_mark is in use. + Offset in_use_offset_; + + DISALLOW_IMPLICIT_CONSTRUCTORS(RingBuffer); +}; + +// This class functions just like RingBuffer, but its API uses pointers +// instead of offsets. +class RingBufferWrapper { + public: + // Parameters: + // base_offset: The offset to the start of the buffer + // size: The size of the buffer in bytes. + // helper: A CommandBufferHelper for dealing with tokens. + // base: The physical address that corresponds to base_offset. + RingBufferWrapper(RingBuffer::Offset base_offset, + unsigned int size, + CommandBufferHelper* helper, + void* base) + : allocator_(base_offset, size, helper), + base_(static_cast<int8*>(base) - base_offset) { + } + + // Allocates a block of memory. If the buffer is out of directly available + // memory, this function may wait until memory that was freed "pending a + // token" can be re-used. + // + // Parameters: + // size: the size of the memory block to allocate. + // + // Returns: + // the pointer to the allocated memory block, or NULL if out of + // memory. + void* Alloc(unsigned int size) { + RingBuffer::Offset offset = allocator_.Alloc(size); + return GetPointer(offset); + } + + // Allocates a block of memory. If the buffer is out of directly available + // memory, this function may wait until memory that was freed "pending a + // token" can be re-used. + // This is a type-safe version of Alloc, returning a typed pointer. + // + // Parameters: + // count: the number of elements to allocate. + // + // Returns: + // the pointer to the allocated memory block, or NULL if out of + // memory. + template <typename T> T* AllocTyped(unsigned int count) { + return static_cast<T*>(Alloc(count * sizeof(T))); + } + + // Frees a block of memory, pending the passage of a token. That memory won't + // be re-allocated until the token has passed through the command stream. + // + // Parameters: + // pointer: the pointer to the memory block to free. + // token: the token value to wait for before re-using the memory. + void FreePendingToken(void* pointer, unsigned int token) { + GPU_DCHECK(pointer); + allocator_.FreePendingToken(GetOffset(pointer), token); + } + + // Gets a pointer to a memory block given the base memory and the offset. + void* GetPointer(RingBuffer::Offset offset) const { + return static_cast<int8*>(base_) + offset; + } + + // Gets the offset to a memory block given the base memory and the address. + RingBuffer::Offset GetOffset(void* pointer) const { + return static_cast<int8*>(pointer) - static_cast<int8*>(base_); + } + + // Gets the size of the largest free block that is available without waiting. + unsigned int GetLargestFreeSizeNoWaiting() { + return allocator_.GetLargestFreeSizeNoWaiting(); + } + + // Gets the size of the largest free block that can be allocated if the + // caller can wait. + unsigned int GetLargestFreeOrPendingSize() { + return allocator_.GetLargestFreeOrPendingSize(); + } + + private: + RingBuffer allocator_; + void* base_; + DISALLOW_IMPLICIT_CONSTRUCTORS(RingBufferWrapper); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_ |