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/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());
48 base::SharedMemory
* memory() override
{ return bitmap_data_
->memory
.get(); }
51 scoped_refptr
<BitmapData
> bitmap_data_
;
52 HostSharedBitmapManager
* manager_
;
57 base::LazyInstance
<HostSharedBitmapManager
> g_shared_memory_manager
=
58 LAZY_INSTANCE_INITIALIZER
;
60 HostSharedBitmapManager::HostSharedBitmapManager() {}
61 HostSharedBitmapManager::~HostSharedBitmapManager() {
62 DCHECK(handle_map_
.empty());
65 HostSharedBitmapManager
* HostSharedBitmapManager::current() {
66 return g_shared_memory_manager
.Pointer();
69 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::AllocateSharedBitmap(
70 const gfx::Size
& size
) {
71 base::AutoLock
lock(lock_
);
73 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
))
74 return scoped_ptr
<cc::SharedBitmap
>();
76 scoped_refptr
<BitmapData
> data(
77 new BitmapData(base::GetCurrentProcessHandle(),
79 // Bitmaps allocated in host don't need to be shared to other processes, so
80 // allocate them with new instead.
81 data
->pixels
= scoped_ptr
<uint8
[]>(new uint8
[bitmap_size
]);
83 cc::SharedBitmapId id
= cc::SharedBitmap::GenerateId();
84 handle_map_
[id
] = data
;
85 return make_scoped_ptr(
86 new HostSharedBitmap(data
->pixels
.get(), data
, id
, this));
89 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::GetSharedBitmapFromId(
90 const gfx::Size
& size
,
91 const cc::SharedBitmapId
& id
) {
92 base::AutoLock
lock(lock_
);
93 BitmapMap::iterator it
= handle_map_
.find(id
);
94 if (it
== handle_map_
.end())
95 return scoped_ptr
<cc::SharedBitmap
>();
97 BitmapData
* data
= it
->second
.get();
100 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
) ||
101 bitmap_size
> data
->buffer_size
)
102 return scoped_ptr
<cc::SharedBitmap
>();
105 return make_scoped_ptr(
106 new HostSharedBitmap(data
->pixels
.get(), data
, id
, nullptr));
108 if (!data
->memory
->memory()) {
109 return scoped_ptr
<cc::SharedBitmap
>();
112 return make_scoped_ptr(new HostSharedBitmap(
113 static_cast<uint8
*>(data
->memory
->memory()), data
, id
, nullptr));
116 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::GetBitmapForSharedMemory(
117 base::SharedMemory
*) {
118 return scoped_ptr
<cc::SharedBitmap
>();
121 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
123 const base::SharedMemoryHandle
& handle
,
124 base::ProcessHandle process_handle
,
125 const cc::SharedBitmapId
& id
) {
126 base::AutoLock
lock(lock_
);
127 if (handle_map_
.find(id
) != handle_map_
.end())
129 scoped_refptr
<BitmapData
> data(
130 new BitmapData(process_handle
, buffer_size
));
132 handle_map_
[id
] = data
;
133 process_map_
[process_handle
].insert(id
);
135 data
->memory
= make_scoped_ptr(
136 new base::SharedMemory(handle
, false, data
->process_handle
));
139 make_scoped_ptr(new base::SharedMemory(handle
, false));
141 data
->memory
->Map(data
->buffer_size
);
142 data
->memory
->Close();
145 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
146 base::ProcessHandle process_handle
,
148 const cc::SharedBitmapId
& id
,
149 base::SharedMemoryHandle
* shared_memory_handle
) {
150 base::AutoLock
lock(lock_
);
151 if (handle_map_
.find(id
) != handle_map_
.end()) {
152 *shared_memory_handle
= base::SharedMemory::NULLHandle();
155 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
156 if (!shared_memory
->CreateAndMapAnonymous(buffer_size
)) {
157 LOG(ERROR
) << "Cannot create shared memory buffer";
158 *shared_memory_handle
= base::SharedMemory::NULLHandle();
162 scoped_refptr
<BitmapData
> data(
163 new BitmapData(process_handle
, buffer_size
));
164 data
->memory
= shared_memory
.Pass();
166 handle_map_
[id
] = data
;
167 process_map_
[process_handle
].insert(id
);
168 if (!data
->memory
->ShareToProcess(process_handle
, shared_memory_handle
)) {
169 LOG(ERROR
) << "Cannot share shared memory buffer";
170 *shared_memory_handle
= base::SharedMemory::NULLHandle();
173 data
->memory
->Close();
176 void HostSharedBitmapManager::ChildDeletedSharedBitmap(
177 const cc::SharedBitmapId
& id
) {
178 base::AutoLock
lock(lock_
);
179 BitmapMap::iterator it
= handle_map_
.find(id
);
180 if (it
== handle_map_
.end())
182 base::hash_set
<cc::SharedBitmapId
>& res
=
183 process_map_
[it
->second
->process_handle
];
185 handle_map_
.erase(it
);
188 void HostSharedBitmapManager::ProcessRemoved(
189 base::ProcessHandle process_handle
) {
190 base::AutoLock
lock(lock_
);
191 ProcessMap::iterator proc_it
= process_map_
.find(process_handle
);
192 if (proc_it
== process_map_
.end())
194 base::hash_set
<cc::SharedBitmapId
>& res
= proc_it
->second
;
196 for (base::hash_set
<cc::SharedBitmapId
>::iterator it
= res
.begin();
199 handle_map_
.erase(*it
);
201 process_map_
.erase(proc_it
);
204 size_t HostSharedBitmapManager::AllocatedBitmapCount() const {
205 base::AutoLock
lock(lock_
);
206 return handle_map_
.size();
209 void HostSharedBitmapManager::FreeSharedMemoryFromMap(
210 const cc::SharedBitmapId
& id
) {
211 base::AutoLock
lock(lock_
);
212 handle_map_
.erase(id
);
215 } // namespace content