// 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 "base/logging.h" #include "base/macros.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: // alignment: Alignment for allocations. // 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. // base: The physical address that corresponds to base_offset. RingBuffer(unsigned int alignment, Offset base_offset, unsigned int size, CommandBufferHelper* helper, void* base); ~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 pointer to the allocated memory block. void* 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: // 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); // 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_; } // 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_); } // Rounds the given size to the alignment in use. unsigned int RoundToAlignment(unsigned int size) { return (size + alignment_ - 1) & ~(alignment_ - 1); } 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_; // Alignment for allocations. unsigned int alignment_; // The physical address that corresponds to base_offset. void* base_; DISALLOW_IMPLICIT_CONSTRUCTORS(RingBuffer); }; } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_