• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gpu/command_buffer/client/mapped_memory.h"
6 
7 #include <algorithm>
8 #include <functional>
9 
10 #include "base/debug/trace_event.h"
11 #include "base/logging.h"
12 #include "gpu/command_buffer/client/cmd_buffer_helper.h"
13 
14 namespace gpu {
15 
MemoryChunk(int32 shm_id,gpu::Buffer shm,CommandBufferHelper * helper)16 MemoryChunk::MemoryChunk(
17     int32 shm_id, gpu::Buffer shm, CommandBufferHelper* helper)
18     : shm_id_(shm_id),
19       shm_(shm),
20       allocator_(shm.size, helper, shm.ptr) {
21 }
22 
MappedMemoryManager(CommandBufferHelper * helper,size_t unused_memory_reclaim_limit)23 MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper,
24                                          size_t unused_memory_reclaim_limit)
25     : chunk_size_multiple_(1),
26       helper_(helper),
27       allocated_memory_(0),
28       max_free_bytes_(unused_memory_reclaim_limit) {
29 }
30 
~MappedMemoryManager()31 MappedMemoryManager::~MappedMemoryManager() {
32   CommandBuffer* cmd_buf = helper_->command_buffer();
33   for (MemoryChunkVector::iterator iter = chunks_.begin();
34        iter != chunks_.end(); ++iter) {
35     MemoryChunk* chunk = *iter;
36     cmd_buf->DestroyTransferBuffer(chunk->shm_id());
37   }
38 }
39 
Alloc(unsigned int size,int32 * shm_id,unsigned int * shm_offset)40 void* MappedMemoryManager::Alloc(
41     unsigned int size, int32* shm_id, unsigned int* shm_offset) {
42   DCHECK(shm_id);
43   DCHECK(shm_offset);
44   if (size <= allocated_memory_) {
45     size_t total_bytes_in_use = 0;
46     // See if any of the chunks can satisfy this request.
47     for (size_t ii = 0; ii < chunks_.size(); ++ii) {
48       MemoryChunk* chunk = chunks_[ii];
49       chunk->FreeUnused();
50       total_bytes_in_use += chunk->bytes_in_use();
51       if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) {
52         void* mem = chunk->Alloc(size);
53         DCHECK(mem);
54         *shm_id = chunk->shm_id();
55         *shm_offset = chunk->GetOffset(mem);
56         return mem;
57       }
58     }
59 
60     // If there is a memory limit being enforced and total free
61     // memory (allocated_memory_ - total_bytes_in_use) is larger than
62     // the limit try waiting.
63     if (max_free_bytes_ != kNoLimit &&
64         (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) {
65       TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait");
66       for (size_t ii = 0; ii < chunks_.size(); ++ii) {
67         MemoryChunk* chunk = chunks_[ii];
68         if (chunk->GetLargestFreeSizeWithWaiting() >= size) {
69           void* mem = chunk->Alloc(size);
70           DCHECK(mem);
71           *shm_id = chunk->shm_id();
72           *shm_offset = chunk->GetOffset(mem);
73           return mem;
74         }
75       }
76     }
77   }
78 
79   // Make a new chunk to satisfy the request.
80   CommandBuffer* cmd_buf = helper_->command_buffer();
81   unsigned int chunk_size =
82       ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) *
83       chunk_size_multiple_;
84   int32 id = -1;
85   gpu::Buffer shm = cmd_buf->CreateTransferBuffer(chunk_size, &id);
86   if (id  < 0)
87     return NULL;
88   MemoryChunk* mc = new MemoryChunk(id, shm, helper_);
89   allocated_memory_ += mc->GetSize();
90   chunks_.push_back(mc);
91   void* mem = mc->Alloc(size);
92   DCHECK(mem);
93   *shm_id = mc->shm_id();
94   *shm_offset = mc->GetOffset(mem);
95   return mem;
96 }
97 
Free(void * pointer)98 void MappedMemoryManager::Free(void* pointer) {
99   for (size_t ii = 0; ii < chunks_.size(); ++ii) {
100     MemoryChunk* chunk = chunks_[ii];
101     if (chunk->IsInChunk(pointer)) {
102       chunk->Free(pointer);
103       return;
104     }
105   }
106   NOTREACHED();
107 }
108 
FreePendingToken(void * pointer,int32 token)109 void MappedMemoryManager::FreePendingToken(void* pointer, int32 token) {
110   for (size_t ii = 0; ii < chunks_.size(); ++ii) {
111     MemoryChunk* chunk = chunks_[ii];
112     if (chunk->IsInChunk(pointer)) {
113       chunk->FreePendingToken(pointer, token);
114       return;
115     }
116   }
117   NOTREACHED();
118 }
119 
FreeUnused()120 void MappedMemoryManager::FreeUnused() {
121   CommandBuffer* cmd_buf = helper_->command_buffer();
122   MemoryChunkVector::iterator iter = chunks_.begin();
123   while (iter != chunks_.end()) {
124     MemoryChunk* chunk = *iter;
125     chunk->FreeUnused();
126     if (!chunk->InUse()) {
127       cmd_buf->DestroyTransferBuffer(chunk->shm_id());
128       allocated_memory_ -= chunk->GetSize();
129       iter = chunks_.erase(iter);
130     } else {
131       ++iter;
132     }
133   }
134 }
135 
136 }  // namespace gpu
137