| // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/command_buffer/service/path_manager.h" |
| |
| #include <memory> |
| |
| #include "gpu/command_buffer/service/gpu_service_test.h" |
| #include "gpu/command_buffer/service/mocks.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gl/gl_mock.h" |
| |
| namespace gpu { |
| namespace gles2 { |
| |
| class PathManagerTest : public GpuServiceTest { |
| public: |
| PathManagerTest() = default; |
| |
| protected: |
| void SetUp() override { |
| SetUpWithGLVersion("3.0", "GL_NV_path_rendering"); |
| manager_.reset(new PathManager()); |
| } |
| |
| void TearDown() override { |
| manager_->Destroy(true); |
| manager_.reset(); |
| GpuServiceTest::TearDown(); |
| } |
| |
| std::unique_ptr<PathManager> manager_; |
| }; |
| |
| TEST_F(PathManagerTest, Basic) { |
| const GLuint kClient1Id = 1; |
| const GLuint kService1Id = 11; |
| const GLuint kClient2Id = 2; |
| GLuint service_id = 0; |
| manager_->CreatePathRange(kClient1Id, kClient1Id, kService1Id); |
| ASSERT_TRUE(manager_->HasPathsInRange(kClient1Id, kClient1Id)); |
| EXPECT_TRUE(manager_->GetPath(kClient1Id, &service_id)); |
| EXPECT_EQ(kService1Id, service_id); |
| |
| // Check we get nothing for a non-existent path. |
| service_id = 123u; |
| ASSERT_FALSE(manager_->HasPathsInRange(kClient2Id, kClient2Id)); |
| EXPECT_FALSE(manager_->GetPath(kClient2Id, &service_id)); |
| EXPECT_EQ(123u, service_id); |
| |
| // Check trying to remove non-existent paths does not crash. |
| manager_->RemovePaths(kClient2Id, kClient2Id); |
| |
| // Check that it gets deleted when the last reference is released. |
| EXPECT_CALL(*gl_, DeletePathsNV(kService1Id, 1)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| // Check we can't get the path after we remove it. |
| manager_->RemovePaths(kClient1Id, kClient1Id); |
| ASSERT_FALSE(manager_->HasPathsInRange(kClient1Id, kClient1Id)); |
| EXPECT_FALSE(manager_->GetPath(kClient1Id, &service_id)); |
| } |
| |
| // Tests that path manager does not merge ranges that contain service ids that |
| // prevent the merging. Path ranges A and B can be merged if |
| // * client ids of B start immediately after the last client id of A |
| // * service ids of B start immediately after the last service id of A |
| // and similarly for the 'before' case. |
| TEST_F(PathManagerTest, NonContiguousServiceIds) { |
| const GLuint kMergeCheckRange = 54; |
| |
| const struct { |
| GLuint first_client_id; |
| GLuint last_client_id; |
| GLuint first_service_id; |
| } kIdRanges[] = {{500, 1000, 900}, {1001, 1155, 1}, {200, 499, 4888}}; |
| for (auto& range : kIdRanges) { |
| manager_->CreatePathRange(range.first_client_id, range.last_client_id, |
| range.first_service_id); |
| ASSERT_TRUE(manager_->HasPathsInRange(range.first_client_id, |
| range.first_client_id)); |
| ASSERT_TRUE( |
| manager_->HasPathsInRange(range.last_client_id, range.last_client_id)); |
| ASSERT_TRUE( |
| manager_->HasPathsInRange(range.first_client_id, range.last_client_id)); |
| GLuint service_id = 0u; |
| EXPECT_TRUE(manager_->GetPath(range.first_client_id + 5u, &service_id)); |
| EXPECT_EQ(range.first_service_id + 5u, service_id); |
| } |
| |
| // Insert a mergeable range last, to check that merges |
| // work. Otherwise the test could succeed because merges were not |
| // working. |
| auto& merge_candidate = kIdRanges[1]; |
| GLuint merge_candidate_range = |
| merge_candidate.last_client_id - merge_candidate.first_client_id + 1; |
| manager_->CreatePathRange( |
| merge_candidate.last_client_id + 1, |
| merge_candidate.last_client_id + kMergeCheckRange, |
| merge_candidate.first_service_id + merge_candidate_range); |
| |
| // We detect that ranges were not merged accidentally by detecting individual |
| // deletes. |
| for (auto& range : kIdRanges) { |
| if (&range == &merge_candidate) |
| continue; |
| GLsizei range_amount = range.last_client_id - range.first_client_id + 1; |
| EXPECT_CALL(*gl_, DeletePathsNV(range.first_service_id, range_amount)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| // Just a check that merges work. |
| EXPECT_CALL(*gl_, DeletePathsNV(merge_candidate.first_service_id, |
| merge_candidate_range + kMergeCheckRange)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| // Remove all ids. This should cause the expected amount of DeletePathsNV |
| // calls. |
| manager_->RemovePaths(1, std::numeric_limits<GLsizei>::max()); |
| |
| for (auto& range : kIdRanges) { |
| ASSERT_FALSE( |
| manager_->HasPathsInRange(range.first_client_id, range.last_client_id)); |
| } |
| } |
| |
| TEST_F(PathManagerTest, DeleteBigRange) { |
| // Allocates two ranges which in path manager end up merging as one |
| // big range. The range will be too big to fit in one DeletePaths |
| // call. Test that the range is deleted correctly with two calls. |
| const GLuint kFirstClientId1 = 1; |
| const GLsizei kRange1 = std::numeric_limits<GLsizei>::max() - 3; |
| const GLuint kLastClientId1 = kFirstClientId1 + kRange1 - 1; |
| const GLuint kFirstServiceId1 = 77; |
| const GLuint kLastServiceId1 = kFirstServiceId1 + kRange1 - 1; |
| |
| const GLuint kFirstClientId2 = kLastClientId1 + 1; |
| const GLsizei kRange2 = 15; |
| const GLuint kLastClientId2 = kFirstClientId2 + kRange2 - 1; |
| const GLuint kFirstServiceId2 = kLastServiceId1 + 1; |
| |
| const GLsizei kFirstDeleteRange = std::numeric_limits<GLsizei>::max(); |
| const GLsizei kSecondDeleteRange = kRange2 - (kFirstDeleteRange - kRange1); |
| const GLuint kSecondDeleteFirstServiceId = |
| kFirstServiceId1 + kFirstDeleteRange; |
| |
| EXPECT_CALL(*gl_, DeletePathsNV(kFirstServiceId1, |
| std::numeric_limits<GLsizei>::max())) |
| .RetiresOnSaturation(); |
| |
| EXPECT_CALL(*gl_, DeletePathsNV(kSecondDeleteFirstServiceId, |
| kSecondDeleteRange)).RetiresOnSaturation(); |
| |
| manager_->CreatePathRange(kFirstClientId1, kLastClientId1, kFirstServiceId1); |
| manager_->CreatePathRange(kFirstClientId2, kLastClientId2, kFirstServiceId2); |
| manager_->RemovePaths(0, std::numeric_limits<GLuint>::max()); |
| } |
| |
| } // namespace gles2 |
| |
| } // namespace gpu |