• 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,scoped_refptr<gpu::Buffer> shm,CommandBufferHelper * helper,const base::Closure & poll_callback)16 MemoryChunk::MemoryChunk(int32 shm_id,
17                          scoped_refptr<gpu::Buffer> shm,
18                          CommandBufferHelper* helper,
19                          const base::Closure& poll_callback)
20     : shm_id_(shm_id),
21       shm_(shm),
22       allocator_(shm->size(), helper, poll_callback, shm->memory()) {}
23 
~MemoryChunk()24 MemoryChunk::~MemoryChunk() {}
25 
MappedMemoryManager(CommandBufferHelper * helper,const base::Closure & poll_callback,size_t unused_memory_reclaim_limit)26 MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper,
27                                          const base::Closure& poll_callback,
28                                          size_t unused_memory_reclaim_limit)
29     : chunk_size_multiple_(1),
30       helper_(helper),
31       poll_callback_(poll_callback),
32       allocated_memory_(0),
33       max_free_bytes_(unused_memory_reclaim_limit) {
34 }
35 
~MappedMemoryManager()36 MappedMemoryManager::~MappedMemoryManager() {
37   CommandBuffer* cmd_buf = helper_->command_buffer();
38   for (MemoryChunkVector::iterator iter = chunks_.begin();
39        iter != chunks_.end(); ++iter) {
40     MemoryChunk* chunk = *iter;
41     cmd_buf->DestroyTransferBuffer(chunk->shm_id());
42   }
43 }
44 
Alloc(unsigned int size,int32 * shm_id,unsigned int * shm_offset)45 void* MappedMemoryManager::Alloc(
46     unsigned int size, int32* shm_id, unsigned int* shm_offset) {
47   DCHECK(shm_id);
48   DCHECK(shm_offset);
49   if (size <= allocated_memory_) {
50     size_t total_bytes_in_use = 0;
51     // See if any of the chunks can satisfy this request.
52     for (size_t ii = 0; ii < chunks_.size(); ++ii) {
53       MemoryChunk* chunk = chunks_[ii];
54       chunk->FreeUnused();
55       total_bytes_in_use += chunk->bytes_in_use();
56       if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) {
57         void* mem = chunk->Alloc(size);
58         DCHECK(mem);
59         *shm_id = chunk->shm_id();
60         *shm_offset = chunk->GetOffset(mem);
61         return mem;
62       }
63     }
64 
65     // If there is a memory limit being enforced and total free
66     // memory (allocated_memory_ - total_bytes_in_use) is larger than
67     // the limit try waiting.
68     if (max_free_bytes_ != kNoLimit &&
69         (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) {
70       TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait");
71       for (size_t ii = 0; ii < chunks_.size(); ++ii) {
72         MemoryChunk* chunk = chunks_[ii];
73         if (chunk->GetLargestFreeSizeWithWaiting() >= size) {
74           void* mem = chunk->Alloc(size);
75           DCHECK(mem);
76           *shm_id = chunk->shm_id();
77           *shm_offset = chunk->GetOffset(mem);
78           return mem;
79         }
80       }
81     }
82   }
83 
84   // Make a new chunk to satisfy the request.
85   CommandBuffer* cmd_buf = helper_->command_buffer();
86   unsigned int chunk_size =
87       ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) *
88       chunk_size_multiple_;
89   int32 id = -1;
90   scoped_refptr<gpu::Buffer> shm =
91       cmd_buf->CreateTransferBuffer(chunk_size, &id);
92   if (id  < 0)
93     return NULL;
94   DCHECK(shm);
95   MemoryChunk* mc = new MemoryChunk(id, shm, helper_, poll_callback_);
96   allocated_memory_ += mc->GetSize();
97   chunks_.push_back(mc);
98   void* mem = mc->Alloc(size);
99   DCHECK(mem);
100   *shm_id = mc->shm_id();
101   *shm_offset = mc->GetOffset(mem);
102   return mem;
103 }
104 
Free(void * pointer)105 void MappedMemoryManager::Free(void* pointer) {
106   for (size_t ii = 0; ii < chunks_.size(); ++ii) {
107     MemoryChunk* chunk = chunks_[ii];
108     if (chunk->IsInChunk(pointer)) {
109       chunk->Free(pointer);
110       return;
111     }
112   }
113   NOTREACHED();
114 }
115 
FreePendingToken(void * pointer,int32 token)116 void MappedMemoryManager::FreePendingToken(void* pointer, int32 token) {
117   for (size_t ii = 0; ii < chunks_.size(); ++ii) {
118     MemoryChunk* chunk = chunks_[ii];
119     if (chunk->IsInChunk(pointer)) {
120       chunk->FreePendingToken(pointer, token);
121       return;
122     }
123   }
124   NOTREACHED();
125 }
126 
FreeUnused()127 void MappedMemoryManager::FreeUnused() {
128   CommandBuffer* cmd_buf = helper_->command_buffer();
129   MemoryChunkVector::iterator iter = chunks_.begin();
130   while (iter != chunks_.end()) {
131     MemoryChunk* chunk = *iter;
132     chunk->FreeUnused();
133     if (!chunk->InUse()) {
134       cmd_buf->DestroyTransferBuffer(chunk->shm_id());
135       allocated_memory_ -= chunk->GetSize();
136       iter = chunks_.erase(iter);
137     } else {
138       ++iter;
139     }
140   }
141 }
142 
143 }  // namespace gpu
144