// 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. #ifndef GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_ #define GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_ #include #include #include "base/bind.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/trace_event/memory_dump_provider.h" #include "gpu/command_buffer/client/fenced_allocator.h" #include "gpu/command_buffer/common/buffer.h" #include "gpu/gpu_export.h" namespace gpu { class CommandBufferHelper; // Manages a shared memory segment. class GPU_EXPORT MemoryChunk { public: MemoryChunk(int32_t shm_id, scoped_refptr shm, CommandBufferHelper* helper); ~MemoryChunk(); // Gets the size of the largest free block that is available without waiting. unsigned int GetLargestFreeSizeWithoutWaiting() { return allocator_.GetLargestFreeSize(); } // Gets the size of the largest free block that can be allocated if the // caller can wait. unsigned int GetLargestFreeSizeWithWaiting() { return allocator_.GetLargestFreeOrPendingSize(); } // Gets the size of the chunk. unsigned int GetSize() const { return static_cast(shm_->size()); } // The shared memory id for this chunk. int32_t shm_id() const { return shm_id_; } // 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) { return allocator_.Alloc(size); } // Gets the offset to a memory block given the base memory and the address. // It translates NULL to FencedAllocator::kInvalidOffset. unsigned int GetOffset(void* pointer) { return allocator_.GetOffset(pointer); } // Frees a block of memory. // // Parameters: // pointer: the pointer to the memory block to free. void Free(void* pointer) { allocator_.Free(pointer); } // 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) { allocator_.FreePendingToken(pointer, token); } // Frees any blocks whose tokens have passed. void FreeUnused() { allocator_.FreeUnused(); } // Gets the free size of the chunk. unsigned int GetFreeSize() { return allocator_.GetFreeSize(); } // Returns true if pointer is in the range of this block. bool IsInChunk(void* pointer) const { return pointer >= shm_->memory() && pointer < reinterpret_cast(shm_->memory()) + shm_->size(); } // Returns true of any memory in this chunk is in use. bool InUse() { return allocator_.InUse(); } size_t bytes_in_use() const { return allocator_.bytes_in_use(); } private: int32_t shm_id_; scoped_refptr shm_; FencedAllocatorWrapper allocator_; DISALLOW_COPY_AND_ASSIGN(MemoryChunk); }; // Manages MemoryChunks. class GPU_EXPORT MappedMemoryManager : public base::trace_event::MemoryDumpProvider { public: enum MemoryLimit { kNoLimit = 0, }; // |unused_memory_reclaim_limit|: When exceeded this causes pending memory // to be reclaimed before allocating more memory. MappedMemoryManager(CommandBufferHelper* helper, size_t unused_memory_reclaim_limit); ~MappedMemoryManager() override; unsigned int chunk_size_multiple() const { return chunk_size_multiple_; } void set_chunk_size_multiple(unsigned int multiple) { DCHECK(multiple % FencedAllocator::kAllocAlignment == 0); chunk_size_multiple_ = multiple; } size_t max_allocated_bytes() const { return max_allocated_bytes_; } void set_max_allocated_bytes(size_t max_allocated_bytes) { max_allocated_bytes_ = max_allocated_bytes; } // Allocates a block of memory // Parameters: // size: size of memory to allocate. // shm_id: pointer to variable to receive the shared memory id. // shm_offset: pointer to variable to receive the shared memory offset. // Returns: // pointer to allocated block of memory. NULL if failure. void* Alloc( unsigned int size, int32_t* shm_id, unsigned int* shm_offset); // Frees a block of memory. // // Parameters: // pointer: the pointer to the memory block to free. void Free(void* pointer); // 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, int32_t token); // Free Any Shared memory that is not in use. void FreeUnused(); // Overridden from base::trace_event::MemoryDumpProvider: bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args, base::trace_event::ProcessMemoryDump* pmd) override; // Used for testing size_t num_chunks() const { return chunks_.size(); } size_t bytes_in_use() const { size_t bytes_in_use = 0; for (size_t ii = 0; ii < chunks_.size(); ++ii) { bytes_in_use += chunks_[ii]->bytes_in_use(); } return bytes_in_use; } // Used for testing size_t allocated_memory() const { return allocated_memory_; } private: typedef std::vector> MemoryChunkVector; // size a chunk is rounded up to. unsigned int chunk_size_multiple_; CommandBufferHelper* helper_; MemoryChunkVector chunks_; size_t allocated_memory_; size_t max_free_bytes_; size_t max_allocated_bytes_; // A process-unique ID used for disambiguating memory dumps from different // mapped memory manager. int tracing_id_; DISALLOW_COPY_AND_ASSIGN(MappedMemoryManager); }; // A class that will manage the lifetime of a mapped memory allocation class GPU_EXPORT ScopedMappedMemoryPtr { public: ScopedMappedMemoryPtr( uint32_t size, CommandBufferHelper* helper, MappedMemoryManager* mapped_memory_manager) : buffer_(NULL), size_(0), shm_id_(0), shm_offset_(0), flush_after_release_(false), helper_(helper), mapped_memory_manager_(mapped_memory_manager) { Reset(size); } ~ScopedMappedMemoryPtr() { Release(); } bool valid() const { return buffer_ != NULL; } void SetFlushAfterRelease(bool flush_after_release) { flush_after_release_ = flush_after_release; } uint32_t size() const { return size_; } int32_t shm_id() const { return shm_id_; } uint32_t offset() const { return shm_offset_; } void* address() const { return buffer_; } void Release(); void Reset(uint32_t new_size); private: void* buffer_; uint32_t size_; int32_t shm_id_; uint32_t shm_offset_; bool flush_after_release_; CommandBufferHelper* helper_; MappedMemoryManager* mapped_memory_manager_; DISALLOW_COPY_AND_ASSIGN(ScopedMappedMemoryPtr); }; } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_MAPPED_MEMORY_H_