summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/transfer_buffer_manager.cc
blob: 76443a1f2500022dd797f8847b4997b1a36fdbe9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 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.

#include "gpu/command_buffer/service/transfer_buffer_manager.h"

#include <limits>

#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/debug/trace_event.h"
#include "base/process/process_handle.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"

using ::base::SharedMemory;

namespace gpu {

TransferBufferManagerInterface::~TransferBufferManagerInterface() {
}

TransferBufferManager::TransferBufferManager()
    : shared_memory_bytes_allocated_(0) {
}

TransferBufferManager::~TransferBufferManager() {
  while (!registered_buffers_.empty()) {
    BufferMap::iterator it = registered_buffers_.begin();
    DCHECK(shared_memory_bytes_allocated_ >= it->second.size);
    shared_memory_bytes_allocated_ -= it->second.size;
    delete it->second.shared_memory;
    registered_buffers_.erase(it);
  }
  DCHECK(!shared_memory_bytes_allocated_);
}

bool TransferBufferManager::Initialize() {
  return true;
}

bool TransferBufferManager::RegisterTransferBuffer(
    int32 id,
    base::SharedMemory* shared_memory,
    size_t size) {
  if (id <= 0) {
    DVLOG(0) << "Cannot register transfer buffer with non-positive ID.";
    return false;
  }

  // Fail if the ID is in use.
  if (registered_buffers_.find(id) != registered_buffers_.end()) {
    DVLOG(0) << "Buffer ID already in use.";
    return false;
  }

  // Duplicate the handle.
  base::SharedMemoryHandle duped_shared_memory_handle;
  if (!shared_memory->ShareToProcess(base::GetCurrentProcessHandle(),
                                     &duped_shared_memory_handle)) {
    DVLOG(0) << "Failed to duplicate shared memory handle.";
    return false;
  }
  scoped_ptr<SharedMemory> duped_shared_memory(
      new SharedMemory(duped_shared_memory_handle, false));

  // Map the shared memory into this process. This validates the size.
  if (!duped_shared_memory->Map(size)) {
    DVLOG(0) << "Failed to map shared memory.";
    return false;
  }

  // If it could be mapped register the shared memory with the ID.
  Buffer buffer;
  buffer.ptr = duped_shared_memory->memory();
  buffer.size = size;
  buffer.shared_memory = duped_shared_memory.release();

  shared_memory_bytes_allocated_ += size;
  TRACE_COUNTER_ID1(
      "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_);

  registered_buffers_[id] = buffer;

  return true;
}

void TransferBufferManager::DestroyTransferBuffer(int32 id) {
  BufferMap::iterator it = registered_buffers_.find(id);
  if (it == registered_buffers_.end()) {
    DVLOG(0) << "Transfer buffer ID was not registered.";
    return;
  }

  DCHECK(shared_memory_bytes_allocated_ >= it->second.size);
  shared_memory_bytes_allocated_ -= it->second.size;
  TRACE_COUNTER_ID1(
      "gpu", "GpuTransferBufferMemory", this, shared_memory_bytes_allocated_);

  delete it->second.shared_memory;
  registered_buffers_.erase(it);
}

Buffer TransferBufferManager::GetTransferBuffer(int32 id) {
  if (id == 0)
    return Buffer();

  BufferMap::iterator it = registered_buffers_.find(id);
  if (it == registered_buffers_.end())
    return Buffer();

  return it->second;
}

}  // namespace gpu