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 "content/common/view_messages.h"
10 #include "ui/gfx/geometry/size.h"
14 class BitmapData
: public base::RefCountedThreadSafe
<BitmapData
> {
16 BitmapData(base::ProcessHandle process_handle
,
18 : process_handle(process_handle
),
19 buffer_size(buffer_size
) {}
20 base::ProcessHandle process_handle
;
21 scoped_ptr
<base::SharedMemory
> memory
;
22 scoped_ptr
<uint8
[]> pixels
;
26 friend class base::RefCountedThreadSafe
<BitmapData
>;
28 DISALLOW_COPY_AND_ASSIGN(BitmapData
);
33 class HostSharedBitmap
: public cc::SharedBitmap
{
35 HostSharedBitmap(uint8
* pixels
,
36 scoped_refptr
<BitmapData
> bitmap_data
,
37 const cc::SharedBitmapId
& id
,
38 HostSharedBitmapManager
* manager
)
39 : SharedBitmap(pixels
, id
),
40 bitmap_data_(bitmap_data
),
43 ~HostSharedBitmap() override
{
45 manager_
->FreeSharedMemoryFromMap(id());
49 scoped_refptr
<BitmapData
> bitmap_data_
;
50 HostSharedBitmapManager
* manager_
;
55 base::LazyInstance
<HostSharedBitmapManager
> g_shared_memory_manager
=
56 LAZY_INSTANCE_INITIALIZER
;
58 HostSharedBitmapManagerClient::HostSharedBitmapManagerClient(
59 HostSharedBitmapManager
* manager
)
63 HostSharedBitmapManagerClient::~HostSharedBitmapManagerClient() {
64 for (const auto& id
: owned_bitmaps_
)
65 manager_
->ChildDeletedSharedBitmap(id
);
68 void HostSharedBitmapManagerClient::AllocateSharedBitmapForChild(
69 base::ProcessHandle process_handle
,
71 const cc::SharedBitmapId
& id
,
72 base::SharedMemoryHandle
* shared_memory_handle
) {
73 manager_
->AllocateSharedBitmapForChild(process_handle
, buffer_size
, id
,
74 shared_memory_handle
);
75 owned_bitmaps_
.insert(id
);
78 void HostSharedBitmapManagerClient::ChildAllocatedSharedBitmap(
80 const base::SharedMemoryHandle
& handle
,
81 base::ProcessHandle process_handle
,
82 const cc::SharedBitmapId
& id
) {
83 manager_
->ChildAllocatedSharedBitmap(buffer_size
, handle
, process_handle
, id
);
84 owned_bitmaps_
.insert(id
);
87 void HostSharedBitmapManagerClient::ChildDeletedSharedBitmap(
88 const cc::SharedBitmapId
& id
) {
89 manager_
->ChildDeletedSharedBitmap(id
);
90 owned_bitmaps_
.erase(id
);
93 HostSharedBitmapManager::HostSharedBitmapManager() {}
94 HostSharedBitmapManager::~HostSharedBitmapManager() {
95 DCHECK(handle_map_
.empty());
98 HostSharedBitmapManager
* HostSharedBitmapManager::current() {
99 return g_shared_memory_manager
.Pointer();
102 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::AllocateSharedBitmap(
103 const gfx::Size
& size
) {
104 base::AutoLock
lock(lock_
);
106 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
))
107 return scoped_ptr
<cc::SharedBitmap
>();
109 scoped_refptr
<BitmapData
> data(
110 new BitmapData(base::GetCurrentProcessHandle(),
112 // Bitmaps allocated in host don't need to be shared to other processes, so
113 // allocate them with new instead.
114 data
->pixels
= scoped_ptr
<uint8
[]>(new uint8
[bitmap_size
]);
116 cc::SharedBitmapId id
= cc::SharedBitmap::GenerateId();
117 handle_map_
[id
] = data
;
118 return make_scoped_ptr(
119 new HostSharedBitmap(data
->pixels
.get(), data
, id
, this));
122 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::GetSharedBitmapFromId(
123 const gfx::Size
& size
,
124 const cc::SharedBitmapId
& id
) {
125 base::AutoLock
lock(lock_
);
126 BitmapMap::iterator it
= handle_map_
.find(id
);
127 if (it
== handle_map_
.end())
128 return scoped_ptr
<cc::SharedBitmap
>();
130 BitmapData
* data
= it
->second
.get();
133 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
) ||
134 bitmap_size
> data
->buffer_size
)
135 return scoped_ptr
<cc::SharedBitmap
>();
138 return make_scoped_ptr(
139 new HostSharedBitmap(data
->pixels
.get(), data
, id
, nullptr));
141 if (!data
->memory
->memory()) {
142 return scoped_ptr
<cc::SharedBitmap
>();
145 return make_scoped_ptr(new HostSharedBitmap(
146 static_cast<uint8
*>(data
->memory
->memory()), data
, id
, nullptr));
149 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
151 const base::SharedMemoryHandle
& handle
,
152 base::ProcessHandle process_handle
,
153 const cc::SharedBitmapId
& id
) {
154 base::AutoLock
lock(lock_
);
155 if (handle_map_
.find(id
) != handle_map_
.end())
157 scoped_refptr
<BitmapData
> data(
158 new BitmapData(process_handle
, buffer_size
));
160 handle_map_
[id
] = data
;
162 data
->memory
= make_scoped_ptr(
163 new base::SharedMemory(handle
, false, data
->process_handle
));
166 make_scoped_ptr(new base::SharedMemory(handle
, false));
168 data
->memory
->Map(data
->buffer_size
);
169 data
->memory
->Close();
172 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
173 base::ProcessHandle process_handle
,
175 const cc::SharedBitmapId
& id
,
176 base::SharedMemoryHandle
* shared_memory_handle
) {
177 base::AutoLock
lock(lock_
);
178 if (handle_map_
.find(id
) != handle_map_
.end()) {
179 *shared_memory_handle
= base::SharedMemory::NULLHandle();
182 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
183 if (!shared_memory
->CreateAndMapAnonymous(buffer_size
)) {
184 LOG(ERROR
) << "Cannot create shared memory buffer";
185 *shared_memory_handle
= base::SharedMemory::NULLHandle();
189 scoped_refptr
<BitmapData
> data(
190 new BitmapData(process_handle
, buffer_size
));
191 data
->memory
= shared_memory
.Pass();
193 handle_map_
[id
] = data
;
194 if (!data
->memory
->ShareToProcess(process_handle
, shared_memory_handle
)) {
195 LOG(ERROR
) << "Cannot share shared memory buffer";
196 *shared_memory_handle
= base::SharedMemory::NULLHandle();
199 data
->memory
->Close();
202 void HostSharedBitmapManager::ChildDeletedSharedBitmap(
203 const cc::SharedBitmapId
& id
) {
204 base::AutoLock
lock(lock_
);
205 handle_map_
.erase(id
);
208 size_t HostSharedBitmapManager::AllocatedBitmapCount() const {
209 base::AutoLock
lock(lock_
);
210 return handle_map_
.size();
213 void HostSharedBitmapManager::FreeSharedMemoryFromMap(
214 const cc::SharedBitmapId
& id
) {
215 base::AutoLock
lock(lock_
);
216 handle_map_
.erase(id
);
219 } // namespace content