| // Copyright (c) 2009 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. |
| |
| #include "gpu/command_buffer/service/command_buffer_service.h" |
| |
| #include <limits> |
| |
| #include "base/callback.h" |
| #include "gpu/command_buffer/common/cmd_buffer_common.h" |
| |
| using ::base::SharedMemory; |
| |
| namespace gpu { |
| |
| CommandBufferService::CommandBufferService() |
| : size_(0), |
| get_offset_(0), |
| put_offset_(0), |
| token_(0), |
| error_(error::kNoError) { |
| // Element zero is always NULL. |
| registered_objects_.push_back(linked_ptr<SharedMemory>()); |
| } |
| |
| CommandBufferService::~CommandBufferService() { |
| } |
| |
| bool CommandBufferService::Initialize(int32 size) { |
| // Fail if already initialized. |
| if (ring_buffer_.get()) |
| return false; |
| |
| if (size <= 0 || size > kMaxCommandBufferSize) |
| return false; |
| |
| size_ = size; |
| |
| ring_buffer_.reset(new SharedMemory); |
| uint32 size_bytes = size * sizeof(CommandBufferEntry); |
| if (ring_buffer_->Create(std::wstring(), false, false, size_bytes)) { |
| if (ring_buffer_->Map(size_bytes)) |
| return true; |
| } |
| |
| size_ = 0; |
| ring_buffer_.reset(); |
| return false; |
| } |
| |
| Buffer CommandBufferService::GetRingBuffer() { |
| Buffer buffer; |
| if (ring_buffer_.get()) { |
| buffer.ptr = ring_buffer_->memory(); |
| buffer.size = ring_buffer_->max_size(); |
| buffer.shared_memory = ring_buffer_.get(); |
| } |
| return buffer; |
| } |
| |
| CommandBufferService::State CommandBufferService::GetState() { |
| State state; |
| state.size = size_; |
| state.get_offset = get_offset_; |
| state.put_offset = put_offset_; |
| state.token = token_; |
| state.error = error_; |
| |
| return state; |
| } |
| |
| CommandBufferService::State CommandBufferService::Flush(int32 put_offset) { |
| if (put_offset < 0 || put_offset > size_) { |
| error_ = gpu::error::kOutOfBounds; |
| return GetState(); |
| } |
| |
| put_offset_ = put_offset; |
| |
| if (put_offset_change_callback_.get()) { |
| put_offset_change_callback_->Run(); |
| } |
| |
| return GetState(); |
| } |
| |
| void CommandBufferService::SetGetOffset(int32 get_offset) { |
| DCHECK(get_offset >= 0 && get_offset < size_); |
| get_offset_ = get_offset; |
| } |
| |
| int32 CommandBufferService::CreateTransferBuffer(size_t size) { |
| linked_ptr<SharedMemory> buffer(new SharedMemory); |
| if (!buffer->Create(std::wstring(), false, false, size)) |
| return -1; |
| |
| if (unused_registered_object_elements_.empty()) { |
| // Check we haven't exceeded the range that fits in a 32-bit integer. |
| if (registered_objects_.size() > std::numeric_limits<uint32>::max()) |
| return -1; |
| |
| int32 handle = static_cast<int32>(registered_objects_.size()); |
| registered_objects_.push_back(buffer); |
| return handle; |
| } |
| |
| int32 handle = *unused_registered_object_elements_.begin(); |
| unused_registered_object_elements_.erase( |
| unused_registered_object_elements_.begin()); |
| DCHECK(!registered_objects_[handle].get()); |
| registered_objects_[handle] = buffer; |
| return handle; |
| } |
| |
| void CommandBufferService::DestroyTransferBuffer(int32 handle) { |
| if (handle <= 0) |
| return; |
| |
| if (static_cast<size_t>(handle) >= registered_objects_.size()) |
| return; |
| |
| registered_objects_[handle].reset(); |
| unused_registered_object_elements_.insert(handle); |
| |
| // Remove all null objects from the end of the vector. This allows the vector |
| // to shrink when, for example, all objects are unregistered. Note that this |
| // loop never removes element zero, which is always NULL. |
| while (registered_objects_.size() > 1 && !registered_objects_.back().get()) { |
| registered_objects_.pop_back(); |
| unused_registered_object_elements_.erase( |
| static_cast<int32>(registered_objects_.size())); |
| } |
| } |
| |
| Buffer CommandBufferService::GetTransferBuffer(int32 handle) { |
| if (handle < 0) |
| return Buffer(); |
| |
| if (static_cast<size_t>(handle) >= registered_objects_.size()) |
| return Buffer(); |
| |
| base::SharedMemory* shared_memory = registered_objects_[handle].get(); |
| if (!shared_memory) |
| return Buffer(); |
| |
| if (!shared_memory->memory()) { |
| if (!shared_memory->Map(shared_memory->max_size())) |
| return Buffer(); |
| } |
| |
| Buffer buffer; |
| buffer.ptr = shared_memory->memory(); |
| buffer.size = shared_memory->max_size(); |
| buffer.shared_memory = shared_memory; |
| return buffer; |
| } |
| |
| void CommandBufferService::SetToken(int32 token) { |
| token_ = token; |
| } |
| |
| void CommandBufferService::SetParseError(error::Error error) { |
| if (error_ == error::kNoError) { |
| error_ = error; |
| } |
| } |
| |
| void CommandBufferService::SetPutOffsetChangeCallback( |
| Callback0::Type* callback) { |
| put_offset_change_callback_.reset(callback); |
| } |
| |
| } // namespace gpu |