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: 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>; 30 ~BitmapData() {} 31 DISALLOW_COPY_AND_ASSIGN(BitmapData); 32 }; 33 34 // Holds a reference on the memory to keep it alive. 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 41 HostSharedBitmapManager::HostSharedBitmapManager() {} 42 HostSharedBitmapManager::~HostSharedBitmapManager() {} 43 44 HostSharedBitmapManager* HostSharedBitmapManager::current() { 45 return g_shared_memory_manager.Pointer(); 46 } 47 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 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 105 scoped_ptr<cc::SharedBitmap> HostSharedBitmapManager::GetBitmapForSharedMemory( 106 base::SharedMemory*) { 107 return scoped_ptr<cc::SharedBitmap>(); 108 } 109 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 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 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 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 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