| // 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. |
| |
| #include "gpu/command_buffer/service/transfer_buffer_manager.h" |
| |
| #include <limits> |
| |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/debug/trace_event.h" |
| #include "base/process/process_handle.h" |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| |
| using ::base::SharedMemory; |
| |
| namespace gpu { |
| |
| TransferBufferManagerInterface::~TransferBufferManagerInterface() { |
| } |
| |
| TransferBufferManager::TransferBufferManager() |
| : shared_memory_bytes_allocated_(0) { |
| } |
| |
| TransferBufferManager::~TransferBufferManager() { |
| while (!registered_buffers_.empty()) { |
| BufferMap::iterator it = registered_buffers_.begin(); |
| DCHECK(shared_memory_bytes_allocated_ >= it->second.size); |
| shared_memory_bytes_allocated_ -= it->second.size; |
| delete it->second.shared_memory; |
| registered_buffers_.erase(it); |
| } |
| DCHECK(!shared_memory_bytes_allocated_); |
| } |
| |
| bool TransferBufferManager::Initialize() { |
| return true; |
| } |
| |
| bool TransferBufferManager::RegisterTransferBuffer( |
| int32 id, |
| base::SharedMemory* shared_memory, |
| size_t size) { |
| if (id <= 0) { |
| DVLOG(0) << "Cannot register transfer buffer with non-positive ID."; |
| return false; |
| } |
| |
| // Fail if the ID is in use. |
| if (registered_buffers_.find(id) != registered_buffers_.end()) { |
| DVLOG(0) << "Buffer ID already in use."; |
| return false; |
| } |
| |
| // Duplicate the handle. |
| base::SharedMemoryHandle duped_shared_memory_handle; |
| if (!shared_memory->ShareToProcess(base::GetCurrentProcessHandle(), |
| &duped_shared_memory_handle)) { |
| DVLOG(0) << "Failed to duplicate shared memory handle."; |
| return false; |
| } |
| scoped_ptr<SharedMemory> duped_shared_memory( |
| new SharedMemory(duped_shared_memory_handle, false)); |
| |
| // Map the shared memory into this process. This validates the size. |
| if (!duped_shared_memory->Map(size)) { |
| DVLOG(0) << "Failed to map shared memory."; |
| return false; |
| } |
| |
| // If it could be mapped register the shared memory with the ID. |
| Buffer buffer; |
| buffer.ptr = duped_shared_memory->memory(); |
| buffer.size = size; |
| buffer.shared_memory = duped_shared_memory.release(); |
| |
| shared_memory_bytes_allocated_ += size; |
| TRACE_COUNTER_ID1( |
| "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_); |
| |
| registered_buffers_[id] = buffer; |
| |
| return true; |
| } |
| |
| void TransferBufferManager::DestroyTransferBuffer(int32 id) { |
| BufferMap::iterator it = registered_buffers_.find(id); |
| if (it == registered_buffers_.end()) { |
| DVLOG(0) << "Transfer buffer ID was not registered."; |
| return; |
| } |
| |
| DCHECK(shared_memory_bytes_allocated_ >= it->second.size); |
| shared_memory_bytes_allocated_ -= it->second.size; |
| TRACE_COUNTER_ID1( |
| "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_); |
| |
| delete it->second.shared_memory; |
| registered_buffers_.erase(it); |
| } |
| |
| Buffer TransferBufferManager::GetTransferBuffer(int32 id) { |
| if (id == 0) |
| return Buffer(); |
| |
| BufferMap::iterator it = registered_buffers_.find(id); |
| if (it == registered_buffers_.end()) |
| return Buffer(); |
| |
| return it->second; |
| } |
| |
| } // namespace gpu |
| |