| 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
|
|
|
|
|