1 // Copyright (c) 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/child/child_shared_bitmap_manager.h"
7 #include "base/debug/alias.h"
8 #include "base/process/memory.h"
9 #include "base/process/process_metrics.h"
10 #include "content/child/child_thread_impl.h"
11 #include "content/common/child_process_messages.h"
12 #include "ui/gfx/geometry/size.h"
18 class ChildSharedBitmap
: public SharedMemoryBitmap
{
20 ChildSharedBitmap(scoped_refptr
<ThreadSafeSender
> sender
,
21 base::SharedMemory
* shared_memory
,
22 const cc::SharedBitmapId
& id
)
23 : SharedMemoryBitmap(static_cast<uint8
*>(shared_memory
->memory()),
28 ChildSharedBitmap(scoped_refptr
<ThreadSafeSender
> sender
,
29 scoped_ptr
<base::SharedMemory
> shared_memory_holder
,
30 const cc::SharedBitmapId
& id
)
31 : ChildSharedBitmap(sender
, shared_memory_holder
.get(), id
) {
32 shared_memory_holder_
= shared_memory_holder
.Pass();
35 ~ChildSharedBitmap() override
{
36 sender_
->Send(new ChildProcessHostMsg_DeletedSharedBitmap(id()));
40 scoped_refptr
<ThreadSafeSender
> sender_
;
41 scoped_ptr
<base::SharedMemory
> shared_memory_holder_
;
44 // Collect extra information for debugging bitmap creation failures.
45 void CollectMemoryUsageAndDie(const gfx::Size
& size
, size_t alloc_size
) {
47 int width
= size
.width();
48 int height
= size
.height();
49 DWORD last_error
= GetLastError();
51 scoped_ptr
<base::ProcessMetrics
> metrics(
52 base::ProcessMetrics::CreateProcessMetrics(
53 base::GetCurrentProcessHandle()));
55 size_t private_bytes
= 0;
56 size_t shared_bytes
= 0;
57 metrics
->GetMemoryBytes(&private_bytes
, &shared_bytes
);
59 base::debug::Alias(&width
);
60 base::debug::Alias(&height
);
61 base::debug::Alias(&last_error
);
62 base::debug::Alias(&private_bytes
);
63 base::debug::Alias(&shared_bytes
);
65 base::TerminateBecauseOutOfMemory(alloc_size
);
70 SharedMemoryBitmap::SharedMemoryBitmap(uint8
* pixels
,
71 const cc::SharedBitmapId
& id
,
72 base::SharedMemory
* shared_memory
)
73 : SharedBitmap(pixels
, id
), shared_memory_(shared_memory
) {
76 ChildSharedBitmapManager::ChildSharedBitmapManager(
77 scoped_refptr
<ThreadSafeSender
> sender
)
81 ChildSharedBitmapManager::~ChildSharedBitmapManager() {}
83 scoped_ptr
<cc::SharedBitmap
> ChildSharedBitmapManager::AllocateSharedBitmap(
84 const gfx::Size
& size
) {
85 scoped_ptr
<SharedMemoryBitmap
> bitmap
= AllocateSharedMemoryBitmap(size
);
87 // Close file descriptor to avoid running out.
89 bitmap
->shared_memory()->Close();
94 scoped_ptr
<SharedMemoryBitmap
>
95 ChildSharedBitmapManager::AllocateSharedMemoryBitmap(const gfx::Size
& size
) {
96 TRACE_EVENT2("renderer",
97 "ChildSharedBitmapManager::AllocateSharedMemoryBitmap", "width",
98 size
.width(), "height", size
.height());
100 if (!cc::SharedBitmap::SizeInBytes(size
, &memory_size
))
101 return scoped_ptr
<SharedMemoryBitmap
>();
102 cc::SharedBitmapId id
= cc::SharedBitmap::GenerateId();
103 scoped_ptr
<base::SharedMemory
> memory
;
104 #if defined(OS_POSIX)
105 base::SharedMemoryHandle handle
;
106 sender_
->Send(new ChildProcessHostMsg_SyncAllocateSharedBitmap(
107 memory_size
, id
, &handle
));
108 memory
= make_scoped_ptr(new base::SharedMemory(handle
, false));
109 if (!memory
->Map(memory_size
))
110 CollectMemoryUsageAndDie(size
, memory_size
);
112 memory
= ChildThreadImpl::AllocateSharedMemory(memory_size
, sender_
.get());
114 CollectMemoryUsageAndDie(size
, memory_size
);
116 if (!memory
->Map(memory_size
))
117 CollectMemoryUsageAndDie(size
, memory_size
);
119 base::SharedMemoryHandle handle_to_send
= memory
->handle();
120 sender_
->Send(new ChildProcessHostMsg_AllocatedSharedBitmap(
121 memory_size
, handle_to_send
, id
));
123 return make_scoped_ptr(new ChildSharedBitmap(sender_
, memory
.Pass(), id
));
126 scoped_ptr
<cc::SharedBitmap
> ChildSharedBitmapManager::GetSharedBitmapFromId(
128 const cc::SharedBitmapId
&) {
130 return scoped_ptr
<cc::SharedBitmap
>();
133 scoped_ptr
<cc::SharedBitmap
> ChildSharedBitmapManager::GetBitmapForSharedMemory(
134 base::SharedMemory
* mem
) {
135 cc::SharedBitmapId id
= cc::SharedBitmap::GenerateId();
136 base::SharedMemoryHandle handle_to_send
= mem
->handle();
137 #if defined(OS_POSIX)
138 if (!mem
->ShareToProcess(base::GetCurrentProcessHandle(), &handle_to_send
))
139 return scoped_ptr
<cc::SharedBitmap
>();
141 sender_
->Send(new ChildProcessHostMsg_AllocatedSharedBitmap(
142 mem
->mapped_size(), handle_to_send
, id
));
144 return make_scoped_ptr(new ChildSharedBitmap(sender_
, mem
, id
));
147 } // namespace content