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_
;
57 base::LazyInstance
<HostSharedBitmapManager
> g_shared_memory_manager
=
58 LAZY_INSTANCE_INITIALIZER
;
60 HostSharedBitmapManagerClient::HostSharedBitmapManagerClient(
61 HostSharedBitmapManager
* manager
)
65 HostSharedBitmapManagerClient::~HostSharedBitmapManagerClient() {
66 for (const auto& id
: owned_bitmaps_
)
67 manager_
->ChildDeletedSharedBitmap(id
);
70 void HostSharedBitmapManagerClient::AllocateSharedBitmapForChild(
71 base::ProcessHandle process_handle
,
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(
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_
);
108 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
))
109 return scoped_ptr
<cc::SharedBitmap
>();
111 scoped_refptr
<BitmapData
> data(
112 new BitmapData(base::GetCurrentProcessHandle(),
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();
135 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
) ||
136 bitmap_size
> data
->buffer_size
)
137 return scoped_ptr
<cc::SharedBitmap
>();
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(
160 base::HexEncode(bitmap
.first
.name
, sizeof(bitmap
.first
.name
))
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
171 auto guid
= cc::GetSharedBitmapGUIDForTracing(bitmap
.first
);
172 pmd
->CreateSharedGlobalAllocatorDump(guid
);
173 pmd
->AddOwnershipEdge(dump
->guid(), guid
);
179 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
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())
187 scoped_refptr
<BitmapData
> data(
188 new BitmapData(process_handle
, buffer_size
));
190 handle_map_
[id
] = data
;
192 data
->memory
= make_scoped_ptr(
193 new base::SharedMemory(handle
, false, data
->process_handle
));
196 make_scoped_ptr(new base::SharedMemory(handle
, false));
198 data
->memory
->Map(data
->buffer_size
);
199 data
->memory
->Close();
202 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
203 base::ProcessHandle process_handle
,
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();
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();
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();
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