root/gpu/command_buffer/client/mapped_memory.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. allocator_
  2. max_free_bytes_
  3. Alloc
  4. Free
  5. FreePendingToken
  6. FreeUnused

// Copyright (c) 2011 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.

#include "gpu/command_buffer/client/mapped_memory.h"

#include <algorithm>
#include <functional>

#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "gpu/command_buffer/client/cmd_buffer_helper.h"

namespace gpu {

MemoryChunk::MemoryChunk(int32 shm_id,
                         scoped_refptr<gpu::Buffer> shm,
                         CommandBufferHelper* helper,
                         const base::Closure& poll_callback)
    : shm_id_(shm_id),
      shm_(shm),
      allocator_(shm->size(), helper, poll_callback, shm->memory()) {}

MemoryChunk::~MemoryChunk() {}

MappedMemoryManager::MappedMemoryManager(CommandBufferHelper* helper,
                                         const base::Closure& poll_callback,
                                         size_t unused_memory_reclaim_limit)
    : chunk_size_multiple_(1),
      helper_(helper),
      poll_callback_(poll_callback),
      allocated_memory_(0),
      max_free_bytes_(unused_memory_reclaim_limit) {
}

MappedMemoryManager::~MappedMemoryManager() {
  CommandBuffer* cmd_buf = helper_->command_buffer();
  for (MemoryChunkVector::iterator iter = chunks_.begin();
       iter != chunks_.end(); ++iter) {
    MemoryChunk* chunk = *iter;
    cmd_buf->DestroyTransferBuffer(chunk->shm_id());
  }
}

void* MappedMemoryManager::Alloc(
    unsigned int size, int32* shm_id, unsigned int* shm_offset) {
  DCHECK(shm_id);
  DCHECK(shm_offset);
  if (size <= allocated_memory_) {
    size_t total_bytes_in_use = 0;
    // See if any of the chunks can satisfy this request.
    for (size_t ii = 0; ii < chunks_.size(); ++ii) {
      MemoryChunk* chunk = chunks_[ii];
      chunk->FreeUnused();
      total_bytes_in_use += chunk->bytes_in_use();
      if (chunk->GetLargestFreeSizeWithoutWaiting() >= size) {
        void* mem = chunk->Alloc(size);
        DCHECK(mem);
        *shm_id = chunk->shm_id();
        *shm_offset = chunk->GetOffset(mem);
        return mem;
      }
    }

    // If there is a memory limit being enforced and total free
    // memory (allocated_memory_ - total_bytes_in_use) is larger than
    // the limit try waiting.
    if (max_free_bytes_ != kNoLimit &&
        (allocated_memory_ - total_bytes_in_use) >= max_free_bytes_) {
      TRACE_EVENT0("gpu", "MappedMemoryManager::Alloc::wait");
      for (size_t ii = 0; ii < chunks_.size(); ++ii) {
        MemoryChunk* chunk = chunks_[ii];
        if (chunk->GetLargestFreeSizeWithWaiting() >= size) {
          void* mem = chunk->Alloc(size);
          DCHECK(mem);
          *shm_id = chunk->shm_id();
          *shm_offset = chunk->GetOffset(mem);
          return mem;
        }
      }
    }
  }

  // Make a new chunk to satisfy the request.
  CommandBuffer* cmd_buf = helper_->command_buffer();
  unsigned int chunk_size =
      ((size + chunk_size_multiple_ - 1) / chunk_size_multiple_) *
      chunk_size_multiple_;
  int32 id = -1;
  scoped_refptr<gpu::Buffer> shm =
      cmd_buf->CreateTransferBuffer(chunk_size, &id);
  if (id  < 0)
    return NULL;
  DCHECK(shm);
  MemoryChunk* mc = new MemoryChunk(id, shm, helper_, poll_callback_);
  allocated_memory_ += mc->GetSize();
  chunks_.push_back(mc);
  void* mem = mc->Alloc(size);
  DCHECK(mem);
  *shm_id = mc->shm_id();
  *shm_offset = mc->GetOffset(mem);
  return mem;
}

void MappedMemoryManager::Free(void* pointer) {
  for (size_t ii = 0; ii < chunks_.size(); ++ii) {
    MemoryChunk* chunk = chunks_[ii];
    if (chunk->IsInChunk(pointer)) {
      chunk->Free(pointer);
      return;
    }
  }
  NOTREACHED();
}

void MappedMemoryManager::FreePendingToken(void* pointer, int32 token) {
  for (size_t ii = 0; ii < chunks_.size(); ++ii) {
    MemoryChunk* chunk = chunks_[ii];
    if (chunk->IsInChunk(pointer)) {
      chunk->FreePendingToken(pointer, token);
      return;
    }
  }
  NOTREACHED();
}

void MappedMemoryManager::FreeUnused() {
  CommandBuffer* cmd_buf = helper_->command_buffer();
  MemoryChunkVector::iterator iter = chunks_.begin();
  while (iter != chunks_.end()) {
    MemoryChunk* chunk = *iter;
    chunk->FreeUnused();
    if (!chunk->InUse()) {
      cmd_buf->DestroyTransferBuffer(chunk->shm_id());
      allocated_memory_ -= chunk->GetSize();
      iter = chunks_.erase(iter);
    } else {
      ++iter;
    }
  }
}

}  // namespace gpu

/* [<][>][^][v][top][bottom][index][help] */