// Copyright 2014 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 #include #include #include "base/threading/platform_thread.h" #include "gpu/command_buffer/tests/gl_manager.h" #include "gpu/command_buffer/tests/gl_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace gpu { class QueryTest : public testing::Test { protected: virtual void SetUp() { gl_.Initialize(GLManager::Options()); } virtual void TearDown() { gl_.Destroy(); } GLManager gl_; }; TEST_F(QueryTest, MultipleQueries) { EXPECT_TRUE(GLTestHelper::HasExtension("GL_CHROMIUM_get_error_query")); EXPECT_TRUE(GLTestHelper::HasExtension( "GL_CHROMIUM_command_buffer_latency_query")); GLuint error_query = 0; GLuint commands_issue_query = 0; glGenQueriesEXT(1, &error_query); glGenQueriesEXT(1, &commands_issue_query); GLuint available; GLuint result; base::TimeTicks before = base::TimeTicks::HighResNow(); // Begin two queries of different types glBeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, commands_issue_query); glBeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, error_query); glEnable(GL_TEXTURE_2D); // Generates an INVALID_ENUM error // End the two queries glEndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); glEndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); glFinish(); base::TimeTicks after = base::TimeTicks::HighResNow(); // Check that we got result on both queries. available = 0; result = 0; glGetQueryObjectuivEXT(commands_issue_query, GL_QUERY_RESULT_AVAILABLE_EXT, &available); EXPECT_TRUE(available); glGetQueryObjectuivEXT(commands_issue_query, GL_QUERY_RESULT_EXT, &result); // Sanity check - the resulting delta is shorter than the time it took to // run this test. EXPECT_LT(result, base::TimeDelta(after - before).InMicroseconds()); result = 0; available = 0; glGetQueryObjectuivEXT(error_query, GL_QUERY_RESULT_AVAILABLE_EXT, &available); EXPECT_TRUE(available); glGetQueryObjectuivEXT(error_query, GL_QUERY_RESULT_EXT, &result); EXPECT_EQ(static_cast(GL_INVALID_ENUM), result); } TEST_F(QueryTest, GetErrorBasic) { EXPECT_TRUE(GLTestHelper::HasExtension("GL_CHROMIUM_get_error_query")); GLuint query = 0; glGenQueriesEXT(1, &query); GLuint query_status = 0; GLuint result = 0; glBeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, query); glEnable(GL_TEXTURE_2D); // Generates an INVALID_ENUM error glEndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM); glFinish(); query_status = 0; result = 0; glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &result); EXPECT_TRUE(result); glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &query_status); EXPECT_EQ(static_cast(GL_INVALID_ENUM), query_status); } TEST_F(QueryTest, DISABLED_LatencyQueryBasic) { EXPECT_TRUE(GLTestHelper::HasExtension( "GL_CHROMIUM_command_buffer_latency_query")); GLuint query = 0; glGenQueriesEXT(1, &query); GLuint query_result = 0; GLuint available = 0; // First test a query with a ~1ms "latency". const unsigned int kExpectedLatencyMicroseconds = 2000; const unsigned int kTimePrecisionMicroseconds = 1000; glBeginQueryEXT(GL_LATENCY_QUERY_CHROMIUM, query); // Usually, we want to measure gpu-side latency, but we fake it by // adding client side latency for our test because it's easier. base::PlatformThread::Sleep( base::TimeDelta::FromMicroseconds(kExpectedLatencyMicroseconds)); glEndQueryEXT(GL_LATENCY_QUERY_CHROMIUM); glFinish(); query_result = 0; available = 0; glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &available); EXPECT_TRUE(available); glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &query_result); EXPECT_GE(query_result, kExpectedLatencyMicroseconds - kTimePrecisionMicroseconds); EXPECT_LE(query_result, kExpectedLatencyMicroseconds + kTimePrecisionMicroseconds); // Then test a query with the lowest latency possible. glBeginQueryEXT(GL_LATENCY_QUERY_CHROMIUM, query); glEndQueryEXT(GL_LATENCY_QUERY_CHROMIUM); glFinish(); query_result = 0; available = 0; glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &available); EXPECT_TRUE(available); glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &query_result); EXPECT_LE(query_result, kTimePrecisionMicroseconds); } TEST_F(QueryTest, CommandsCompleted) { if (!GLTestHelper::HasExtension("GL_CHROMIUM_sync_query")) { LOG(INFO) << "GL_CHROMIUM_sync_query not supported. Skipping test..."; return; } GLuint query; glGenQueriesEXT(1, &query); glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query); glClearColor(0.0, 0.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); glFlush(); GLuint result = 0; glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_EXT, &result); EXPECT_EQ(0u, result); glDeleteQueriesEXT(1, &query); GLTestHelper::CheckGLError("no errors", __LINE__); } TEST_F(QueryTest, CommandsCompletedWithFinish) { if (!GLTestHelper::HasExtension("GL_CHROMIUM_sync_query")) { LOG(INFO) << "GL_CHROMIUM_sync_query not supported. Skipping test..."; return; } GLuint query; glGenQueriesEXT(1, &query); glBeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, query); glClearColor(0.0, 0.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glEndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM); glFinish(); GLuint result = 0; glGetQueryObjectuivEXT(query, GL_QUERY_RESULT_AVAILABLE_EXT, &result); EXPECT_EQ(1u, result); glDeleteQueriesEXT(1, &query); GLTestHelper::CheckGLError("no errors", __LINE__); } } // namespace gpu