• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/common/host_shared_bitmap_manager.h"
6 
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"
11 
12 namespace content {
13 
14 class BitmapData : public base::RefCountedThreadSafe<BitmapData> {
15  public:
BitmapData(base::ProcessHandle process_handle,base::SharedMemoryHandle memory_handle,size_t buffer_size)16   BitmapData(base::ProcessHandle process_handle,
17              base::SharedMemoryHandle memory_handle,
18              size_t buffer_size)
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;
26   size_t buffer_size;
27 
28  private:
29   friend class base::RefCountedThreadSafe<BitmapData>;
~BitmapData()30   ~BitmapData() {}
31   DISALLOW_COPY_AND_ASSIGN(BitmapData);
32 };
33 
34 // Holds a reference on the memory to keep it alive.
FreeSharedMemory(scoped_refptr<BitmapData> data,cc::SharedBitmap * bitmap)35 void FreeSharedMemory(scoped_refptr<BitmapData> data,
36                       cc::SharedBitmap* bitmap) {}
37 
38 base::LazyInstance<HostSharedBitmapManager> g_shared_memory_manager =
39     LAZY_INSTANCE_INITIALIZER;
40 
HostSharedBitmapManager()41 HostSharedBitmapManager::HostSharedBitmapManager() {}
~HostSharedBitmapManager()42 HostSharedBitmapManager::~HostSharedBitmapManager() {}
43 
current()44 HostSharedBitmapManager* HostSharedBitmapManager::current() {
45   return g_shared_memory_manager.Pointer();
46 }
47 
AllocateSharedBitmap(const gfx::Size & size)48 scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::AllocateSharedBitmap(
49     const gfx::Size& size) {
50   base::AutoLock lock(lock_);
51   size_t bitmap_size;
52   if (!cc::SharedBitmap::SizeInBytes(size, &bitmap_size))
53     return scoped_ptr<cc::SharedBitmap>();
54 
55   scoped_refptr<BitmapData> data(
56       new BitmapData(base::GetCurrentProcessHandle(),
57                      base::SharedMemory::NULLHandle(),
58                      bitmap_size));
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]);
62 
63   cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
64   handle_map_[id] = data;
65   return make_scoped_ptr(new cc::SharedBitmap(
66       data->pixels.get(),
67       id,
68       base::Bind(&HostSharedBitmapManager::FreeSharedMemoryFromMap,
69                  base::Unretained(this))));
70 }
71 
GetSharedBitmapFromId(const gfx::Size & size,const cc::SharedBitmapId & id)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>();
79 
80   BitmapData* data = it->second.get();
81 
82   size_t bitmap_size;
83   if (!cc::SharedBitmap::SizeInBytes(size, &bitmap_size) ||
84       bitmap_size > data->buffer_size)
85     return scoped_ptr<cc::SharedBitmap>();
86 
87   if (data->pixels) {
88     return make_scoped_ptr(new cc::SharedBitmap(
89         data->pixels.get(), id, base::Bind(&FreeSharedMemory, it->second)));
90   }
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>();
96     }
97   }
98 
99   scoped_ptr<cc::SharedBitmap> bitmap(new cc::SharedBitmap(
100       data->memory.get(), id, base::Bind(&FreeSharedMemory, it->second)));
101 
102   return bitmap.Pass();
103 }
104 
GetBitmapForSharedMemory(base::SharedMemory *)105 scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::GetBitmapForSharedMemory(
106     base::SharedMemory*) {
107   return scoped_ptr<cc::SharedBitmap>();
108 }
109 
ChildAllocatedSharedBitmap(size_t buffer_size,const base::SharedMemoryHandle & handle,base::ProcessHandle process_handle,const cc::SharedBitmapId & id)110 void HostSharedBitmapManager::ChildAllocatedSharedBitmap(
111     size_t buffer_size,
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())
117     return;
118   scoped_refptr<BitmapData> data(
119       new BitmapData(process_handle, handle, buffer_size));
120 
121   handle_map_[id] = data;
122   process_map_[process_handle].insert(id);
123 #if defined(OS_WIN)
124   data->memory = make_scoped_ptr(
125       new base::SharedMemory(data->memory_handle, false, data->process_handle));
126 #else
127   data->memory =
128       make_scoped_ptr(new base::SharedMemory(data->memory_handle, false));
129 #endif
130 }
131 
AllocateSharedBitmapForChild(base::ProcessHandle process_handle,size_t buffer_size,const cc::SharedBitmapId & id,base::SharedMemoryHandle * shared_memory_handle)132 void HostSharedBitmapManager::AllocateSharedBitmapForChild(
133     base::ProcessHandle process_handle,
134     size_t buffer_size,
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();
140     return;
141   }
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();
146     return;
147   }
148 
149   scoped_refptr<BitmapData> data(
150       new BitmapData(process_handle, shared_memory->handle(), buffer_size));
151   data->memory = shared_memory.Pass();
152 
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();
158     return;
159   }
160 }
161 
ChildDeletedSharedBitmap(const cc::SharedBitmapId & id)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())
167     return;
168   base::hash_set<cc::SharedBitmapId>& res =
169       process_map_[it->second->process_handle];
170   res.erase(id);
171   handle_map_.erase(it);
172 }
173 
ProcessRemoved(base::ProcessHandle process_handle)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())
179     return;
180   base::hash_set<cc::SharedBitmapId>& res = proc_it->second;
181 
182   for (base::hash_set<cc::SharedBitmapId>::iterator it = res.begin();
183        it != res.end();
184        ++it) {
185     handle_map_.erase(*it);
186   }
187   process_map_.erase(proc_it);
188 }
189 
FreeSharedMemoryFromMap(cc::SharedBitmap * bitmap)190 void HostSharedBitmapManager::FreeSharedMemoryFromMap(
191     cc::SharedBitmap* bitmap) {
192   base::AutoLock lock(lock_);
193   handle_map_.erase(bitmap->id());
194 }
195 
196 }  // namespace content
197