1 // Copyright 2014 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/common/gpu/client/gpu_memory_buffer_impl.h"
8 #include "content/common/gpu/gpu_memory_buffer_factory.h"
9 #include "testing/gtest/include/gtest/gtest.h"
14 const int kClientId
= 1;
16 class GpuMemoryBufferImplTest
17 : public testing::TestWithParam
<gfx::GpuMemoryBufferType
> {
19 GpuMemoryBufferImplTest() : buffer_count_(0), factory_(nullptr) {}
21 // Overridden from testing::Test:
22 void SetUp() override
{
23 factory_
= GpuMemoryBufferFactory::Create(GetParam());
24 factory_
->GetSupportedGpuMemoryBufferConfigurations(
25 &supported_configurations_
);
27 void TearDown() override
{ factory_
.reset(); }
29 gfx::GpuMemoryBufferHandle
CreateGpuMemoryBuffer(
30 gfx::GpuMemoryBufferId id
,
31 const gfx::Size
& size
,
32 gfx::GpuMemoryBuffer::Format format
,
33 gfx::GpuMemoryBuffer::Usage usage
) {
35 return factory_
->CreateGpuMemoryBuffer(id
, size
, format
, usage
, kClientId
,
36 gfx::kNullPluginWindow
);
39 void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id
, uint32 sync_point
) {
40 factory_
->DestroyGpuMemoryBuffer(id
, kClientId
);
41 DCHECK_GT(buffer_count_
, 0);
45 std::vector
<GpuMemoryBufferFactory::Configuration
> supported_configurations_
;
49 scoped_ptr
<GpuMemoryBufferFactory
> factory_
;
52 TEST_P(GpuMemoryBufferImplTest
, CreateFromHandle
) {
53 const int kBufferId
= 1;
55 gfx::Size
buffer_size(8, 8);
57 for (auto configuration
: supported_configurations_
) {
58 scoped_ptr
<GpuMemoryBufferImpl
> buffer(
59 GpuMemoryBufferImpl::CreateFromHandle(
60 CreateGpuMemoryBuffer(kBufferId
, buffer_size
, configuration
.format
,
62 buffer_size
, configuration
.format
, configuration
.usage
,
63 base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer
,
64 base::Unretained(this), kBufferId
)));
65 EXPECT_EQ(1, buffer_count_
);
67 EXPECT_EQ(buffer
->GetFormat(), configuration
.format
);
69 // Check if destruction callback is executed when deleting the buffer.
71 EXPECT_EQ(0, buffer_count_
);
75 TEST_P(GpuMemoryBufferImplTest
, Map
) {
76 const int kBufferId
= 1;
78 // Use a multiple of 4 for both dimensions to support compressed formats.
79 gfx::Size
buffer_size(4, 4);
81 for (auto configuration
: supported_configurations_
) {
82 if (configuration
.usage
!= gfx::GpuMemoryBuffer::MAP
)
85 scoped_ptr
<GpuMemoryBufferImpl
> buffer(
86 GpuMemoryBufferImpl::CreateFromHandle(
87 CreateGpuMemoryBuffer(kBufferId
, buffer_size
, configuration
.format
,
89 buffer_size
, configuration
.format
, configuration
.usage
,
90 base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer
,
91 base::Unretained(this), kBufferId
)));
93 EXPECT_FALSE(buffer
->IsMapped());
96 GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(
97 configuration
.format
);
99 // Map buffer into user space.
100 scoped_ptr
<void*[]> mapped_buffers(new void*[num_planes
]);
101 bool rv
= buffer
->Map(mapped_buffers
.get());
103 EXPECT_TRUE(buffer
->IsMapped());
106 scoped_ptr
<int[]> strides(new int[num_planes
]);
107 buffer
->GetStride(strides
.get());
109 // Copy and compare mapped buffers.
110 for (size_t plane
= 0; plane
< num_planes
; ++plane
) {
111 size_t row_size_in_bytes
= 0;
112 EXPECT_TRUE(GpuMemoryBufferImpl::RowSizeInBytes(
113 buffer_size
.width(), configuration
.format
, plane
,
114 &row_size_in_bytes
));
115 EXPECT_GT(row_size_in_bytes
, 0u);
117 scoped_ptr
<char[]> data(new char[row_size_in_bytes
]);
118 memset(data
.get(), 0x2a + plane
, row_size_in_bytes
);
121 buffer_size
.height() /
122 GpuMemoryBufferImpl::SubsamplingFactor(configuration
.format
, plane
);
123 for (size_t y
= 0; y
< height
; ++y
) {
124 memcpy(static_cast<char*>(mapped_buffers
[plane
]) + y
* strides
[plane
],
125 data
.get(), row_size_in_bytes
);
126 EXPECT_EQ(memcmp(static_cast<char*>(mapped_buffers
[plane
]) +
128 data
.get(), row_size_in_bytes
),
134 EXPECT_FALSE(buffer
->IsMapped());
138 TEST_P(GpuMemoryBufferImplTest
, PersistentMap
) {
139 const int kBufferId
= 1;
141 // Use a multiple of 4 for both dimensions to support compressed formats.
142 gfx::Size
buffer_size(4, 4);
144 for (auto configuration
: supported_configurations_
) {
145 if (configuration
.usage
!= gfx::GpuMemoryBuffer::PERSISTENT_MAP
)
148 scoped_ptr
<GpuMemoryBufferImpl
> buffer(
149 GpuMemoryBufferImpl::CreateFromHandle(
150 CreateGpuMemoryBuffer(kBufferId
, buffer_size
, configuration
.format
,
151 configuration
.usage
),
152 buffer_size
, configuration
.format
, configuration
.usage
,
153 base::Bind(&GpuMemoryBufferImplTest::DestroyGpuMemoryBuffer
,
154 base::Unretained(this), kBufferId
)));
156 EXPECT_FALSE(buffer
->IsMapped());
159 GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(
160 configuration
.format
);
162 // Map buffer into user space.
163 scoped_ptr
<void* []> mapped_buffers(new void* [num_planes
]);
164 bool rv
= buffer
->Map(mapped_buffers
.get());
166 EXPECT_TRUE(buffer
->IsMapped());
169 scoped_ptr
<int[]> strides(new int[num_planes
]);
170 buffer
->GetStride(strides
.get());
172 // Copy and compare mapped buffers.
173 for (size_t plane
= 0; plane
< num_planes
; ++plane
) {
174 size_t row_size_in_bytes
;
175 EXPECT_TRUE(GpuMemoryBufferImpl::RowSizeInBytes(
176 buffer_size
.width(), configuration
.format
, plane
,
177 &row_size_in_bytes
));
179 scoped_ptr
<char[]> data(new char[row_size_in_bytes
]);
180 memset(data
.get(), 0x2a + plane
, row_size_in_bytes
);
183 buffer_size
.height() /
184 GpuMemoryBufferImpl::SubsamplingFactor(configuration
.format
, plane
);
185 for (size_t y
= 0; y
< height
; ++y
) {
186 memcpy(static_cast<char*>(mapped_buffers
[plane
]) + y
* strides
[plane
],
187 data
.get(), row_size_in_bytes
);
188 EXPECT_EQ(memcmp(static_cast<char*>(mapped_buffers
[plane
]) +
190 data
.get(), row_size_in_bytes
),
196 EXPECT_FALSE(buffer
->IsMapped());
198 // Remap the buffer, and compare again. It should contain the same data.
199 rv
= buffer
->Map(mapped_buffers
.get());
201 EXPECT_TRUE(buffer
->IsMapped());
203 buffer
->GetStride(strides
.get());
205 for (size_t plane
= 0; plane
< num_planes
; ++plane
) {
206 size_t row_size_in_bytes
;
207 EXPECT_TRUE(GpuMemoryBufferImpl::RowSizeInBytes(
208 buffer_size
.width(), configuration
.format
, plane
,
209 &row_size_in_bytes
));
211 scoped_ptr
<char[]> data(new char[row_size_in_bytes
]);
212 memset(data
.get(), 0x2a + plane
, row_size_in_bytes
);
215 buffer_size
.height() /
216 GpuMemoryBufferImpl::SubsamplingFactor(configuration
.format
, plane
);
217 for (size_t y
= 0; y
< height
; ++y
) {
218 EXPECT_EQ(memcmp(static_cast<char*>(mapped_buffers
[plane
]) +
220 data
.get(), row_size_in_bytes
),
226 EXPECT_FALSE(buffer
->IsMapped());
230 std::vector
<gfx::GpuMemoryBufferType
> GetSupportedGpuMemoryBufferTypes() {
231 std::vector
<gfx::GpuMemoryBufferType
> supported_types
;
232 GpuMemoryBufferFactory::GetSupportedTypes(&supported_types
);
233 return supported_types
;
236 INSTANTIATE_TEST_CASE_P(
237 GpuMemoryBufferImplTests
,
238 GpuMemoryBufferImplTest
,
239 ::testing::ValuesIn(GetSupportedGpuMemoryBufferTypes()));
242 } // namespace content