mapped_memory.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 "gpu/command_buffer/client/cmd_buffer_helper.h"
11
12namespace gpu {
13
14MemoryChunk::MemoryChunk(
15    int32 shm_id, gpu::Buffer shm, CommandBufferHelper* helper)
16    : shm_id_(shm_id),
17      shm_(shm),
18      allocator_(shm.size, helper, shm.ptr) {
19}
20
21MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper)
22    : chunk_size_multiple_(1),
23      helper_(helper) {
24}
25
26MappedMemoryManager::~MappedMemoryManager() {
27  CommandBuffer* cmd_buf = helper_->command_buffer();
28  for (MemoryChunkVector::iterator iter = chunks_.begin();
29       iter != chunks_.end(); ++iter) {
30    MemoryChunk* chunk = *iter;
31    cmd_buf->DestroyTransferBuffer(chunk->shm_id());
32    delete chunk;
33  }
34}
35
36void* MappedMemoryManager::Alloc(
37    unsigned int size, int32* shm_id, unsigned int* shm_offset) {
38  GPU_DCHECK(shm_id);
39  GPU_DCHECK(shm_offset);
40  // See if any of the chucks can satisfy this request.
41  for (size_t ii = 0; ii < chunks_.size(); ++ii) {
42    MemoryChunk* chunk = chunks_[ii];
43    chunk->FreeUnused();
44    if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) {
45      void* mem = chunk->Alloc(size);
46      GPU_DCHECK(mem);
47      *shm_id = chunk->shm_id();
48      *shm_offset = chunk->GetOffset(mem);
49      return mem;
50    }
51  }
52
53  // Make a new chunk to satisfy the request.
54  CommandBuffer* cmd_buf = helper_->command_buffer();
55  unsigned int chunk_size =
56      ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) *
57      chunk_size_multiple_;
58  int32 id = -1;
59  gpu::Buffer shm = cmd_buf->CreateTransferBuffer(chunk_size, &id);
60  if (id  < 0)
61    return NULL;
62  MemoryChunk* mc = new MemoryChunk(id, shm, helper_);
63  chunks_.push_back(mc);
64  void* mem = mc->Alloc(size);
65  GPU_DCHECK(mem);
66  *shm_id = mc->shm_id();
67  *shm_offset = mc->GetOffset(mem);
68  return mem;
69}
70
71void MappedMemoryManager::Free(void* pointer) {
72  for (size_t ii = 0; ii < chunks_.size(); ++ii) {
73    MemoryChunk* chunk = chunks_[ii];
74    if (chunk->IsInChunk(pointer)) {
75      chunk->Free(pointer);
76      return;
77    }
78  }
79  GPU_NOTREACHED();
80}
81
82void MappedMemoryManager::FreePendingToken(void* pointer, int32 token) {
83  for (size_t ii = 0; ii < chunks_.size(); ++ii) {
84    MemoryChunk* chunk = chunks_[ii];
85    if (chunk->IsInChunk(pointer)) {
86      chunk->FreePendingToken(pointer, token);
87      return;
88    }
89  }
90  GPU_NOTREACHED();
91}
92
93void MappedMemoryManager::FreeUnused() {
94  CommandBuffer* cmd_buf = helper_->command_buffer();
95  MemoryChunkVector::iterator iter = chunks_.begin();
96  while (iter != chunks_.end()) {
97    MemoryChunk* chunk = *iter;
98    chunk->FreeUnused();
99    if (!chunk->InUse()) {
100      cmd_buf->DestroyTransferBuffer(chunk->shm_id());
101      iter = chunks_.erase(iter);
102    } else {
103      ++iter;
104    }
105  }
106}
107
108}  // namespace gpu
109
110
111
112