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
,
17 base::SharedMemoryHandle memory_handle
,
19 : process_handle(process_handle
),
20 memory_handle(memory_handle
),
21 buffer_size(buffer_size
) {}
22 base::ProcessHandle process_handle
;
23 base::SharedMemoryHandle memory_handle
;
24 scoped_ptr
<base::SharedMemory
> memory
;
25 scoped_ptr
<uint8
[]> pixels
;
29 friend class base::RefCountedThreadSafe
<BitmapData
>;
31 DISALLOW_COPY_AND_ASSIGN(BitmapData
);
34 // Holds a reference on the memory to keep it alive.
35 void FreeSharedMemory(scoped_refptr
<BitmapData
> data
,
36 cc::SharedBitmap
* bitmap
) {}
38 base::LazyInstance
<HostSharedBitmapManager
> g_shared_memory_manager
=
39 LAZY_INSTANCE_INITIALIZER
;
41 HostSharedBitmapManager::HostSharedBitmapManager() {}
42 HostSharedBitmapManager::~HostSharedBitmapManager() {}
44 HostSharedBitmapManager
* HostSharedBitmapManager::current() {
45 return g_shared_memory_manager
.Pointer();
48 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::AllocateSharedBitmap(
49 const gfx::Size
& size
) {
50 base::AutoLock
lock(lock_
);
52 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
))
53 return scoped_ptr
<cc::SharedBitmap
>();
55 scoped_refptr
<BitmapData
> data(
56 new BitmapData(base::GetCurrentProcessHandle(),
57 base::SharedMemory::NULLHandle(),
59 // Bitmaps allocated in host don't need to be shared to other processes, so
60 // allocate them with new instead.
61 data
->pixels
= scoped_ptr
<uint8
[]>(new uint8
[bitmap_size
]);
63 cc::SharedBitmapId id
= cc::SharedBitmap::GenerateId();
64 handle_map_
[id
] = data
;
65 return make_scoped_ptr(new cc::SharedBitmap(
68 base::Bind(&HostSharedBitmapManager::FreeSharedMemoryFromMap
,
69 base::Unretained(this))));
72 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::GetSharedBitmapFromId(
73 const gfx::Size
& size
,
74 const cc::SharedBitmapId
& id
) {
75 base::AutoLock
lock(lock_
);
76 BitmapMap::iterator it
= handle_map_
.find(id
);
77 if (it
== handle_map_
.end())
78 return scoped_ptr
<cc::SharedBitmap
>();
80 BitmapData
* data
= it
->second
.get();
83 if (!cc::SharedBitmap::SizeInBytes(size
, &bitmap_size
) ||
84 bitmap_size
> data
->buffer_size
)
85 return scoped_ptr
<cc::SharedBitmap
>();
88 return make_scoped_ptr(new cc::SharedBitmap(
89 data
->pixels
.get(), id
, base::Bind(&FreeSharedMemory
, it
->second
)));
91 if (!data
->memory
->memory()) {
92 TRACE_EVENT0("renderer_host",
93 "HostSharedBitmapManager::GetSharedBitmapFromId");
94 if (!data
->memory
->Map(data
->buffer_size
)) {
95 return scoped_ptr
<cc::SharedBitmap
>();
99 scoped_ptr
<cc::SharedBitmap
> bitmap(new cc::SharedBitmap(
100 data
->memory
.get(), id
, base::Bind(&FreeSharedMemory
, it
->second
)));
102 return bitmap
.Pass();
105 scoped_ptr
<cc::SharedBitmap
> HostSharedBitmapManager::GetBitmapForSharedMemory(
106 base::SharedMemory
*) {
107 return scoped_ptr
<cc::SharedBitmap
>();
110 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
112 const base::SharedMemoryHandle
& handle
,
113 base::ProcessHandle process_handle
,
114 const cc::SharedBitmapId
& id
) {
115 base::AutoLock
lock(lock_
);
116 if (handle_map_
.find(id
) != handle_map_
.end())
118 scoped_refptr
<BitmapData
> data(
119 new BitmapData(process_handle
, handle
, buffer_size
));
121 handle_map_
[id
] = data
;
122 process_map_
[process_handle
].insert(id
);
124 data
->memory
= make_scoped_ptr(
125 new base::SharedMemory(data
->memory_handle
, false, data
->process_handle
));
128 make_scoped_ptr(new base::SharedMemory(data
->memory_handle
, false));
132 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
133 base::ProcessHandle process_handle
,
135 const cc::SharedBitmapId
& id
,
136 base::SharedMemoryHandle
* shared_memory_handle
) {
137 base::AutoLock
lock(lock_
);
138 if (handle_map_
.find(id
) != handle_map_
.end()) {
139 *shared_memory_handle
= base::SharedMemory::NULLHandle();
142 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory
);
143 if (!shared_memory
->CreateAndMapAnonymous(buffer_size
)) {
144 LOG(ERROR
) << "Cannot create shared memory buffer";
145 *shared_memory_handle
= base::SharedMemory::NULLHandle();
149 scoped_refptr
<BitmapData
> data(
150 new BitmapData(process_handle
, shared_memory
->handle(), buffer_size
));
151 data
->memory
= shared_memory
.Pass();
153 handle_map_
[id
] = data
;
154 process_map_
[process_handle
].insert(id
);
155 if (!data
->memory
->ShareToProcess(process_handle
, shared_memory_handle
)) {
156 LOG(ERROR
) << "Cannot share shared memory buffer";
157 *shared_memory_handle
= base::SharedMemory::NULLHandle();
162 void HostSharedBitmapManager::ChildDeletedSharedBitmap(
163 const cc::SharedBitmapId
& id
) {
164 base::AutoLock
lock(lock_
);
165 BitmapMap::iterator it
= handle_map_
.find(id
);
166 if (it
== handle_map_
.end())
168 base::hash_set
<cc::SharedBitmapId
>& res
=
169 process_map_
[it
->second
->process_handle
];
171 handle_map_
.erase(it
);
174 void HostSharedBitmapManager::ProcessRemoved(
175 base::ProcessHandle process_handle
) {
176 base::AutoLock
lock(lock_
);
177 ProcessMap::iterator proc_it
= process_map_
.find(process_handle
);
178 if (proc_it
== process_map_
.end())
180 base::hash_set
<cc::SharedBitmapId
>& res
= proc_it
->second
;
182 for (base::hash_set
<cc::SharedBitmapId
>::iterator it
= res
.begin();
185 handle_map_
.erase(*it
);
187 process_map_
.erase(proc_it
);
190 size_t HostSharedBitmapManager::AllocatedBitmapCount() const {
191 base::AutoLock
lock(lock_
);
192 return handle_map_
.size();
195 void HostSharedBitmapManager::FreeSharedMemoryFromMap(
196 cc::SharedBitmap
* bitmap
) {
197 base::AutoLock
lock(lock_
);
198 handle_map_
.erase(bitmap
->id());
201 } // namespace content