| Index: gpu/command_buffer/client/ring_buffer.cc
 | 
| ===================================================================
 | 
| --- gpu/command_buffer/client/ring_buffer.cc	(revision 0)
 | 
| +++ gpu/command_buffer/client/ring_buffer.cc	(revision 0)
 | 
| @@ -0,0 +1,103 @@
 | 
| +// Copyright (c) 2010 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 implementation of the RingBuffer class.
 | 
| +
 | 
| +#include "../client/ring_buffer.h"
 | 
| +#include <algorithm>
 | 
| +#include "../client/cmd_buffer_helper.h"
 | 
| +
 | 
| +namespace gpu {
 | 
| +
 | 
| +RingBuffer::RingBuffer(
 | 
| +    Offset base_offset, unsigned int size, CommandBufferHelper* helper)
 | 
| +    : helper_(helper),
 | 
| +      base_offset_(base_offset),
 | 
| +      size_(size),
 | 
| +      free_offset_(0),
 | 
| +      in_use_offset_(0) {
 | 
| +}
 | 
| +
 | 
| +RingBuffer::~RingBuffer() {
 | 
| +  // Free blocks pending tokens.
 | 
| +  while (!blocks_.empty()) {
 | 
| +    FreeOldestBlock();
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +void RingBuffer::FreeOldestBlock() {
 | 
| +  DCHECK(!blocks_.empty()) << "no free blocks";
 | 
| +  Block& block = blocks_.front();
 | 
| +  DCHECK(block.valid) << "attempt to allocate more than maximum memory";
 | 
| +  helper_->WaitForToken(block.token);
 | 
| +  in_use_offset_ += block.size;
 | 
| +  if (in_use_offset_ == size_) {
 | 
| +    in_use_offset_ = 0;
 | 
| +  }
 | 
| +  // If they match then the entire buffer is free.
 | 
| +  if (in_use_offset_ == free_offset_) {
 | 
| +    in_use_offset_ = 0;
 | 
| +    free_offset_ = 0;
 | 
| +  }
 | 
| +  blocks_.pop_back();
 | 
| +}
 | 
| +
 | 
| +RingBuffer::Offset RingBuffer::Alloc(unsigned int size) {
 | 
| +  DCHECK_LE(size, size_) << "attempt to allocate more than maximum memory";
 | 
| +  // Similarly to malloc, an allocation of 0 allocates at least 1 byte, to
 | 
| +  // return different pointers every time.
 | 
| +  if (size == 0) size = 1;
 | 
| +
 | 
| +  // Wait until there is enough room.
 | 
| +  while (size > GetLargestFreeSizeNoWaiting()) {
 | 
| +    FreeOldestBlock();
 | 
| +  }
 | 
| +
 | 
| +  Offset offset = free_offset_;
 | 
| +  blocks_.push_back(Block(offset, size));
 | 
| +  free_offset_ += size;
 | 
| +  if (free_offset_ == size_) {
 | 
| +    free_offset_ = 0;
 | 
| +  }
 | 
| +  return offset + base_offset_;
 | 
| +}
 | 
| +
 | 
| +void RingBuffer::FreePendingToken(RingBuffer::Offset offset,
 | 
| +                                  unsigned int token) {
 | 
| +  offset -= base_offset_;
 | 
| +  DCHECK(!blocks_.empty()) << "no allocations to free";
 | 
| +  for (Container::reverse_iterator it = blocks_.rbegin();
 | 
| +        it != blocks_.rend();
 | 
| +        ++it) {
 | 
| +    Block& block = *it;
 | 
| +    if (block.offset == offset) {
 | 
| +      DCHECK(!block.valid) << "block that corresponds to offset already freed";
 | 
| +      block.token = token;
 | 
| +      block.valid = true;
 | 
| +      return;
 | 
| +    }
 | 
| +  }
 | 
| +  NOTREACHED() << "attempt to free non-existant block";
 | 
| +}
 | 
| +
 | 
| +unsigned int RingBuffer::GetLargestFreeSizeNoWaiting() {
 | 
| +  if (free_offset_ == in_use_offset_) {
 | 
| +    if (blocks_.empty()) {
 | 
| +      // The entire buffer is free.
 | 
| +      DCHECK_EQ(free_offset_, 0u);
 | 
| +      return size_;
 | 
| +    } else {
 | 
| +      // The entire buffer is in use.
 | 
| +      return 0;
 | 
| +    }
 | 
| +  } else if (free_offset_ > in_use_offset_) {
 | 
| +    // It's free from free_offset_ to size_
 | 
| +    return size_ - free_offset_;
 | 
| +  } else {
 | 
| +    // It's free from free_offset_ -> in_use_offset_;
 | 
| +    return in_use_offset_ - free_offset_;
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +}  // namespace gpu
 | 
| 
 | 
| Property changes on: gpu\command_buffer\client\ring_buffer.cc
 | 
| ___________________________________________________________________
 | 
| Added: svn:eol-style
 | 
|    + LF
 | 
| 
 | 
| 
 |