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/query_manager.h"
6 #include "gpu/command_buffer/common/gles2_cmd_format.h"
7 #include "gpu/command_buffer/service/cmd_buffer_engine.h"
8 #include "gpu/command_buffer/service/error_state_mock.h"
9 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
10 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
11 #include "gpu/command_buffer/service/feature_info.h"
12 #include "gpu/command_buffer/service/test_helper.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/gl/gl_mock.h"
17 using ::testing::InSequence;
18 using ::testing::Return;
19 using ::testing::SetArgumentPointee;
24 class QueryManagerTest : public testing::Test {
26 static const int32 kSharedMemoryId = 401;
27 static const size_t kSharedBufferSize = 2048;
28 static const uint32 kSharedMemoryOffset = 132;
29 static const int32 kInvalidSharedMemoryId = 402;
30 static const uint32 kInvalidSharedMemoryOffset = kSharedBufferSize + 1;
31 static const uint32 kInitialResult = 0xBDBDBDBDu;
32 static const uint8 kInitialMemoryValue = 0xBDu;
36 virtual ~QueryManagerTest() {
40 virtual void SetUp() {
41 gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>());
42 ::gfx::MockGLInterface::SetGLInterface(gl_.get());
43 engine_.reset(new MockCommandBufferEngine());
44 decoder_.reset(new MockGLES2Decoder());
45 decoder_->set_engine(engine_.get());
46 TestHelper::SetupFeatureInfoInitExpectations(
48 "GL_EXT_occlusion_query_boolean");
49 scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
50 feature_info->Initialize();
51 manager_.reset(new QueryManager(decoder_.get(), feature_info.get()));
54 virtual void TearDown() {
56 manager_->Destroy(false);
59 ::gfx::MockGLInterface::SetGLInterface(NULL);
63 QueryManager::Query* CreateQuery(
64 GLenum target, GLuint client_id, int32 shm_id, uint32 shm_offset,
66 EXPECT_CALL(*gl_, GenQueriesARB(1, _))
67 .WillOnce(SetArgumentPointee<1>(service_id))
68 .RetiresOnSaturation();
69 return manager_->CreateQuery(target, client_id, shm_id, shm_offset);
72 void QueueQuery(QueryManager::Query* query,
74 base::subtle::Atomic32 submit_count) {
75 EXPECT_CALL(*gl_, BeginQueryARB(query->target(), service_id))
77 .RetiresOnSaturation();
78 EXPECT_CALL(*gl_, EndQueryARB(query->target()))
80 .RetiresOnSaturation();
81 EXPECT_TRUE(manager_->BeginQuery(query));
82 EXPECT_TRUE(manager_->EndQuery(query, submit_count));
85 // Use StrictMock to make 100% sure we know how GL will be called.
86 scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
87 scoped_ptr<MockGLES2Decoder> decoder_;
88 scoped_ptr<QueryManager> manager_;
91 class MockCommandBufferEngine : public CommandBufferEngine {
93 MockCommandBufferEngine() {
94 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
95 shared_memory->CreateAndMapAnonymous(kSharedBufferSize);
97 MakeBufferFromSharedMemory(shared_memory.Pass(), kSharedBufferSize);
98 data_ = static_cast<uint8*>(valid_buffer_->memory());
102 virtual ~MockCommandBufferEngine() {
105 virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id)
107 return shm_id == kSharedMemoryId ? valid_buffer_ : invalid_buffer_;
110 void ClearSharedMemory() {
111 memset(data_, kInitialMemoryValue, kSharedBufferSize);
114 virtual void set_token(int32 token) OVERRIDE {
118 virtual bool SetGetBuffer(int32 /* transfer_buffer_id */) OVERRIDE {
123 // Overridden from CommandBufferEngine.
124 virtual bool SetGetOffset(int32 offset) OVERRIDE {
129 // Overridden from CommandBufferEngine.
130 virtual int32 GetGetOffset() OVERRIDE {
137 scoped_refptr<gpu::Buffer> valid_buffer_;
138 scoped_refptr<gpu::Buffer> invalid_buffer_;
141 scoped_ptr<MockCommandBufferEngine> engine_;
144 // GCC requires these declarations, but MSVC requires they not be present
145 #ifndef COMPILER_MSVC
146 const int32 QueryManagerTest::kSharedMemoryId;
147 const size_t QueryManagerTest::kSharedBufferSize;
148 const uint32 QueryManagerTest::kSharedMemoryOffset;
149 const int32 QueryManagerTest::kInvalidSharedMemoryId;
150 const uint32 QueryManagerTest::kInvalidSharedMemoryOffset;
151 const uint32 QueryManagerTest::kInitialResult;
152 const uint8 QueryManagerTest::kInitialMemoryValue;
155 TEST_F(QueryManagerTest, Basic) {
156 const GLuint kClient1Id = 1;
157 const GLuint kService1Id = 11;
158 const GLuint kClient2Id = 2;
160 EXPECT_FALSE(manager_->HavePendingQueries());
161 // Check we can create a Query.
162 scoped_refptr<QueryManager::Query> query(
163 CreateQuery(GL_ANY_SAMPLES_PASSED_EXT, kClient1Id,
164 kSharedMemoryId, kSharedMemoryOffset, kService1Id));
165 ASSERT_TRUE(query.get() != NULL);
166 // Check we can get the same Query.
167 EXPECT_EQ(query.get(), manager_->GetQuery(kClient1Id));
168 // Check we get nothing for a non-existent query.
169 EXPECT_TRUE(manager_->GetQuery(kClient2Id) == NULL);
170 // Check we can delete the query.
171 manager_->RemoveQuery(kClient1Id);
172 // Check we get nothing for a non-existent query.
173 EXPECT_TRUE(manager_->GetQuery(kClient1Id) == NULL);
174 // Check query is deleted
175 EXPECT_TRUE(query->IsDeleted());
176 EXPECT_FALSE(manager_->HavePendingQueries());
179 TEST_F(QueryManagerTest, Destroy) {
180 const GLuint kClient1Id = 1;
181 const GLuint kService1Id = 11;
184 scoped_refptr<QueryManager::Query> query(
185 CreateQuery(GL_ANY_SAMPLES_PASSED_EXT, kClient1Id,
186 kSharedMemoryId, kSharedMemoryOffset, kService1Id));
187 ASSERT_TRUE(query.get() != NULL);
188 EXPECT_CALL(*gl_, DeleteQueriesARB(1, ::testing::Pointee(kService1Id)))
190 .RetiresOnSaturation();
191 manager_->Destroy(true);
192 // Check we get nothing for a non-existent query.
193 EXPECT_TRUE(manager_->GetQuery(kClient1Id) == NULL);
194 // Check query is deleted
195 EXPECT_TRUE(query->IsDeleted());
198 TEST_F(QueryManagerTest, QueryBasic) {
199 const GLuint kClient1Id = 1;
200 const GLuint kService1Id = 11;
201 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
204 scoped_refptr<QueryManager::Query> query(
205 CreateQuery(kTarget, kClient1Id,
206 kSharedMemoryId, kSharedMemoryOffset, kService1Id));
207 ASSERT_TRUE(query.get() != NULL);
209 EXPECT_TRUE(query->IsValid());
210 EXPECT_FALSE(query->IsDeleted());
211 EXPECT_FALSE(query->pending());
212 EXPECT_EQ(kTarget, query->target());
213 EXPECT_EQ(kSharedMemoryId, query->shm_id());
214 EXPECT_EQ(kSharedMemoryOffset, query->shm_offset());
217 TEST_F(QueryManagerTest, ProcessPendingQuery) {
218 const GLuint kClient1Id = 1;
219 const GLuint kService1Id = 11;
220 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
221 const base::subtle::Atomic32 kSubmitCount = 123;
222 const GLuint kResult = 1;
224 // Check nothing happens if there are no pending queries.
225 EXPECT_TRUE(manager_->ProcessPendingQueries());
228 scoped_refptr<QueryManager::Query> query(
229 CreateQuery(kTarget, kClient1Id,
230 kSharedMemoryId, kSharedMemoryOffset, kService1Id));
231 ASSERT_TRUE(query.get() != NULL);
233 // Setup shared memory like client would.
234 QuerySync* sync = decoder_->GetSharedMemoryAs<QuerySync*>(
235 kSharedMemoryId, kSharedMemoryOffset, sizeof(*sync));
236 ASSERT_TRUE(sync != NULL);
240 QueueQuery(query.get(), kService1Id, kSubmitCount);
241 EXPECT_TRUE(query->pending());
242 EXPECT_TRUE(manager_->HavePendingQueries());
244 // Process with return not available.
245 // Expect 1 GL command.
247 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
248 .WillOnce(SetArgumentPointee<2>(0))
249 .RetiresOnSaturation();
250 EXPECT_TRUE(manager_->ProcessPendingQueries());
251 EXPECT_TRUE(query->pending());
252 EXPECT_EQ(0, sync->process_count);
253 EXPECT_EQ(0u, sync->result);
255 // Process with return available.
256 // Expect 2 GL commands.
258 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
259 .WillOnce(SetArgumentPointee<2>(1))
260 .RetiresOnSaturation();
262 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_EXT, _))
263 .WillOnce(SetArgumentPointee<2>(kResult))
264 .RetiresOnSaturation();
265 EXPECT_TRUE(manager_->ProcessPendingQueries());
266 EXPECT_FALSE(query->pending());
267 EXPECT_EQ(kSubmitCount, sync->process_count);
268 EXPECT_EQ(kResult, sync->result);
269 EXPECT_FALSE(manager_->HavePendingQueries());
271 // Process with no queries.
272 // Expect no GL commands/
273 EXPECT_TRUE(manager_->ProcessPendingQueries());
276 TEST_F(QueryManagerTest, ProcessPendingQueries) {
277 const GLuint kClient1Id = 1;
278 const GLuint kService1Id = 11;
279 const GLuint kClient2Id = 2;
280 const GLuint kService2Id = 12;
281 const GLuint kClient3Id = 3;
282 const GLuint kService3Id = 13;
283 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
284 const base::subtle::Atomic32 kSubmitCount1 = 123;
285 const base::subtle::Atomic32 kSubmitCount2 = 123;
286 const base::subtle::Atomic32 kSubmitCount3 = 123;
287 const GLuint kResult1 = 1;
288 const GLuint kResult2 = 1;
289 const GLuint kResult3 = 1;
291 // Setup shared memory like client would.
292 QuerySync* sync1 = decoder_->GetSharedMemoryAs<QuerySync*>(
293 kSharedMemoryId, kSharedMemoryOffset, sizeof(*sync1) * 3);
294 ASSERT_TRUE(sync1 != NULL);
295 QuerySync* sync2 = sync1 + 1;
296 QuerySync* sync3 = sync2 + 1;
299 scoped_refptr<QueryManager::Query> query1(
300 CreateQuery(kTarget, kClient1Id,
301 kSharedMemoryId, kSharedMemoryOffset + sizeof(*sync1) * 0,
303 scoped_refptr<QueryManager::Query> query2(
304 CreateQuery(kTarget, kClient2Id,
305 kSharedMemoryId, kSharedMemoryOffset + sizeof(*sync1) * 1,
307 scoped_refptr<QueryManager::Query> query3(
308 CreateQuery(kTarget, kClient3Id,
309 kSharedMemoryId, kSharedMemoryOffset + sizeof(*sync1) * 2,
311 ASSERT_TRUE(query1.get() != NULL);
312 ASSERT_TRUE(query2.get() != NULL);
313 ASSERT_TRUE(query3.get() != NULL);
314 EXPECT_FALSE(manager_->HavePendingQueries());
321 QueueQuery(query1.get(), kService1Id, kSubmitCount1);
322 QueueQuery(query2.get(), kService2Id, kSubmitCount2);
323 QueueQuery(query3.get(), kService3Id, kSubmitCount3);
324 EXPECT_TRUE(query1->pending());
325 EXPECT_TRUE(query2->pending());
326 EXPECT_TRUE(query3->pending());
327 EXPECT_TRUE(manager_->HavePendingQueries());
329 // Process with return available for first 2 queries.
330 // Expect 4 GL commands.
334 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
335 .WillOnce(SetArgumentPointee<2>(1))
336 .RetiresOnSaturation();
338 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_EXT, _))
339 .WillOnce(SetArgumentPointee<2>(kResult1))
340 .RetiresOnSaturation();
342 GetQueryObjectuivARB(kService2Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
343 .WillOnce(SetArgumentPointee<2>(1))
344 .RetiresOnSaturation();
346 GetQueryObjectuivARB(kService2Id, GL_QUERY_RESULT_EXT, _))
347 .WillOnce(SetArgumentPointee<2>(kResult2))
348 .RetiresOnSaturation();
350 GetQueryObjectuivARB(kService3Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
351 .WillOnce(SetArgumentPointee<2>(0))
352 .RetiresOnSaturation();
353 EXPECT_TRUE(manager_->ProcessPendingQueries());
355 EXPECT_FALSE(query1->pending());
356 EXPECT_FALSE(query2->pending());
357 EXPECT_TRUE(query3->pending());
358 EXPECT_EQ(kSubmitCount1, sync1->process_count);
359 EXPECT_EQ(kSubmitCount2, sync2->process_count);
360 EXPECT_EQ(kResult1, sync1->result);
361 EXPECT_EQ(kResult2, sync2->result);
362 EXPECT_EQ(0, sync3->process_count);
363 EXPECT_EQ(0u, sync3->result);
364 EXPECT_TRUE(manager_->HavePendingQueries());
366 // Process with renaming query. No result.
367 // Expect 1 GL commands.
369 GetQueryObjectuivARB(kService3Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
370 .WillOnce(SetArgumentPointee<2>(0))
371 .RetiresOnSaturation();
372 EXPECT_TRUE(manager_->ProcessPendingQueries());
373 EXPECT_TRUE(query3->pending());
374 EXPECT_EQ(0, sync3->process_count);
375 EXPECT_EQ(0u, sync3->result);
376 EXPECT_TRUE(manager_->HavePendingQueries());
378 // Process with renaming query. With result.
379 // Expect 2 GL commands.
381 GetQueryObjectuivARB(kService3Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
382 .WillOnce(SetArgumentPointee<2>(1))
383 .RetiresOnSaturation();
385 GetQueryObjectuivARB(kService3Id, GL_QUERY_RESULT_EXT, _))
386 .WillOnce(SetArgumentPointee<2>(kResult3))
387 .RetiresOnSaturation();
388 EXPECT_TRUE(manager_->ProcessPendingQueries());
389 EXPECT_FALSE(query3->pending());
390 EXPECT_EQ(kSubmitCount3, sync3->process_count);
391 EXPECT_EQ(kResult3, sync3->result);
392 EXPECT_FALSE(manager_->HavePendingQueries());
395 TEST_F(QueryManagerTest, ProcessPendingBadSharedMemoryId) {
396 const GLuint kClient1Id = 1;
397 const GLuint kService1Id = 11;
398 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
399 const base::subtle::Atomic32 kSubmitCount = 123;
400 const GLuint kResult = 1;
403 scoped_refptr<QueryManager::Query> query(
404 CreateQuery(kTarget, kClient1Id,
405 kInvalidSharedMemoryId, kSharedMemoryOffset, kService1Id));
406 ASSERT_TRUE(query.get() != NULL);
409 QueueQuery(query.get(), kService1Id, kSubmitCount);
411 // Process with return available.
412 // Expect 2 GL commands.
414 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
415 .WillOnce(SetArgumentPointee<2>(1))
416 .RetiresOnSaturation();
418 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_EXT, _))
419 .WillOnce(SetArgumentPointee<2>(kResult))
420 .RetiresOnSaturation();
421 EXPECT_FALSE(manager_->ProcessPendingQueries());
424 TEST_F(QueryManagerTest, ProcessPendingBadSharedMemoryOffset) {
425 const GLuint kClient1Id = 1;
426 const GLuint kService1Id = 11;
427 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
428 const base::subtle::Atomic32 kSubmitCount = 123;
429 const GLuint kResult = 1;
432 scoped_refptr<QueryManager::Query> query(
433 CreateQuery(kTarget, kClient1Id,
434 kSharedMemoryId, kInvalidSharedMemoryOffset, kService1Id));
435 ASSERT_TRUE(query.get() != NULL);
438 QueueQuery(query.get(), kService1Id, kSubmitCount);
440 // Process with return available.
441 // Expect 2 GL commands.
443 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_AVAILABLE_EXT, _))
444 .WillOnce(SetArgumentPointee<2>(1))
445 .RetiresOnSaturation();
447 GetQueryObjectuivARB(kService1Id, GL_QUERY_RESULT_EXT, _))
448 .WillOnce(SetArgumentPointee<2>(kResult))
449 .RetiresOnSaturation();
450 EXPECT_FALSE(manager_->ProcessPendingQueries());
453 TEST_F(QueryManagerTest, ExitWithPendingQuery) {
454 const GLuint kClient1Id = 1;
455 const GLuint kService1Id = 11;
456 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
457 const base::subtle::Atomic32 kSubmitCount = 123;
460 scoped_refptr<QueryManager::Query> query(
461 CreateQuery(kTarget, kClient1Id,
462 kSharedMemoryId, kSharedMemoryOffset, kService1Id));
463 ASSERT_TRUE(query.get() != NULL);
466 QueueQuery(query.get(), kService1Id, kSubmitCount);
469 // Test that when based on ARB_occlusion_query2 we use GL_ANY_SAMPLES_PASSED_ARB
470 // for GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
471 TEST_F(QueryManagerTest, ARBOcclusionQuery2) {
472 const GLuint kClient1Id = 1;
473 const GLuint kService1Id = 11;
474 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT;
475 const base::subtle::Atomic32 kSubmitCount = 123;
477 TestHelper::SetupFeatureInfoInitExpectations(
479 "GL_ARB_occlusion_query2");
480 scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
481 feature_info->Initialize();
482 scoped_ptr<QueryManager> manager(
483 new QueryManager(decoder_.get(), feature_info.get()));
485 EXPECT_CALL(*gl_, GenQueriesARB(1, _))
486 .WillOnce(SetArgumentPointee<1>(kService1Id))
487 .RetiresOnSaturation();
488 QueryManager::Query* query = manager->CreateQuery(
489 kTarget, kClient1Id, kSharedMemoryId, kSharedMemoryOffset);
490 ASSERT_TRUE(query != NULL);
492 EXPECT_CALL(*gl_, BeginQueryARB(GL_ANY_SAMPLES_PASSED_EXT, kService1Id))
494 .RetiresOnSaturation();
495 EXPECT_CALL(*gl_, EndQueryARB(GL_ANY_SAMPLES_PASSED_EXT))
497 .RetiresOnSaturation();
498 EXPECT_TRUE(manager->BeginQuery(query));
499 EXPECT_TRUE(manager->EndQuery(query, kSubmitCount));
500 manager->Destroy(false);
503 // Test that when based on ARB_occlusion_query we use GL_SAMPLES_PASSED_ARB
504 // for GL_ANY_SAMPLES_PASSED_EXT
505 TEST_F(QueryManagerTest, ARBOcclusionQuery) {
506 const GLuint kClient1Id = 1;
507 const GLuint kService1Id = 11;
508 const GLenum kTarget = GL_ANY_SAMPLES_PASSED_EXT;
509 const base::subtle::Atomic32 kSubmitCount = 123;
511 TestHelper::SetupFeatureInfoInitExpectations(
513 "GL_ARB_occlusion_query");
514 scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
515 feature_info->Initialize();
516 scoped_ptr<QueryManager> manager(
517 new QueryManager(decoder_.get(), feature_info.get()));
519 EXPECT_CALL(*gl_, GenQueriesARB(1, _))
520 .WillOnce(SetArgumentPointee<1>(kService1Id))
521 .RetiresOnSaturation();
522 QueryManager::Query* query = manager->CreateQuery(
523 kTarget, kClient1Id, kSharedMemoryId, kSharedMemoryOffset);
524 ASSERT_TRUE(query != NULL);
526 EXPECT_CALL(*gl_, BeginQueryARB(GL_SAMPLES_PASSED_ARB, kService1Id))
528 .RetiresOnSaturation();
529 EXPECT_CALL(*gl_, EndQueryARB(GL_SAMPLES_PASSED_ARB))
531 .RetiresOnSaturation();
532 EXPECT_TRUE(manager->BeginQuery(query));
533 EXPECT_TRUE(manager->EndQuery(query, kSubmitCount));
534 manager->Destroy(false);
537 TEST_F(QueryManagerTest, GetErrorQuery) {
538 const GLuint kClient1Id = 1;
539 const GLenum kTarget = GL_GET_ERROR_QUERY_CHROMIUM;
540 const base::subtle::Atomic32 kSubmitCount = 123;
542 TestHelper::SetupFeatureInfoInitExpectations(gl_.get(), "");
543 scoped_refptr<FeatureInfo> feature_info(new FeatureInfo());
544 feature_info->Initialize();
545 scoped_ptr<QueryManager> manager(
546 new QueryManager(decoder_.get(), feature_info.get()));
548 QueryManager::Query* query = manager->CreateQuery(
549 kTarget, kClient1Id, kSharedMemoryId, kSharedMemoryOffset);
550 ASSERT_TRUE(query != NULL);
552 // Setup shared memory like client would.
553 QuerySync* sync = decoder_->GetSharedMemoryAs<QuerySync*>(
554 kSharedMemoryId, kSharedMemoryOffset, sizeof(*sync));
555 ASSERT_TRUE(sync != NULL);
558 EXPECT_TRUE(manager->BeginQuery(query));
560 MockErrorState mock_error_state;
561 EXPECT_CALL(*decoder_.get(), GetErrorState())
562 .WillRepeatedly(Return(&mock_error_state));
563 EXPECT_CALL(mock_error_state, GetGLError())
564 .WillOnce(Return(GL_INVALID_ENUM))
565 .RetiresOnSaturation();
567 EXPECT_TRUE(manager->EndQuery(query, kSubmitCount));
568 EXPECT_FALSE(query->pending());
570 EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), sync->result);
572 manager->Destroy(false);