1 // Copyright (c) 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.
5 #include "gpu/command_buffer/service/path_manager.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/mocks.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "ui/gl/gl_mock.h"
16 class PathManagerTest
: public GpuServiceTest
{
21 void SetUp() override
{
22 SetUpWithGLVersion("3.0", "GL_NV_path_rendering");
23 manager_
.reset(new PathManager());
26 void TearDown() override
{
27 manager_
->Destroy(true);
29 GpuServiceTest::TearDown();
32 scoped_ptr
<PathManager
> manager_
;
35 TEST_F(PathManagerTest
, Basic
) {
36 const GLuint kClient1Id
= 1;
37 const GLuint kService1Id
= 11;
38 const GLuint kClient2Id
= 2;
39 GLuint service_id
= 0;
40 manager_
->CreatePathRange(kClient1Id
, kClient1Id
, kService1Id
);
41 ASSERT_TRUE(manager_
->HasPathsInRange(kClient1Id
, kClient1Id
));
42 EXPECT_TRUE(manager_
->GetPath(kClient1Id
, &service_id
));
43 EXPECT_EQ(kService1Id
, service_id
);
45 // Check we get nothing for a non-existent path.
47 ASSERT_FALSE(manager_
->HasPathsInRange(kClient2Id
, kClient2Id
));
48 EXPECT_FALSE(manager_
->GetPath(kClient2Id
, &service_id
));
49 EXPECT_EQ(123u, service_id
);
51 // Check trying to remove non-existent paths does not crash.
52 manager_
->RemovePaths(kClient2Id
, kClient2Id
);
54 // Check that it gets deleted when the last reference is released.
55 EXPECT_CALL(*gl_
, DeletePathsNV(kService1Id
, 1))
57 .RetiresOnSaturation();
59 // Check we can't get the path after we remove it.
60 manager_
->RemovePaths(kClient1Id
, kClient1Id
);
61 ASSERT_FALSE(manager_
->HasPathsInRange(kClient1Id
, kClient1Id
));
62 EXPECT_FALSE(manager_
->GetPath(kClient1Id
, &service_id
));
65 // Tests that path manager does not merge ranges that contain service ids that
66 // prevent the merging. Path ranges A and B can be merged if
67 // * client ids of B start immediately after the last client id of A
68 // * service ids of B start immediately after the last service id of A
69 // and similarly for the 'before' case.
70 TEST_F(PathManagerTest
, NonContiguousServiceIds
) {
71 const GLuint kMergeCheckRange
= 54;
74 GLuint first_client_id
;
75 GLuint last_client_id
;
76 GLuint first_service_id
;
77 } kIdRanges
[] = {{500, 1000, 900}, {1001, 1155, 1}, {200, 499, 4888}};
78 for (auto& range
: kIdRanges
) {
79 manager_
->CreatePathRange(range
.first_client_id
, range
.last_client_id
,
80 range
.first_service_id
);
81 ASSERT_TRUE(manager_
->HasPathsInRange(range
.first_client_id
,
82 range
.first_client_id
));
84 manager_
->HasPathsInRange(range
.last_client_id
, range
.last_client_id
));
86 manager_
->HasPathsInRange(range
.first_client_id
, range
.last_client_id
));
87 GLuint service_id
= 0u;
88 EXPECT_TRUE(manager_
->GetPath(range
.first_client_id
+ 5u, &service_id
));
89 EXPECT_EQ(range
.first_service_id
+ 5u, service_id
);
92 // Insert a mergeable range last, to check that merges
93 // work. Otherwise the test could succeed because merges were not
95 auto& merge_candidate
= kIdRanges
[1];
96 GLuint merge_candidate_range
=
97 merge_candidate
.last_client_id
- merge_candidate
.first_client_id
+ 1;
98 manager_
->CreatePathRange(
99 merge_candidate
.last_client_id
+ 1,
100 merge_candidate
.last_client_id
+ kMergeCheckRange
,
101 merge_candidate
.first_service_id
+ merge_candidate_range
);
103 // We detect that ranges were not merged accidentally by detecting individual
105 for (auto& range
: kIdRanges
) {
106 if (&range
== &merge_candidate
)
108 GLsizei range_amount
= range
.last_client_id
- range
.first_client_id
+ 1;
109 EXPECT_CALL(*gl_
, DeletePathsNV(range
.first_service_id
, range_amount
))
111 .RetiresOnSaturation();
114 // Just a check that merges work.
115 EXPECT_CALL(*gl_
, DeletePathsNV(merge_candidate
.first_service_id
,
116 merge_candidate_range
+ kMergeCheckRange
))
118 .RetiresOnSaturation();
120 // Remove all ids. This should cause the expected amount of DeletePathsNV
122 manager_
->RemovePaths(1, std::numeric_limits
<GLsizei
>::max());
124 for (auto& range
: kIdRanges
) {
126 manager_
->HasPathsInRange(range
.first_client_id
, range
.last_client_id
));
130 TEST_F(PathManagerTest
, DeleteBigRange
) {
131 // Allocates two ranges which in path manager end up merging as one
132 // big range. The range will be too big to fit in one DeletePaths
133 // call. Test that the range is deleted correctly with two calls.
134 const GLuint kFirstClientId1
= 1;
135 const GLsizei kRange1
= std::numeric_limits
<GLsizei
>::max() - 3;
136 const GLuint kLastClientId1
= kFirstClientId1
+ kRange1
- 1;
137 const GLuint kFirstServiceId1
= 77;
138 const GLuint kLastServiceId1
= kFirstServiceId1
+ kRange1
- 1;
140 const GLuint kFirstClientId2
= kLastClientId1
+ 1;
141 const GLsizei kRange2
= 15;
142 const GLuint kLastClientId2
= kFirstClientId2
+ kRange2
- 1;
143 const GLuint kFirstServiceId2
= kLastServiceId1
+ 1;
145 const GLsizei kFirstDeleteRange
= std::numeric_limits
<GLsizei
>::max();
146 const GLsizei kSecondDeleteRange
= kRange2
- (kFirstDeleteRange
- kRange1
);
147 const GLuint kSecondDeleteFirstServiceId
=
148 kFirstServiceId1
+ kFirstDeleteRange
;
150 EXPECT_CALL(*gl_
, DeletePathsNV(kFirstServiceId1
,
151 std::numeric_limits
<GLsizei
>::max()))
152 .RetiresOnSaturation();
154 EXPECT_CALL(*gl_
, DeletePathsNV(kSecondDeleteFirstServiceId
,
155 kSecondDeleteRange
)).RetiresOnSaturation();
157 manager_
->CreatePathRange(kFirstClientId1
, kLastClientId1
, kFirstServiceId1
);
158 manager_
->CreatePathRange(kFirstClientId2
, kLastClientId2
, kFirstServiceId2
);
159 manager_
->RemovePaths(0, std::numeric_limits
<GLuint
>::max());