Add ICU message format support
[chromium-blink-merge.git] / content / common / host_shared_bitmap_manager.cc
blobf913dba71bf0b5b31916fed5e5e431846837a4ac
1 // Copyright 2013 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.
5 #include "content/common/host_shared_bitmap_manager.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "base/trace_event/process_memory_dump.h"
11 #include "content/common/view_messages.h"
12 #include "ui/gfx/geometry/size.h"
14 namespace content {
16 class BitmapData : public base::RefCountedThreadSafe<BitmapData> {
17 public:
18 BitmapData(base::ProcessHandle process_handle,
19 size_t buffer_size)
20 : process_handle(process_handle),
21 buffer_size(buffer_size) {}
22 base::ProcessHandle process_handle;
23 scoped_ptr<base::SharedMemory> memory;
24 scoped_ptr<uint8[]> pixels;
25 size_t buffer_size;
27 private:
28 friend class base::RefCountedThreadSafe<BitmapData>;
29 ~BitmapData() {}
30 DISALLOW_COPY_AND_ASSIGN(BitmapData);
33 namespace {
35 class HostSharedBitmap : public cc::SharedBitmap {
36 public:
37 HostSharedBitmap(uint8* pixels,
38 scoped_refptr<BitmapData> bitmap_data,
39 const cc::SharedBitmapId& id,
40 HostSharedBitmapManager* manager)
41 : SharedBitmap(pixels, id),
42 bitmap_data_(bitmap_data),
43 manager_(manager) {}
45 ~HostSharedBitmap() override {
46 if (manager_)
47 manager_->FreeSharedMemoryFromMap(id());
50 private:
51 scoped_refptr<BitmapData> bitmap_data_;
52 HostSharedBitmapManager* manager_;
55 } // namespace
57 base::LazyInstance<HostSharedBitmapManager> g_shared_memory_manager =
58 LAZY_INSTANCE_INITIALIZER;
60 HostSharedBitmapManagerClient::HostSharedBitmapManagerClient(
61 HostSharedBitmapManager* manager)
62 : manager_(manager) {
65 HostSharedBitmapManagerClient::~HostSharedBitmapManagerClient() {
66 for (const auto& id : owned_bitmaps_)
67 manager_->ChildDeletedSharedBitmap(id);
70 void HostSharedBitmapManagerClient::AllocateSharedBitmapForChild(
71 base::ProcessHandle process_handle,
72 size_t buffer_size,
73 const cc::SharedBitmapId& id,
74 base::SharedMemoryHandle* shared_memory_handle) {
75 manager_->AllocateSharedBitmapForChild(process_handle, buffer_size, id,
76 shared_memory_handle);
77 owned_bitmaps_.insert(id);
80 void HostSharedBitmapManagerClient::ChildAllocatedSharedBitmap(
81 size_t buffer_size,
82 const base::SharedMemoryHandle& handle,
83 base::ProcessHandle process_handle,
84 const cc::SharedBitmapId& id) {
85 manager_->ChildAllocatedSharedBitmap(buffer_size, handle, process_handle, id);
86 owned_bitmaps_.insert(id);
89 void HostSharedBitmapManagerClient::ChildDeletedSharedBitmap(
90 const cc::SharedBitmapId& id) {
91 manager_->ChildDeletedSharedBitmap(id);
92 owned_bitmaps_.erase(id);
95 HostSharedBitmapManager::HostSharedBitmapManager() {}
96 HostSharedBitmapManager::~HostSharedBitmapManager() {
97 DCHECK(handle_map_.empty());
100 HostSharedBitmapManager* HostSharedBitmapManager::current() {
101 return g_shared_memory_manager.Pointer();
104 scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::AllocateSharedBitmap(
105 const gfx::Size& size) {
106 base::AutoLock lock(lock_);
107 size_t bitmap_size;
108 if (!cc::SharedBitmap::SizeInBytes(size, &bitmap_size))
109 return scoped_ptr<cc::SharedBitmap>();
111 scoped_refptr<BitmapData> data(
112 new BitmapData(base::GetCurrentProcessHandle(),
113 bitmap_size));
114 // Bitmaps allocated in host don't need to be shared to other processes, so
115 // allocate them with new instead.
116 data->pixels = scoped_ptr<uint8[]>(new uint8[bitmap_size]);
118 cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
119 handle_map_[id] = data;
120 return make_scoped_ptr(
121 new HostSharedBitmap(data->pixels.get(), data, id, this));
124 scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::GetSharedBitmapFromId(
125 const gfx::Size& size,
126 const cc::SharedBitmapId& id) {
127 base::AutoLock lock(lock_);
128 BitmapMap::iterator it = handle_map_.find(id);
129 if (it == handle_map_.end())
130 return scoped_ptr<cc::SharedBitmap>();
132 BitmapData* data = it->second.get();
134 size_t bitmap_size;
135 if (!cc::SharedBitmap::SizeInBytes(size, &bitmap_size) ||
136 bitmap_size > data->buffer_size)
137 return scoped_ptr<cc::SharedBitmap>();
139 if (data->pixels) {
140 return make_scoped_ptr(
141 new HostSharedBitmap(data->pixels.get(), data, id, nullptr));
143 if (!data->memory->memory()) {
144 return scoped_ptr<cc::SharedBitmap>();
147 return make_scoped_ptr(new HostSharedBitmap(
148 static_cast<uint8*>(data->memory->memory()), data, id, nullptr));
151 bool HostSharedBitmapManager::OnMemoryDump(
152 const base::trace_event::MemoryDumpArgs& args,
153 base::trace_event::ProcessMemoryDump* pmd) {
154 base::AutoLock lock(lock_);
156 for (const auto& bitmap : handle_map_) {
157 base::trace_event::MemoryAllocatorDump* dump =
158 pmd->CreateAllocatorDump(base::StringPrintf(
159 "sharedbitmap/%s",
160 base::HexEncode(bitmap.first.name, sizeof(bitmap.first.name))
161 .c_str()));
162 if (!dump)
163 return false;
165 dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
166 base::trace_event::MemoryAllocatorDump::kUnitsBytes,
167 bitmap.second->buffer_size);
169 // Generate a global GUID used to share this allocation with renderer
170 // processes.
171 auto guid = cc::GetSharedBitmapGUIDForTracing(bitmap.first);
172 pmd->CreateSharedGlobalAllocatorDump(guid);
173 pmd->AddOwnershipEdge(dump->guid(), guid);
176 return true;
179 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
180 size_t buffer_size,
181 const base::SharedMemoryHandle& handle,
182 base::ProcessHandle process_handle,
183 const cc::SharedBitmapId& id) {
184 base::AutoLock lock(lock_);
185 if (handle_map_.find(id) != handle_map_.end())
186 return;
187 scoped_refptr<BitmapData> data(
188 new BitmapData(process_handle, buffer_size));
190 handle_map_[id] = data;
191 #if defined(OS_WIN)
192 data->memory = make_scoped_ptr(
193 new base::SharedMemory(handle, false, data->process_handle));
194 #else
195 data->memory =
196 make_scoped_ptr(new base::SharedMemory(handle, false));
197 #endif
198 data->memory->Map(data->buffer_size);
199 data->memory->Close();
202 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
203 base::ProcessHandle process_handle,
204 size_t buffer_size,
205 const cc::SharedBitmapId& id,
206 base::SharedMemoryHandle* shared_memory_handle) {
207 base::AutoLock lock(lock_);
208 if (handle_map_.find(id) != handle_map_.end()) {
209 *shared_memory_handle = base::SharedMemory::NULLHandle();
210 return;
212 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory);
213 if (!shared_memory->CreateAndMapAnonymous(buffer_size)) {
214 LOG(ERROR) << "Cannot create shared memory buffer";
215 *shared_memory_handle = base::SharedMemory::NULLHandle();
216 return;
219 scoped_refptr<BitmapData> data(
220 new BitmapData(process_handle, buffer_size));
221 data->memory = shared_memory.Pass();
223 handle_map_[id] = data;
224 if (!data->memory->ShareToProcess(process_handle, shared_memory_handle)) {
225 LOG(ERROR) << "Cannot share shared memory buffer";
226 *shared_memory_handle = base::SharedMemory::NULLHandle();
227 return;
229 data->memory->Close();
232 void HostSharedBitmapManager::ChildDeletedSharedBitmap(
233 const cc::SharedBitmapId& id) {
234 base::AutoLock lock(lock_);
235 handle_map_.erase(id);
238 size_t HostSharedBitmapManager::AllocatedBitmapCount() const {
239 base::AutoLock lock(lock_);
240 return handle_map_.size();
243 void HostSharedBitmapManager::FreeSharedMemoryFromMap(
244 const cc::SharedBitmapId& id) {
245 base::AutoLock lock(lock_);
246 handle_map_.erase(id);
249 } // namespace content