1 // Copyright (c) 2012 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 "gpu/command_buffer/service/renderbuffer_manager.h"
8 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
9 #include "gpu/command_buffer/service/feature_info.h"
10 #include "gpu/command_buffer/service/gpu_service_test.h"
11 #include "gpu/command_buffer/service/mocks.h"
12 #include "gpu/command_buffer/service/test_helper.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/gl/gl_implementation.h"
15 #include "ui/gl/gl_mock.h"
17 using ::testing::StrictMock
;
22 class RenderbufferManagerTestBase
: public GpuServiceTest
{
24 static const GLint kMaxSize
= 128;
25 static const GLint kMaxSamples
= 4;
28 void SetUpBase(MemoryTracker
* memory_tracker
,
29 bool depth24_supported
,
31 GpuServiceTest::SetUp();
32 feature_info_
= new FeatureInfo();
33 TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
35 depth24_supported
? "GL_OES_depth24" : "",
37 use_gles
? "OpenGL ES 2.0" : "OpenGL 2.1");
38 feature_info_
->Initialize();
39 manager_
.reset(new RenderbufferManager(
40 memory_tracker
, kMaxSize
, kMaxSamples
, feature_info_
.get()));
43 void TearDown() override
{
44 manager_
->Destroy(true);
46 GpuServiceTest::TearDown();
49 scoped_refptr
<FeatureInfo
> feature_info_
;
50 scoped_ptr
<RenderbufferManager
> manager_
;
53 class RenderbufferManagerTest
: public RenderbufferManagerTestBase
{
55 void SetUp() override
{
56 bool depth24_supported
= false;
57 bool use_gles
= false;
58 SetUpBase(NULL
, depth24_supported
, use_gles
);
62 class RenderbufferManagerMemoryTrackerTest
63 : public RenderbufferManagerTestBase
{
65 void SetUp() override
{
66 mock_memory_tracker_
= new StrictMock
<MockMemoryTracker
>();
67 bool depth24_supported
= false;
68 bool use_gles
= false;
69 SetUpBase(mock_memory_tracker_
.get(), depth24_supported
, use_gles
);
72 scoped_refptr
<MockMemoryTracker
> mock_memory_tracker_
;
75 #define EXPECT_MEMORY_ALLOCATION_CHANGE(old_size, new_size, pool) \
76 EXPECT_CALL(*mock_memory_tracker_.get(), \
77 TrackMemoryAllocatedChange(old_size, new_size, pool)) \
78 .Times(1).RetiresOnSaturation()
80 // GCC requires these declarations, but MSVC requires they not be present
82 const GLint
RenderbufferManagerTestBase::kMaxSize
;
83 const GLint
RenderbufferManagerTestBase::kMaxSamples
;
86 TEST_F(RenderbufferManagerTest
, Basic
) {
87 const GLuint kClient1Id
= 1;
88 const GLuint kService1Id
= 11;
89 const GLuint kClient2Id
= 2;
90 EXPECT_EQ(kMaxSize
, manager_
->max_renderbuffer_size());
91 EXPECT_EQ(kMaxSamples
, manager_
->max_samples());
92 EXPECT_FALSE(manager_
->HaveUnclearedRenderbuffers());
93 // Check we can create renderbuffer.
94 manager_
->CreateRenderbuffer(kClient1Id
, kService1Id
);
95 // Check renderbuffer got created.
96 scoped_refptr
<Renderbuffer
> renderbuffer1
=
97 manager_
->GetRenderbuffer(kClient1Id
);
98 ASSERT_TRUE(renderbuffer1
.get() != NULL
);
99 EXPECT_FALSE(manager_
->HaveUnclearedRenderbuffers());
100 EXPECT_EQ(kClient1Id
, renderbuffer1
->client_id());
101 // Check we get nothing for a non-existent renderbuffer.
102 EXPECT_TRUE(manager_
->GetRenderbuffer(kClient2Id
) == NULL
);
103 // Check trying to a remove non-existent renderbuffers does not crash.
104 manager_
->RemoveRenderbuffer(kClient2Id
);
105 // Check that the renderbuffer is deleted when the last ref is released.
106 EXPECT_CALL(*gl_
, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id
)))
108 .RetiresOnSaturation();
109 // Check we can't get the renderbuffer after we remove it.
110 manager_
->RemoveRenderbuffer(kClient1Id
);
111 EXPECT_TRUE(manager_
->GetRenderbuffer(kClient1Id
) == NULL
);
112 EXPECT_FALSE(manager_
->HaveUnclearedRenderbuffers());
113 EXPECT_EQ(0u, renderbuffer1
->client_id());
116 TEST_F(RenderbufferManagerTest
, Destroy
) {
117 const GLuint kClient1Id
= 1;
118 const GLuint kService1Id
= 11;
119 // Check we can create renderbuffer.
120 manager_
->CreateRenderbuffer(kClient1Id
, kService1Id
);
121 // Check renderbuffer got created.
122 Renderbuffer
* renderbuffer1
=
123 manager_
->GetRenderbuffer(kClient1Id
);
124 ASSERT_TRUE(renderbuffer1
!= NULL
);
125 EXPECT_CALL(*gl_
, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id
)))
127 .RetiresOnSaturation();
128 manager_
->Destroy(true);
129 renderbuffer1
= manager_
->GetRenderbuffer(kClient1Id
);
130 ASSERT_TRUE(renderbuffer1
== NULL
);
133 TEST_F(RenderbufferManagerTest
, Renderbuffer
) {
134 const GLuint kClient1Id
= 1;
135 const GLuint kService1Id
= 11;
136 // Check we can create renderbuffer.
137 manager_
->CreateRenderbuffer(kClient1Id
, kService1Id
);
138 // Check renderbuffer got created.
139 Renderbuffer
* renderbuffer1
=
140 manager_
->GetRenderbuffer(kClient1Id
);
141 ASSERT_TRUE(renderbuffer1
!= NULL
);
142 EXPECT_EQ(kService1Id
, renderbuffer1
->service_id());
143 EXPECT_EQ(0, renderbuffer1
->samples());
144 EXPECT_EQ(static_cast<GLenum
>(GL_RGBA4
), renderbuffer1
->internal_format());
145 EXPECT_EQ(0, renderbuffer1
->width());
146 EXPECT_EQ(0, renderbuffer1
->height());
147 EXPECT_TRUE(renderbuffer1
->cleared());
148 EXPECT_EQ(0u, renderbuffer1
->EstimatedSize());
150 // Check if we set the info it gets marked as not cleared.
151 const GLsizei kSamples
= 4;
152 const GLenum kFormat
= GL_RGBA4
;
153 const GLsizei kWidth
= 128;
154 const GLsizei kHeight
= 64;
155 manager_
->SetInfo(renderbuffer1
, kSamples
, kFormat
, kWidth
, kHeight
);
156 EXPECT_EQ(kSamples
, renderbuffer1
->samples());
157 EXPECT_EQ(kFormat
, renderbuffer1
->internal_format());
158 EXPECT_EQ(kWidth
, renderbuffer1
->width());
159 EXPECT_EQ(kHeight
, renderbuffer1
->height());
160 EXPECT_FALSE(renderbuffer1
->cleared());
161 EXPECT_FALSE(renderbuffer1
->IsDeleted());
162 EXPECT_TRUE(manager_
->HaveUnclearedRenderbuffers());
163 EXPECT_EQ(kWidth
* kHeight
* 4u * 4u, renderbuffer1
->EstimatedSize());
165 manager_
->SetCleared(renderbuffer1
, true);
166 EXPECT_TRUE(renderbuffer1
->cleared());
167 EXPECT_FALSE(manager_
->HaveUnclearedRenderbuffers());
169 manager_
->SetInfo(renderbuffer1
, kSamples
, kFormat
, kWidth
, kHeight
);
170 EXPECT_TRUE(manager_
->HaveUnclearedRenderbuffers());
172 // Check that the renderbuffer is deleted when the last ref is released.
173 EXPECT_CALL(*gl_
, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id
)))
175 .RetiresOnSaturation();
176 manager_
->RemoveRenderbuffer(kClient1Id
);
177 EXPECT_FALSE(manager_
->HaveUnclearedRenderbuffers());
180 TEST_F(RenderbufferManagerMemoryTrackerTest
, Basic
) {
181 const GLuint kClient1Id
= 1;
182 const GLuint kService1Id
= 11;
183 EXPECT_MEMORY_ALLOCATION_CHANGE(0, 0, MemoryTracker::kUnmanaged
);
184 manager_
->CreateRenderbuffer(kClient1Id
, kService1Id
);
185 Renderbuffer
* renderbuffer1
=
186 manager_
->GetRenderbuffer(kClient1Id
);
187 ASSERT_TRUE(renderbuffer1
!= NULL
);
189 const GLsizei kSamples
= 4;
190 const GLenum kFormat
= GL_RGBA4
;
191 const GLsizei kWidth
= 128;
192 const GLsizei kHeight1
= 64;
193 const GLsizei kHeight2
= 32;
194 uint32 expected_size_1
= 0;
195 uint32 expected_size_2
= 0;
196 manager_
->ComputeEstimatedRenderbufferSize(
197 kWidth
, kHeight1
, kSamples
, kFormat
, &expected_size_1
);
198 manager_
->ComputeEstimatedRenderbufferSize(
199 kWidth
, kHeight2
, kSamples
, kFormat
, &expected_size_2
);
200 EXPECT_MEMORY_ALLOCATION_CHANGE(
201 0, expected_size_1
, MemoryTracker::kUnmanaged
);
202 manager_
->SetInfo(renderbuffer1
, kSamples
, kFormat
, kWidth
, kHeight1
);
203 EXPECT_MEMORY_ALLOCATION_CHANGE(
204 expected_size_1
, 0, MemoryTracker::kUnmanaged
);
205 EXPECT_MEMORY_ALLOCATION_CHANGE(
206 0, expected_size_2
, MemoryTracker::kUnmanaged
);
207 manager_
->SetInfo(renderbuffer1
, kSamples
, kFormat
, kWidth
, kHeight2
);
208 EXPECT_MEMORY_ALLOCATION_CHANGE(
209 expected_size_2
, 0, MemoryTracker::kUnmanaged
);
210 EXPECT_CALL(*gl_
, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id
)))
212 .RetiresOnSaturation();
215 TEST_F(RenderbufferManagerTest
, UseDeletedRenderbufferInfo
) {
216 const GLuint kClient1Id
= 1;
217 const GLuint kService1Id
= 11;
218 manager_
->CreateRenderbuffer(kClient1Id
, kService1Id
);
219 scoped_refptr
<Renderbuffer
> renderbuffer1(
220 manager_
->GetRenderbuffer(kClient1Id
));
221 ASSERT_TRUE(renderbuffer1
.get() != NULL
);
223 manager_
->RemoveRenderbuffer(kClient1Id
);
224 // Use after removing.
225 const GLsizei kSamples
= 4;
226 const GLenum kFormat
= GL_RGBA4
;
227 const GLsizei kWidth
= 128;
228 const GLsizei kHeight
= 64;
229 manager_
->SetInfo(renderbuffer1
.get(), kSamples
, kFormat
, kWidth
, kHeight
);
230 // See that it still affects manager.
231 EXPECT_TRUE(manager_
->HaveUnclearedRenderbuffers());
232 manager_
->SetCleared(renderbuffer1
.get(), true);
233 EXPECT_FALSE(manager_
->HaveUnclearedRenderbuffers());
234 // Check that the renderbuffer is deleted when the last ref is released.
235 EXPECT_CALL(*gl_
, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id
)))
237 .RetiresOnSaturation();
238 renderbuffer1
= NULL
;
243 bool InSet(std::set
<std::string
>* string_set
, const std::string
& str
) {
244 std::pair
<std::set
<std::string
>::iterator
, bool> result
=
245 string_set
->insert(str
);
246 return !result
.second
;
249 } // anonymous namespace
251 TEST_F(RenderbufferManagerTest
, AddToSignature
) {
252 const GLuint kClient1Id
= 1;
253 const GLuint kService1Id
= 11;
254 manager_
->CreateRenderbuffer(kClient1Id
, kService1Id
);
255 scoped_refptr
<Renderbuffer
> renderbuffer1(
256 manager_
->GetRenderbuffer(kClient1Id
));
257 ASSERT_TRUE(renderbuffer1
.get() != NULL
);
258 const GLsizei kSamples
= 4;
259 const GLenum kFormat
= GL_RGBA4
;
260 const GLsizei kWidth
= 128;
261 const GLsizei kHeight
= 64;
262 manager_
->SetInfo(renderbuffer1
.get(), kSamples
, kFormat
, kWidth
, kHeight
);
263 std::string signature1
;
264 std::string signature2
;
265 renderbuffer1
->AddToSignature(&signature1
);
267 std::set
<std::string
> string_set
;
268 EXPECT_FALSE(InSet(&string_set
, signature1
));
270 // change things and see that the signatures change.
272 renderbuffer1
.get(), kSamples
+ 1, kFormat
, kWidth
, kHeight
);
273 renderbuffer1
->AddToSignature(&signature2
);
274 EXPECT_FALSE(InSet(&string_set
, signature2
));
277 renderbuffer1
.get(), kSamples
, kFormat
+ 1, kWidth
, kHeight
);
279 renderbuffer1
->AddToSignature(&signature2
);
280 EXPECT_FALSE(InSet(&string_set
, signature2
));
283 renderbuffer1
.get(), kSamples
, kFormat
, kWidth
+ 1, kHeight
);
285 renderbuffer1
->AddToSignature(&signature2
);
286 EXPECT_FALSE(InSet(&string_set
, signature2
));
289 renderbuffer1
.get(), kSamples
, kFormat
, kWidth
, kHeight
+ 1);
291 renderbuffer1
->AddToSignature(&signature2
);
292 EXPECT_FALSE(InSet(&string_set
, signature2
));
294 // put it back to the same and it should be the same.
295 manager_
->SetInfo(renderbuffer1
.get(), kSamples
, kFormat
, kWidth
, kHeight
);
297 renderbuffer1
->AddToSignature(&signature2
);
298 EXPECT_EQ(signature1
, signature2
);
300 // Check the set was acutally getting different signatures.
301 EXPECT_EQ(5u, string_set
.size());
303 EXPECT_CALL(*gl_
, DeleteRenderbuffersEXT(1, ::testing::Pointee(kService1Id
)))
305 .RetiresOnSaturation();
308 class RenderbufferManagerFormatGLESTest
: public RenderbufferManagerTestBase
{
310 void SetUp() override
{
311 bool depth24_supported
= true;
312 bool use_gles
= true;
313 SetUpBase(NULL
, depth24_supported
, use_gles
);
317 TEST_F(RenderbufferManagerFormatGLESTest
, UpgradeDepthFormatOnGLES
) {
319 manager_
->InternalRenderbufferFormatToImplFormat(GL_DEPTH_COMPONENT16
);
320 EXPECT_EQ(static_cast<GLenum
>(GL_DEPTH_COMPONENT24
), impl_format
);
323 class RenderbufferManagerFormatNonGLESTest
:
324 public RenderbufferManagerTestBase
{
326 void SetUp() override
{
327 bool depth24_supported
= true;
328 bool use_gles
= false;
329 SetUpBase(NULL
, depth24_supported
, use_gles
);
333 TEST_F(RenderbufferManagerFormatNonGLESTest
, UseUnsizedDepthFormatOnNonGLES
) {
335 manager_
->InternalRenderbufferFormatToImplFormat(GL_DEPTH_COMPONENT16
);
336 EXPECT_EQ(static_cast<GLenum
>(GL_DEPTH_COMPONENT
), impl_format
);