// 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 <stdint.h>

#include "base/containers/circular_deque.h"
#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,
             size_t 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);

  // Discards a block within the ring buffer.
  //
  // Parameters:
  //   pointer: the pointer to the memory block to free.
  void DiscardBlock(void* pointer);

  // Gets the size of the largest free block that is available without waiting.
  unsigned int GetLargestFreeSizeNoWaiting();

  // Gets the total size of all free blocks that are available without waiting.
  unsigned int GetTotalFreeSizeNoWaiting();

  // 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_t*>(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_t*>(pointer) - static_cast<int8_t*>(base_);
  }

  // Rounds the given size to the alignment in use.
  unsigned int RoundToAlignment(unsigned int size) {
    return (size + alignment_ - 1) & ~(alignment_ - 1);
  }

  // Shrinks the last block.  new_size must be smaller than the current size
  // and the block must still be in use in order to shrink.
  void ShrinkLastBlock(unsigned int new_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;
  };

  using Container = base::circular_deque<Block>;
  using BlockIndex = unsigned int;

  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_
