Home | History | Annotate | Download | only in common
      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