|  | // 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 <GLES2/gl2.h> | 
|  | #include <GLES2/gl2ext.h> | 
|  | #include <GLES2/gl2extchromium.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | #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: | 
|  | void SetUp() override { gl_.Initialize(GLManager::Options()); } | 
|  |  | 
|  | void TearDown() override { 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::Now(); | 
|  |  | 
|  | // 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::Now(); | 
|  |  | 
|  | // 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_LE(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<uint32_t>(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<uint32_t>(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; | 
|  | } | 
|  |  | 
|  | base::TimeTicks before = base::TimeTicks::Now(); | 
|  |  | 
|  | 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); | 
|  |  | 
|  | base::TimeTicks after = base::TimeTicks::Now(); | 
|  | // Sanity check - the resulting delta is shorter than the time it took to | 
|  | // run this test. | 
|  | EXPECT_LE(result, base::TimeDelta(after - before).InMicroseconds()); | 
|  |  | 
|  | 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 |