root/gpu/command_buffer/client/ring_buffer.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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 "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) {
    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_

/* [<][>][^][v][top][bottom][index][help] */