| // 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 <stddef.h> | 
 | #include <stdint.h> | 
 |  | 
 | #include <memory> | 
 |  | 
 | #include "base/bind.h" | 
 | #include "base/macros.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<gpu::Buffer> 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<unsigned int>(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<const int8_t*>(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<gpu::Buffer> 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<std::unique_ptr<MemoryChunk>> 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_ |