1 // Copyright 2015 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.
6 #include "base/command_line.h"
7 #include "base/memory/discardable_memory.h"
8 #include "base/memory/scoped_vector.h"
9 #include "base/time/time.h"
10 #include "content/child/child_discardable_shared_memory_manager.h"
11 #include "content/child/child_gpu_memory_buffer_manager.h"
12 #include "content/child/child_thread_impl.h"
13 #include "content/common/gpu/client/gpu_memory_buffer_impl.h"
14 #include "content/common/host_discardable_shared_memory_manager.h"
15 #include "content/public/common/content_switches.h"
16 #include "content/public/test/content_browser_test.h"
17 #include "content/public/test/content_browser_test_utils.h"
18 #include "content/shell/browser/shell.h"
24 class ChildThreadImplBrowserTest
: public ContentBrowserTest
{
26 ChildThreadImplBrowserTest()
27 : child_gpu_memory_buffer_manager_(nullptr),
28 child_discardable_shared_memory_manager_(nullptr) {}
30 // Overridden from BrowserTestBase:
31 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
32 command_line
->AppendSwitch(switches::kSingleProcess
);
34 void SetUpOnMainThread() override
{
35 NavigateToURL(shell(), GURL(url::kAboutBlankURL
));
36 PostTaskToInProcessRendererAndWait(
37 base::Bind(&ChildThreadImplBrowserTest::SetUpOnChildThread
, this));
40 ChildGpuMemoryBufferManager
* child_gpu_memory_buffer_manager() {
41 return child_gpu_memory_buffer_manager_
;
44 ChildDiscardableSharedMemoryManager
*
45 child_discardable_shared_memory_manager() {
46 return child_discardable_shared_memory_manager_
;
50 void SetUpOnChildThread() {
51 child_gpu_memory_buffer_manager_
=
52 ChildThreadImpl::current()->gpu_memory_buffer_manager();
53 child_discardable_shared_memory_manager_
=
54 ChildThreadImpl::current()->discardable_shared_memory_manager();
57 ChildGpuMemoryBufferManager
* child_gpu_memory_buffer_manager_
;
58 ChildDiscardableSharedMemoryManager
* child_discardable_shared_memory_manager_
;
61 IN_PROC_BROWSER_TEST_F(ChildThreadImplBrowserTest
,
62 DISABLED_LockDiscardableMemory
) {
63 const size_t kSize
= 1024 * 1024; // 1MiB.
65 scoped_ptr
<base::DiscardableMemory
> memory
=
66 child_discardable_shared_memory_manager()
67 ->AllocateLockedDiscardableMemory(kSize
);
70 void* addr
= memory
->data();
71 ASSERT_NE(nullptr, addr
);
75 // Purge all unlocked memory.
76 HostDiscardableSharedMemoryManager::current()->SetMemoryLimit(0);
78 // Should fail as memory should have been purged.
79 EXPECT_FALSE(memory
->Lock());
82 IN_PROC_BROWSER_TEST_F(ChildThreadImplBrowserTest
,
83 DISABLED_DiscardableMemoryAddressSpace
) {
84 const size_t kLargeSize
= 4 * 1024 * 1024; // 4MiB.
85 const size_t kNumberOfInstances
= 1024 + 1; // >4GiB total.
87 ScopedVector
<base::DiscardableMemory
> instances
;
88 for (size_t i
= 0; i
< kNumberOfInstances
; ++i
) {
89 scoped_ptr
<base::DiscardableMemory
> memory
=
90 child_discardable_shared_memory_manager()
91 ->AllocateLockedDiscardableMemory(kLargeSize
);
93 void* addr
= memory
->data();
94 ASSERT_NE(nullptr, addr
);
96 instances
.push_back(memory
.Pass());
100 IN_PROC_BROWSER_TEST_F(ChildThreadImplBrowserTest
,
101 DISABLED_ReleaseFreeDiscardableMemory
) {
102 const size_t kSize
= 1024 * 1024; // 1MiB.
104 scoped_ptr
<base::DiscardableMemory
> memory
=
105 child_discardable_shared_memory_manager()
106 ->AllocateLockedDiscardableMemory(kSize
);
111 EXPECT_GE(HostDiscardableSharedMemoryManager::current()->GetBytesAllocated(),
114 child_discardable_shared_memory_manager()->ReleaseFreeMemory();
116 // Busy wait for host memory usage to be reduced.
117 base::TimeTicks end
=
118 base::TimeTicks::Now() + base::TimeDelta::FromSeconds(5);
119 while (base::TimeTicks::Now() < end
) {
120 if (!HostDiscardableSharedMemoryManager::current()->GetBytesAllocated())
124 EXPECT_LT(base::TimeTicks::Now(), end
);
127 enum NativeBufferFlag
{ kDisableNativeBuffers
, kEnableNativeBuffers
};
129 class ChildThreadImplGpuMemoryBufferBrowserTest
130 : public ChildThreadImplBrowserTest
,
131 public testing::WithParamInterface
<
132 ::testing::tuple
<NativeBufferFlag
, gfx::GpuMemoryBuffer::Format
>> {
134 // Overridden from BrowserTestBase:
135 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
136 ChildThreadImplBrowserTest::SetUpCommandLine(command_line
);
137 NativeBufferFlag native_buffer_flag
= ::testing::get
<0>(GetParam());
138 switch (native_buffer_flag
) {
139 case kEnableNativeBuffers
:
140 command_line
->AppendSwitch(switches::kEnableNativeGpuMemoryBuffers
);
142 case kDisableNativeBuffers
:
148 IN_PROC_BROWSER_TEST_P(ChildThreadImplGpuMemoryBufferBrowserTest
,
150 gfx::GpuMemoryBuffer::Format format
= ::testing::get
<1>(GetParam());
151 gfx::Size
buffer_size(4, 4);
153 scoped_ptr
<gfx::GpuMemoryBuffer
> buffer
=
154 child_gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
155 buffer_size
, format
, gfx::GpuMemoryBuffer::MAP
);
157 EXPECT_EQ(format
, buffer
->GetFormat());
160 GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(format
);
162 // Map buffer planes.
163 scoped_ptr
<void* []> planes(new void* [num_planes
]);
164 bool rv
= buffer
->Map(planes
.get());
166 EXPECT_TRUE(buffer
->IsMapped());
169 scoped_ptr
<int[]> strides(new int[num_planes
]);
170 buffer
->GetStride(strides
.get());
172 // Write to buffer and check result.
173 for (size_t plane
= 0; plane
< num_planes
; ++plane
) {
174 size_t row_size_in_bytes
= 0;
175 EXPECT_TRUE(GpuMemoryBufferImpl::RowSizeInBytes(buffer_size
.width(), format
,
176 plane
, &row_size_in_bytes
));
178 scoped_ptr
<char[]> data(new char[row_size_in_bytes
]);
179 memset(data
.get(), 0x2a + plane
, row_size_in_bytes
);
180 size_t height
= buffer_size
.height() /
181 GpuMemoryBufferImpl::SubsamplingFactor(format
, plane
);
182 for (size_t y
= 0; y
< height
; ++y
) {
183 // Copy |data| to row |y| of |plane| and verify result.
184 memcpy(static_cast<char*>(planes
[plane
]) + y
* strides
[plane
], data
.get(),
186 EXPECT_EQ(memcmp(static_cast<char*>(planes
[plane
]) + y
* strides
[plane
],
187 data
.get(), row_size_in_bytes
),
193 EXPECT_FALSE(buffer
->IsMapped());
196 INSTANTIATE_TEST_CASE_P(
197 ChildThreadImplGpuMemoryBufferBrowserTests
,
198 ChildThreadImplGpuMemoryBufferBrowserTest
,
199 ::testing::Combine(::testing::Values(kDisableNativeBuffers
,
200 kEnableNativeBuffers
),
201 // These formats are guaranteed to work on all platforms.
202 ::testing::Values(gfx::GpuMemoryBuffer::R_8
,
203 gfx::GpuMemoryBuffer::RGBA_4444
,
204 gfx::GpuMemoryBuffer::RGBA_8888
,
205 gfx::GpuMemoryBuffer::BGRA_8888
,
206 gfx::GpuMemoryBuffer::YUV_420
)));
209 } // namespace content