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"
16 class BitmapData
: public base::RefCountedThreadSafe
<BitmapData
> {
18 BitmapData(base::ProcessHandle process_handle
,
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
;
28 friend class base::RefCountedThreadSafe
<BitmapData
>;
30 DISALLOW_COPY_AND_ASSIGN(BitmapData
);
35 class HostSharedBitmap
: public cc::SharedBitmap
{
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
),
45 ~HostSharedBitmap() override
{
47 manager_
->FreeSharedMemoryFromMap(id());
51 scoped_refptr
<BitmapData
> bitmap_data_
;
52 HostSharedBitmapManager
* manager_
;
55 const char kMemoryAllocatorName
[] = "sharedbitmap";
59 base::LazyInstance
<HostSharedBitmapManager
> g_shared_memory_manager
=
60 LAZY_INSTANCE_INITIALIZER
;
62 HostSharedBitmapManagerClient::HostSharedBitmapManagerClient(
63 HostSharedBitmapManager
* manager
)
67 HostSharedBitmapManagerClient::~HostSharedBitmapManagerClient() {
68 for (const auto& id
: owned_bitmaps_
)
69 manager_
->ChildDeletedSharedBitmap(id
);
72 void HostSharedBitmapManagerClient::AllocateSharedBitmapForChild(
73 base::ProcessHandle process_handle
,
75 const cc::SharedBitmapId
& id
,
76 base::SharedMemoryHandle
* shared_memory_handle
) {
77 manager_
->AllocateSharedBitmapForChild(process_handle
, buffer_size
, id
,
78 shared_memory_handle
);
79 owned_bitmaps_
.insert(id
);
82 void HostSharedBitmapManagerClient::ChildAllocatedSharedBitmap(
84 const base::SharedMemoryHandle
& handle
,
85 base::ProcessHandle process_handle
,
86 const cc::SharedBitmapId
& id
) {
87 manager_
->ChildAllocatedSharedBitmap(buffer_size
, handle
, process_handle
, id
);
88 owned_bitmaps_
.insert(id
);
91 void HostSharedBitmapManagerClient::ChildDeletedSharedBitmap(
92 const cc::SharedBitmapId
& id
) {
93 manager_
->ChildDeletedSharedBitmap(id
);
94 owned_bitmaps_
.erase(id
);
97 HostSharedBitmapManager::HostSharedBitmapManager() {}
98 HostSharedBitmapManager::~HostSharedBitmapManager() {
99 DCHECK(handle_map_
.empty());
102 HostSharedBitmapManager
* HostSharedBitmapManager::current() {
103 return g_shared_memory_manager
.Pointer();
106 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::AllocateSharedBitmap(
107 const gfx::Size
& size
) {
108 base::AutoLock
lock(lock_
);
110 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
))
111 return scoped_ptr
<cc::SharedBitmap
>();
113 scoped_refptr
<BitmapData
> data(
114 new BitmapData(base::GetCurrentProcessHandle(),
116 // Bitmaps allocated in host don't need to be shared to other processes, so
117 // allocate them with new instead.
118 data
->pixels
= scoped_ptr
<uint8
[]>(new uint8
[bitmap_size
]);
120 cc::SharedBitmapId id
= cc::SharedBitmap::GenerateId();
121 handle_map_
[id
] = data
;
122 return make_scoped_ptr(
123 new HostSharedBitmap(data
->pixels
.get(), data
, id
, this));
126 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::GetSharedBitmapFromId(
127 const gfx::Size
& size
,
128 const cc::SharedBitmapId
& id
) {
129 base::AutoLock
lock(lock_
);
130 BitmapMap::iterator it
= handle_map_
.find(id
);
131 if (it
== handle_map_
.end())
132 return scoped_ptr
<cc::SharedBitmap
>();
134 BitmapData
* data
= it
->second
.get();
137 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
) ||
138 bitmap_size
> data
->buffer_size
)
139 return scoped_ptr
<cc::SharedBitmap
>();
142 return make_scoped_ptr(
143 new HostSharedBitmap(data
->pixels
.get(), data
, id
, nullptr));
145 if (!data
->memory
->memory()) {
146 return scoped_ptr
<cc::SharedBitmap
>();
149 return make_scoped_ptr(new HostSharedBitmap(
150 static_cast<uint8
*>(data
->memory
->memory()), data
, id
, nullptr));
153 bool HostSharedBitmapManager::OnMemoryDump(
154 base::trace_event::ProcessMemoryDump
* pmd
) {
155 base::AutoLock
lock(lock_
);
157 for (const auto& bitmap
: handle_map_
) {
158 base::trace_event::MemoryAllocatorDump
* dump
= pmd
->CreateAllocatorDump(
159 base::StringPrintf("%s/%s", kMemoryAllocatorName
,
160 base::HexEncode(bitmap
.first
.name
,
161 sizeof(bitmap
.first
.name
)).c_str()));
165 dump
->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize
,
166 base::trace_event::MemoryAllocatorDump::kUnitsBytes
,
167 bitmap
.second
->buffer_size
);
173 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
175 const base::SharedMemoryHandle
& handle
,
176 base::ProcessHandle process_handle
,
177 const cc::SharedBitmapId
& id
) {
178 base::AutoLock
lock(lock_
);
179 if (handle_map_
.find(id
) != handle_map_
.end())
181 scoped_refptr
<BitmapData
> data(
182 new BitmapData(process_handle
, buffer_size
));
184 handle_map_
[id
] = data
;
186 data
->memory
= make_scoped_ptr(
187 new base::SharedMemory(handle
, false, data
->process_handle
));
190 make_scoped_ptr(new base::SharedMemory(handle
, false));
192 data
->memory
->Map(data
->buffer_size
);
193 data
->memory
->Close();
196 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
197 base::ProcessHandle process_handle
,
199 const cc::SharedBitmapId
& id
,
200 base::SharedMemoryHandle
* shared_memory_handle
) {
201 base::AutoLock
lock(lock_
);
202 if (handle_map_
.find(id
) != handle_map_
.end()) {
203 *shared_memory_handle
= base::SharedMemory::NULLHandle();
206 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
207 if (!shared_memory
->CreateAndMapAnonymous(buffer_size
)) {
208 LOG(ERROR
) << "Cannot create shared memory buffer";
209 *shared_memory_handle
= base::SharedMemory::NULLHandle();
213 scoped_refptr
<BitmapData
> data(
214 new BitmapData(process_handle
, buffer_size
));
215 data
->memory
= shared_memory
.Pass();
217 handle_map_
[id
] = data
;
218 if (!data
->memory
->ShareToProcess(process_handle
, shared_memory_handle
)) {
219 LOG(ERROR
) << "Cannot share shared memory buffer";
220 *shared_memory_handle
= base::SharedMemory::NULLHandle();
223 data
->memory
->Close();
226 void HostSharedBitmapManager::ChildDeletedSharedBitmap(
227 const cc::SharedBitmapId
& id
) {
228 base::AutoLock
lock(lock_
);
229 handle_map_
.erase(id
);
232 size_t HostSharedBitmapManager::AllocatedBitmapCount() const {
233 base::AutoLock
lock(lock_
);
234 return handle_map_
.size();
237 void HostSharedBitmapManager::FreeSharedMemoryFromMap(
238 const cc::SharedBitmapId
& id
) {
239 base::AutoLock
lock(lock_
);
240 handle_map_
.erase(id
);
243 } // namespace content