15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file contains the definition of the RingBuffer class.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <deque>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h"
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/macros.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "gpu/gpu_export.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gpu {
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CommandBufferHelper;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RingBuffer manages a piece of memory as a ring buffer. Memory is allocated
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with Alloc and then a is freed pending a token with FreePendingToken.  Old
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocations must not be kept past new allocations.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GPU_EXPORT RingBuffer {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef unsigned int Offset;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a RingBuffer.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parameters:
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   alignment: Alignment for allocations.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   base_offset: The offset of the start of the buffer.
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   size: The size of the buffer in bytes.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   helper: A CommandBufferHelper for dealing with tokens.
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   base: The physical address that corresponds to base_offset.
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RingBuffer(unsigned int alignment, Offset base_offset,
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)             unsigned int size, CommandBufferHelper* helper, void* base);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~RingBuffer();
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allocates a block of memory. If the buffer is out of directly available
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // memory, this function may wait until memory that was freed "pending a
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // token" can be re-used.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parameters:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   size: the size of the memory block to allocate.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns:
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   the pointer to the allocated memory block.
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void* Alloc(unsigned int size);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Frees a block of memory, pending the passage of a token. That memory won't
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be re-allocated until the token has passed through the command stream.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parameters:
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  //   pointer: the pointer to the memory block to free.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   token: the token value to wait for before re-using the memory.
55010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void FreePendingToken(void* pointer, unsigned int token);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the size of the largest free block that is available without waiting.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int GetLargestFreeSizeNoWaiting();
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets the size of the largest free block that can be allocated if the
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caller can wait. Allocating a block of this size will succeed, but may
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // block.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int GetLargestFreeOrPendingSize() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return size_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
67010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Gets a pointer to a memory block given the base memory and the offset.
68010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  void* GetPointer(RingBuffer::Offset offset) const {
69010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return static_cast<int8*>(base_) + offset;
70010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
72010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Gets the offset to a memory block given the base memory and the address.
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  RingBuffer::Offset GetOffset(void* pointer) const {
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return static_cast<int8*>(pointer) - static_cast<int8*>(base_);
75010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
76010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Rounds the given size to the alignment in use.
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  unsigned int RoundToAlignment(unsigned int size) {
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return (size + alignment_ - 1) & ~(alignment_ - 1);
80010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum State {
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IN_USE,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PADDING,
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FREE_PENDING_TOKEN
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Book-keeping sturcture that describes a block of memory.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Block {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Block(Offset _offset, unsigned int _size, State _state)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : offset(_offset),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          size(_size),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          token(0),
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          state(_state) {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Offset offset;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int size;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int token;  // token to wait for.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::deque<Block> Container;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef unsigned int BlockIndex;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void FreeOldestBlock();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandBufferHelper* helper_;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used blocks are added to the end, blocks are freed from the beginning.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Container blocks_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The base offset of the ring buffer.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Offset base_offset_;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The size of the ring buffer.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Offset size_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Offset of first free byte.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Offset free_offset_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Offset of first used byte.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Range between in_use_mark and free_mark is in use.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Offset in_use_offset_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Alignment for allocations.
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  unsigned int alignment_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // The physical address that corresponds to base_offset.
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* base_;
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(RingBuffer);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gpu
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // GPU_COMMAND_BUFFER_CLIENT_RING_BUFFER_H_
138