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/feature_info.h"
10 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
11 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
12 #include "gpu/command_buffer/service/gpu_service_test.h"
13 #include "gpu/command_buffer/service/test_helper.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/gl/gl_context.h"
16 #include "ui/gl/gl_mock.h"
17 #include "ui/gl/gpu_timing.h"
18 #include "ui/gl/gpu_timing_fake.h"
21 using ::testing::InSequence
;
22 using ::testing::Return
;
23 using ::testing::SetArgumentPointee
;
28 class QueryManagerTest
: public GpuServiceTest
{
30 static const int32 kSharedMemoryId
= 401;
31 static const uint32 kSharedMemoryOffset
= 132;
32 static const int32 kSharedMemory2Id
= 402;
33 static const uint32 kSharedMemory2Offset
= 232;
34 static const size_t kSharedBufferSize
= 2048;
35 static const int32 kInvalidSharedMemoryId
= 403;
36 static const uint32 kInvalidSharedMemoryOffset
= kSharedBufferSize
+ 1;
37 static const uint32 kInitialResult
= 0xBDBDBDBDu
;
38 static const uint8 kInitialMemoryValue
= 0xBDu
;
42 ~QueryManagerTest() override
{}
45 void SetUp() override
{
46 GpuServiceTest::SetUpWithGLVersion("3.2",
47 "GL_ARB_occlusion_query, "
48 "GL_ARB_timer_query");
49 SetUpMockGL("GL_EXT_occlusion_query_boolean, GL_ARB_timer_query");
52 void TearDown() override
{
54 manager_
->Destroy(false);
57 GpuServiceTest::TearDown();
60 void SetUpMockGL(const char* extension_expectations
) {
61 engine_
.reset(new MockCommandBufferEngine());
62 decoder_
.reset(new MockGLES2Decoder());
63 decoder_
->set_engine(engine_
.get());
64 TestHelper::SetupFeatureInfoInitExpectations(
65 gl_
.get(), extension_expectations
);
66 EXPECT_CALL(*decoder_
.get(), GetGLContext())
67 .WillRepeatedly(Return(GetGLContext()));
68 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
69 feature_info
->Initialize();
70 manager_
.reset(new QueryManager(decoder_
.get(), feature_info
.get()));
73 QueryManager::Query
* CreateQuery(
74 GLenum target
, GLuint client_id
, int32 shm_id
, uint32 shm_offset
,
76 EXPECT_CALL(*gl_
, GenQueries(1, _
))
77 .WillOnce(SetArgumentPointee
<1>(service_id
))
78 .RetiresOnSaturation();
79 return manager_
->CreateQuery(target
, client_id
, shm_id
, shm_offset
);
82 void QueueQuery(QueryManager::Query
* query
,
84 base::subtle::Atomic32 submit_count
) {
85 EXPECT_CALL(*gl_
, BeginQuery(query
->target(), service_id
))
87 .RetiresOnSaturation();
88 EXPECT_CALL(*gl_
, EndQuery(query
->target()))
90 .RetiresOnSaturation();
91 EXPECT_TRUE(manager_
->BeginQuery(query
));
92 EXPECT_TRUE(manager_
->EndQuery(query
, submit_count
));
95 scoped_ptr
<MockGLES2Decoder
> decoder_
;
96 scoped_ptr
<QueryManager
> manager_
;
99 class MockCommandBufferEngine
: public CommandBufferEngine
{
101 MockCommandBufferEngine() {
102 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
103 shared_memory
->CreateAndMapAnonymous(kSharedBufferSize
);
105 MakeBufferFromSharedMemory(shared_memory
.Pass(), kSharedBufferSize
);
107 scoped_ptr
<base::SharedMemory
> shared_memory2(new base::SharedMemory());
108 shared_memory2
->CreateAndMapAnonymous(kSharedBufferSize
);
110 MakeBufferFromSharedMemory(shared_memory2
.Pass(), kSharedBufferSize
);
115 ~MockCommandBufferEngine() override
{}
117 scoped_refptr
<gpu::Buffer
> GetSharedMemoryBuffer(int32 shm_id
) override
{
119 case kSharedMemoryId
: return valid_buffer_
;
120 case kSharedMemory2Id
: return valid_buffer2_
;
121 default: return invalid_buffer_
;
125 void ClearSharedMemory() {
126 memset(valid_buffer_
->memory(), kInitialMemoryValue
, kSharedBufferSize
);
127 memset(valid_buffer2_
->memory(), kInitialMemoryValue
, kSharedBufferSize
);
130 void set_token(int32 token
) override
{ DCHECK(false); }
132 bool SetGetBuffer(int32
/* transfer_buffer_id */) override
{
137 // Overridden from CommandBufferEngine.
138 bool SetGetOffset(int32 offset
) override
{
143 // Overridden from CommandBufferEngine.
144 int32
GetGetOffset() override
{
150 scoped_refptr
<gpu::Buffer
> valid_buffer_
;
151 scoped_refptr
<gpu::Buffer
> valid_buffer2_
;
152 scoped_refptr
<gpu::Buffer
> invalid_buffer_
;
155 scoped_ptr
<MockCommandBufferEngine
> engine_
;
158 class QueryManagerManualSetupTest
: public QueryManagerTest
{
160 void SetUp() override
{
161 // Let test setup manually.
165 // GCC requires these declarations, but MSVC requires they not be present
166 #ifndef COMPILER_MSVC
167 const int32
QueryManagerTest::kSharedMemoryId
;
168 const uint32
QueryManagerTest::kSharedMemoryOffset
;
169 const int32
QueryManagerTest::kSharedMemory2Id
;
170 const uint32
QueryManagerTest::kSharedMemory2Offset
;
171 const size_t QueryManagerTest::kSharedBufferSize
;
172 const int32
QueryManagerTest::kInvalidSharedMemoryId
;
173 const uint32
QueryManagerTest::kInvalidSharedMemoryOffset
;
174 const uint32
QueryManagerTest::kInitialResult
;
175 const uint8
QueryManagerTest::kInitialMemoryValue
;
178 TEST_F(QueryManagerTest
, Basic
) {
179 const GLuint kClient1Id
= 1;
180 const GLuint kService1Id
= 11;
181 const GLuint kClient2Id
= 2;
183 EXPECT_FALSE(manager_
->HavePendingQueries());
184 // Check we can create a Query.
185 scoped_refptr
<QueryManager::Query
> query(
186 CreateQuery(GL_ANY_SAMPLES_PASSED_EXT
, kClient1Id
,
187 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
188 ASSERT_TRUE(query
.get() != NULL
);
189 // Check we can get the same Query.
190 EXPECT_EQ(query
.get(), manager_
->GetQuery(kClient1Id
));
191 // Check we get nothing for a non-existent query.
192 EXPECT_TRUE(manager_
->GetQuery(kClient2Id
) == NULL
);
193 // Check we can delete the query.
194 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService1Id
)))
196 .RetiresOnSaturation();
197 manager_
->RemoveQuery(kClient1Id
);
198 // Check we get nothing for a non-existent query.
199 EXPECT_TRUE(manager_
->GetQuery(kClient1Id
) == NULL
);
200 // Check query is deleted
201 EXPECT_TRUE(query
->IsDeleted());
202 EXPECT_FALSE(manager_
->HavePendingQueries());
205 TEST_F(QueryManagerTest
, Destroy
) {
206 const GLuint kClient1Id
= 1;
207 const GLuint kService1Id
= 11;
210 scoped_refptr
<QueryManager::Query
> query(
211 CreateQuery(GL_ANY_SAMPLES_PASSED_EXT
, kClient1Id
,
212 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
213 ASSERT_TRUE(query
.get() != NULL
);
214 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService1Id
)))
216 .RetiresOnSaturation();
217 manager_
->Destroy(true);
218 // Check we get nothing for a non-existent query.
219 EXPECT_TRUE(manager_
->GetQuery(kClient1Id
) == NULL
);
220 // Check query is deleted
221 EXPECT_TRUE(query
->IsDeleted());
224 TEST_F(QueryManagerTest
, QueryBasic
) {
225 const GLuint kClient1Id
= 1;
226 const GLuint kService1Id
= 11;
227 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
230 scoped_refptr
<QueryManager::Query
> query(
231 CreateQuery(kTarget
, kClient1Id
,
232 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
233 ASSERT_TRUE(query
.get() != NULL
);
235 EXPECT_TRUE(query
->IsValid());
236 EXPECT_FALSE(query
->IsDeleted());
237 EXPECT_FALSE(query
->IsPending());
238 EXPECT_EQ(kTarget
, query
->target());
239 EXPECT_EQ(kSharedMemoryId
, query
->shm_id());
240 EXPECT_EQ(kSharedMemoryOffset
, query
->shm_offset());
243 TEST_F(QueryManagerTest
, ProcessPendingQuery
) {
244 const GLuint kClient1Id
= 1;
245 const GLuint kService1Id
= 11;
246 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
247 const base::subtle::Atomic32 kSubmitCount
= 123;
248 const GLuint kResult
= 1;
250 // Check nothing happens if there are no pending queries.
251 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
254 scoped_refptr
<QueryManager::Query
> query(
255 CreateQuery(kTarget
, kClient1Id
,
256 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
257 ASSERT_TRUE(query
.get() != NULL
);
259 // Setup shared memory like client would.
260 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
261 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
262 ASSERT_TRUE(sync
!= NULL
);
266 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
267 EXPECT_TRUE(query
->IsPending());
268 EXPECT_TRUE(manager_
->HavePendingQueries());
270 // Process with return not available.
271 // Expect 1 GL command.
273 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
274 .WillOnce(SetArgumentPointee
<2>(0))
275 .RetiresOnSaturation();
276 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
277 EXPECT_TRUE(query
->IsPending());
278 EXPECT_EQ(0, sync
->process_count
);
279 EXPECT_EQ(0u, sync
->result
);
281 // Process with return available.
282 // Expect 2 GL commands.
284 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
285 .WillOnce(SetArgumentPointee
<2>(1))
286 .RetiresOnSaturation();
288 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
289 .WillOnce(SetArgumentPointee
<2>(kResult
))
290 .RetiresOnSaturation();
291 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
292 EXPECT_FALSE(query
->IsPending());
293 EXPECT_EQ(kSubmitCount
, sync
->process_count
);
294 EXPECT_EQ(kResult
, sync
->result
);
295 EXPECT_FALSE(manager_
->HavePendingQueries());
297 // Process with no queries.
298 // Expect no GL commands/
299 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
302 TEST_F(QueryManagerTest
, ProcessPendingQueries
) {
303 const GLuint kClient1Id
= 1;
304 const GLuint kService1Id
= 11;
305 const GLuint kClient2Id
= 2;
306 const GLuint kService2Id
= 12;
307 const GLuint kClient3Id
= 3;
308 const GLuint kService3Id
= 13;
309 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
310 const base::subtle::Atomic32 kSubmitCount1
= 123;
311 const base::subtle::Atomic32 kSubmitCount2
= 123;
312 const base::subtle::Atomic32 kSubmitCount3
= 123;
313 const GLuint kResult1
= 1;
314 const GLuint kResult2
= 1;
315 const GLuint kResult3
= 1;
317 // Setup shared memory like client would.
318 QuerySync
* sync1
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
319 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync1
) * 3);
320 ASSERT_TRUE(sync1
!= NULL
);
321 QuerySync
* sync2
= sync1
+ 1;
322 QuerySync
* sync3
= sync2
+ 1;
325 scoped_refptr
<QueryManager::Query
> query1(
326 CreateQuery(kTarget
, kClient1Id
,
327 kSharedMemoryId
, kSharedMemoryOffset
+ sizeof(*sync1
) * 0,
329 scoped_refptr
<QueryManager::Query
> query2(
330 CreateQuery(kTarget
, kClient2Id
,
331 kSharedMemoryId
, kSharedMemoryOffset
+ sizeof(*sync1
) * 1,
333 scoped_refptr
<QueryManager::Query
> query3(
334 CreateQuery(kTarget
, kClient3Id
,
335 kSharedMemoryId
, kSharedMemoryOffset
+ sizeof(*sync1
) * 2,
337 ASSERT_TRUE(query1
.get() != NULL
);
338 ASSERT_TRUE(query2
.get() != NULL
);
339 ASSERT_TRUE(query3
.get() != NULL
);
340 EXPECT_FALSE(manager_
->HavePendingQueries());
347 QueueQuery(query1
.get(), kService1Id
, kSubmitCount1
);
348 QueueQuery(query2
.get(), kService2Id
, kSubmitCount2
);
349 QueueQuery(query3
.get(), kService3Id
, kSubmitCount3
);
350 EXPECT_TRUE(query1
->IsPending());
351 EXPECT_TRUE(query2
->IsPending());
352 EXPECT_TRUE(query3
->IsPending());
353 EXPECT_TRUE(manager_
->HavePendingQueries());
355 // Process with return available for first 2 queries.
356 // Expect 4 GL commands.
360 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
361 .WillOnce(SetArgumentPointee
<2>(1))
362 .RetiresOnSaturation();
364 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
365 .WillOnce(SetArgumentPointee
<2>(kResult1
))
366 .RetiresOnSaturation();
368 GetQueryObjectuiv(kService2Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
369 .WillOnce(SetArgumentPointee
<2>(1))
370 .RetiresOnSaturation();
372 GetQueryObjectuiv(kService2Id
, GL_QUERY_RESULT_EXT
, _
))
373 .WillOnce(SetArgumentPointee
<2>(kResult2
))
374 .RetiresOnSaturation();
376 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
377 .WillOnce(SetArgumentPointee
<2>(0))
378 .RetiresOnSaturation();
379 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
381 EXPECT_FALSE(query1
->IsPending());
382 EXPECT_FALSE(query2
->IsPending());
383 EXPECT_TRUE(query3
->IsPending());
384 EXPECT_EQ(kSubmitCount1
, sync1
->process_count
);
385 EXPECT_EQ(kSubmitCount2
, sync2
->process_count
);
386 EXPECT_EQ(kResult1
, sync1
->result
);
387 EXPECT_EQ(kResult2
, sync2
->result
);
388 EXPECT_EQ(0, sync3
->process_count
);
389 EXPECT_EQ(0u, sync3
->result
);
390 EXPECT_TRUE(manager_
->HavePendingQueries());
392 // Process with renaming query. No result.
393 // Expect 1 GL commands.
395 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
396 .WillOnce(SetArgumentPointee
<2>(0))
397 .RetiresOnSaturation();
398 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
399 EXPECT_TRUE(query3
->IsPending());
400 EXPECT_EQ(0, sync3
->process_count
);
401 EXPECT_EQ(0u, sync3
->result
);
402 EXPECT_TRUE(manager_
->HavePendingQueries());
404 // Process with renaming query. With result.
405 // Expect 2 GL commands.
407 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
408 .WillOnce(SetArgumentPointee
<2>(1))
409 .RetiresOnSaturation();
411 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_EXT
, _
))
412 .WillOnce(SetArgumentPointee
<2>(kResult3
))
413 .RetiresOnSaturation();
414 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
415 EXPECT_FALSE(query3
->IsPending());
416 EXPECT_EQ(kSubmitCount3
, sync3
->process_count
);
417 EXPECT_EQ(kResult3
, sync3
->result
);
418 EXPECT_FALSE(manager_
->HavePendingQueries());
421 TEST_F(QueryManagerTest
, ProcessPendingBadSharedMemoryId
) {
422 const GLuint kClient1Id
= 1;
423 const GLuint kService1Id
= 11;
424 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
425 const base::subtle::Atomic32 kSubmitCount
= 123;
426 const GLuint kResult
= 1;
429 scoped_refptr
<QueryManager::Query
> query(
430 CreateQuery(kTarget
, kClient1Id
,
431 kInvalidSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
432 ASSERT_TRUE(query
.get() != NULL
);
435 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
437 // Process with return available.
438 // Expect 2 GL commands.
440 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
441 .WillOnce(SetArgumentPointee
<2>(1))
442 .RetiresOnSaturation();
444 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
445 .WillOnce(SetArgumentPointee
<2>(kResult
))
446 .RetiresOnSaturation();
447 EXPECT_FALSE(manager_
->ProcessPendingQueries(false));
450 TEST_F(QueryManagerTest
, ProcessPendingBadSharedMemoryOffset
) {
451 const GLuint kClient1Id
= 1;
452 const GLuint kService1Id
= 11;
453 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
454 const base::subtle::Atomic32 kSubmitCount
= 123;
455 const GLuint kResult
= 1;
458 scoped_refptr
<QueryManager::Query
> query(
459 CreateQuery(kTarget
, kClient1Id
,
460 kSharedMemoryId
, kInvalidSharedMemoryOffset
, kService1Id
));
461 ASSERT_TRUE(query
.get() != NULL
);
464 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
466 // Process with return available.
467 // Expect 2 GL commands.
469 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
470 .WillOnce(SetArgumentPointee
<2>(1))
471 .RetiresOnSaturation();
473 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
474 .WillOnce(SetArgumentPointee
<2>(kResult
))
475 .RetiresOnSaturation();
476 EXPECT_FALSE(manager_
->ProcessPendingQueries(false));
479 TEST_F(QueryManagerTest
, ExitWithPendingQuery
) {
480 const GLuint kClient1Id
= 1;
481 const GLuint kService1Id
= 11;
482 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
483 const base::subtle::Atomic32 kSubmitCount
= 123;
486 scoped_refptr
<QueryManager::Query
> query(
487 CreateQuery(kTarget
, kClient1Id
,
488 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
489 ASSERT_TRUE(query
.get() != NULL
);
492 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
495 // Test that when based on ARB_occlusion_query2 we use GL_ANY_SAMPLES_PASSED_ARB
496 // for GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
497 TEST_F(QueryManagerTest
, ARBOcclusionQuery2
) {
498 const GLuint kClient1Id
= 1;
499 const GLuint kService1Id
= 11;
500 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
;
501 const base::subtle::Atomic32 kSubmitCount
= 123;
503 TestHelper::SetupFeatureInfoInitExpectations(
505 "GL_ARB_occlusion_query2");
506 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
507 feature_info
->Initialize();
508 scoped_ptr
<QueryManager
> manager(
509 new QueryManager(decoder_
.get(), feature_info
.get()));
511 EXPECT_CALL(*gl_
, GenQueries(1, _
))
512 .WillOnce(SetArgumentPointee
<1>(kService1Id
))
513 .RetiresOnSaturation();
514 QueryManager::Query
* query
= manager
->CreateQuery(
515 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
516 ASSERT_TRUE(query
!= NULL
);
518 EXPECT_CALL(*gl_
, BeginQuery(GL_ANY_SAMPLES_PASSED_EXT
, kService1Id
))
520 .RetiresOnSaturation();
521 EXPECT_CALL(*gl_
, EndQuery(GL_ANY_SAMPLES_PASSED_EXT
))
523 .RetiresOnSaturation();
524 EXPECT_TRUE(manager
->BeginQuery(query
));
525 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
526 manager
->Destroy(false);
529 // Test that when based on ARB_occlusion_query we use GL_SAMPLES_PASSED_ARB
530 // for GL_ANY_SAMPLES_PASSED_EXT
531 TEST_F(QueryManagerTest
, ARBOcclusionQuery
) {
532 const GLuint kClient1Id
= 1;
533 const GLuint kService1Id
= 11;
534 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
535 const base::subtle::Atomic32 kSubmitCount
= 123;
537 TestHelper::SetupFeatureInfoInitExpectations(
539 "GL_ARB_occlusion_query");
540 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
541 feature_info
->Initialize();
542 scoped_ptr
<QueryManager
> manager(
543 new QueryManager(decoder_
.get(), feature_info
.get()));
545 EXPECT_CALL(*gl_
, GenQueries(1, _
))
546 .WillOnce(SetArgumentPointee
<1>(kService1Id
))
547 .RetiresOnSaturation();
548 QueryManager::Query
* query
= manager
->CreateQuery(
549 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
550 ASSERT_TRUE(query
!= NULL
);
552 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService1Id
))
554 .RetiresOnSaturation();
555 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
557 .RetiresOnSaturation();
558 EXPECT_TRUE(manager
->BeginQuery(query
));
559 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
560 manager
->Destroy(false);
563 TEST_F(QueryManagerTest
, ARBOcclusionPauseResume
) {
564 const GLuint kClient1Id
= 1;
565 const GLuint kService1Id
= 11;
566 const GLuint kService2Id
= 12;
567 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
568 const base::subtle::Atomic32 kSubmitCount
= 123;
570 TestHelper::SetupFeatureInfoInitExpectations(
572 "GL_ARB_occlusion_query");
573 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
574 feature_info
->Initialize();
575 scoped_ptr
<QueryManager
> manager(
576 new QueryManager(decoder_
.get(), feature_info
.get()));
578 EXPECT_CALL(*gl_
, GenQueries(1, _
))
579 .WillOnce(SetArgumentPointee
<1>(kService1Id
))
580 .RetiresOnSaturation();
581 QueryManager::Query
* query
= manager
->CreateQuery(
582 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
583 ASSERT_TRUE(query
!= NULL
);
585 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService1Id
))
587 .RetiresOnSaturation();
588 EXPECT_TRUE(manager
->BeginQuery(query
));
590 // Pause and Resume the manager.
591 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
593 .RetiresOnSaturation();
594 manager
->PauseQueries();
596 EXPECT_CALL(*gl_
, GenQueries(1, _
))
597 .WillOnce(SetArgumentPointee
<1>(kService2Id
))
598 .RetiresOnSaturation();
599 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService2Id
))
601 .RetiresOnSaturation();
602 manager
->ResumeQueries();
604 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
606 .RetiresOnSaturation();
607 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
609 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService2Id
,
610 GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
611 .WillOnce(SetArgumentPointee
<2>(1u))
612 .RetiresOnSaturation();
613 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService1Id
,
614 GL_QUERY_RESULT_EXT
, _
))
615 .WillOnce(SetArgumentPointee
<2>(0u))
616 .RetiresOnSaturation();
617 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService2Id
,
618 GL_QUERY_RESULT_EXT
, _
))
619 .WillOnce(SetArgumentPointee
<2>(1u))
620 .RetiresOnSaturation();
621 EXPECT_TRUE(manager
->ProcessPendingQueries(false));
622 EXPECT_TRUE(query
->IsFinished());
624 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
625 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
626 EXPECT_EQ(1u, sync
->result
);
628 // Make sure new query still works.
629 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService2Id
)))
631 .RetiresOnSaturation();
632 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService1Id
))
634 .RetiresOnSaturation();
635 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
637 .RetiresOnSaturation();
638 EXPECT_TRUE(manager
->BeginQuery(query
));
639 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
+ 1));
641 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService1Id
,
642 GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
643 .WillOnce(SetArgumentPointee
<2>(1u))
644 .RetiresOnSaturation();
645 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService1Id
,
646 GL_QUERY_RESULT_EXT
, _
))
647 .WillOnce(SetArgumentPointee
<2>(0u))
648 .RetiresOnSaturation();
649 EXPECT_TRUE(manager
->ProcessPendingQueries(false));
650 EXPECT_TRUE(query
->IsFinished());
652 EXPECT_EQ(0u, sync
->result
);
653 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService1Id
)))
655 .RetiresOnSaturation();
656 manager
->Destroy(true);
659 TEST_F(QueryManagerTest
, TimeElapsedQuery
) {
660 const GLuint kClient1Id
= 1;
661 const GLenum kTarget
= GL_TIME_ELAPSED_EXT
;
662 const base::subtle::Atomic32 kSubmitCount
= 123;
663 gfx::GPUTimingFake fake_timing_queries
;
664 decoder_
->GetGLContext()->CreateGPUTimingClient()->SetCpuTimeForTesting(
665 base::Bind(&gfx::GPUTimingFake::GetFakeCPUTime
));
667 QueryManager::Query
* query
= manager_
->CreateQuery(
668 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
669 ASSERT_TRUE(query
!= NULL
);
671 fake_timing_queries
.ExpectGPUTimerQuery(*gl_
, true);
672 fake_timing_queries
.SetCurrentGLTime(
673 200 * base::Time::kNanosecondsPerMicrosecond
);
674 EXPECT_TRUE(manager_
->BeginQuery(query
));
675 fake_timing_queries
.SetCurrentGLTime(
676 300 * base::Time::kNanosecondsPerMicrosecond
);
677 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
));
678 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
680 EXPECT_TRUE(query
->IsFinished());
682 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
683 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
684 const uint64_t expected_result
=
685 100u * base::Time::kNanosecondsPerMicrosecond
;
686 EXPECT_EQ(expected_result
, sync
->result
);
688 manager_
->Destroy(false);
691 TEST_F(QueryManagerTest
, TimeElapsedPauseResume
) {
692 const GLuint kClient1Id
= 1;
693 const GLenum kTarget
= GL_TIME_ELAPSED_EXT
;
694 const base::subtle::Atomic32 kSubmitCount
= 123;
695 gfx::GPUTimingFake fake_timing_queries
;
696 decoder_
->GetGLContext()->CreateGPUTimingClient()->SetCpuTimeForTesting(
697 base::Bind(&gfx::GPUTimingFake::GetFakeCPUTime
));
699 QueryManager::Query
* query
= manager_
->CreateQuery(
700 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
701 ASSERT_TRUE(query
!= NULL
);
703 fake_timing_queries
.ExpectGPUTimerQuery(*gl_
, true);
704 fake_timing_queries
.SetCurrentGLTime(
705 200 * base::Time::kNanosecondsPerMicrosecond
);
706 EXPECT_TRUE(manager_
->BeginQuery(query
));
708 // Pause and Resume here.
709 fake_timing_queries
.SetCurrentGLTime(
710 300 * base::Time::kNanosecondsPerMicrosecond
);
711 manager_
->PauseQueries();
713 fake_timing_queries
.SetCurrentGLTime(
714 400 * base::Time::kNanosecondsPerMicrosecond
);
715 manager_
->ResumeQueries();
717 fake_timing_queries
.SetCurrentGLTime(
718 500 * base::Time::kNanosecondsPerMicrosecond
);
719 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
));
721 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
722 EXPECT_TRUE(query
->IsFinished());
724 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
725 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
726 const uint64_t expected_result
=
727 300u * base::Time::kNanosecondsPerMicrosecond
;
728 EXPECT_EQ(expected_result
, sync
->result
);
730 // Make sure next query works properly.
731 fake_timing_queries
.SetCurrentGLTime(
732 600 * base::Time::kNanosecondsPerMicrosecond
);
733 EXPECT_TRUE(manager_
->BeginQuery(query
));
734 fake_timing_queries
.SetCurrentGLTime(
735 700 * base::Time::kNanosecondsPerMicrosecond
);
736 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
+ 1));
737 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
739 EXPECT_TRUE(query
->IsFinished());
741 const uint64_t expected_result2
=
742 100u * base::Time::kNanosecondsPerMicrosecond
;
743 EXPECT_EQ(expected_result2
, sync
->result
);
745 manager_
->Destroy(false);
748 TEST_F(QueryManagerManualSetupTest
, TimeElapsedDisjoint
) {
749 GpuServiceTest::SetUpWithGLVersion("OpenGL ES 3.0",
750 "GL_EXT_disjoint_timer_query");
751 gfx::GPUTimingFake fake_timing_queries
;
752 fake_timing_queries
.ExpectDisjointCalls(*gl_
);
753 SetUpMockGL("GL_EXT_disjoint_timer_query");
755 DisjointValueSync
* disjoint_sync
=
756 decoder_
->GetSharedMemoryAs
<DisjointValueSync
*>(kSharedMemory2Id
,
757 kSharedMemory2Offset
,
758 sizeof(*disjoint_sync
));
759 manager_
->SetDisjointSync(kSharedMemory2Id
, kSharedMemory2Offset
);
761 const uint32_t current_disjoint_value
= disjoint_sync
->GetDisjointCount();
762 ASSERT_EQ(0u, current_disjoint_value
);
764 const GLuint kClient1Id
= 1;
765 const GLenum kTarget
= GL_TIME_ELAPSED_EXT
;
766 const base::subtle::Atomic32 kSubmitCount
= 123;
768 QueryManager::Query
* query
= manager_
->CreateQuery(
769 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
770 ASSERT_TRUE(query
!= NULL
);
772 // Disjoint happening before the query should not trigger a disjoint event.
773 fake_timing_queries
.SetDisjoint();
775 fake_timing_queries
.ExpectGPUTimerQuery(*gl_
, true);
776 EXPECT_TRUE(manager_
->BeginQuery(query
));
777 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
));
778 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
780 EXPECT_TRUE(query
->IsFinished());
781 EXPECT_EQ(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
783 // Disjoint happening during query should trigger disjoint event.
784 fake_timing_queries
.ExpectGPUTimerQuery(*gl_
, true);
785 EXPECT_TRUE(manager_
->BeginQuery(query
));
786 fake_timing_queries
.SetDisjoint();
787 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
));
788 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
790 EXPECT_TRUE(query
->IsFinished());
791 EXPECT_NE(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
793 manager_
->Destroy(false);
796 TEST_F(QueryManagerTest
, TimeStampQuery
) {
797 const GLuint kClient1Id
= 1;
798 const GLenum kTarget
= GL_TIMESTAMP_EXT
;
799 const base::subtle::Atomic32 kSubmitCount
= 123;
800 gfx::GPUTimingFake fake_timing_queries
;
802 decoder_
->GetGLContext()->CreateGPUTimingClient()->SetCpuTimeForTesting(
803 base::Bind(&gfx::GPUTimingFake::GetFakeCPUTime
));
805 QueryManager::Query
* query
= manager_
->CreateQuery(
806 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
807 ASSERT_TRUE(query
!= NULL
);
809 const uint64_t expected_result
=
810 100u * base::Time::kNanosecondsPerMicrosecond
;
811 fake_timing_queries
.SetCurrentGLTime(expected_result
);
812 fake_timing_queries
.ExpectGPUTimeStampQuery(*gl_
, false);
813 EXPECT_TRUE(manager_
->QueryCounter(query
, kSubmitCount
));
814 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
816 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
817 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
818 EXPECT_EQ(expected_result
, sync
->result
);
820 manager_
->Destroy(false);
823 TEST_F(QueryManagerManualSetupTest
, TimeStampDisjoint
) {
824 GpuServiceTest::SetUpWithGLVersion("OpenGL ES 3.0",
825 "GL_EXT_disjoint_timer_query");
826 gfx::GPUTimingFake fake_timing_queries
;
827 fake_timing_queries
.ExpectDisjointCalls(*gl_
);
828 SetUpMockGL("GL_EXT_disjoint_timer_query");
830 DisjointValueSync
* disjoint_sync
=
831 decoder_
->GetSharedMemoryAs
<DisjointValueSync
*>(kSharedMemory2Id
,
832 kSharedMemory2Offset
,
833 sizeof(*disjoint_sync
));
834 manager_
->SetDisjointSync(kSharedMemory2Id
, kSharedMemory2Offset
);
836 const uint32_t current_disjoint_value
= disjoint_sync
->GetDisjointCount();
837 ASSERT_EQ(0u, current_disjoint_value
);
839 const GLuint kClient1Id
= 1;
840 const GLenum kTarget
= GL_TIMESTAMP_EXT
;
841 const base::subtle::Atomic32 kSubmitCount
= 123;
843 QueryManager::Query
* query
= manager_
->CreateQuery(
844 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
845 ASSERT_TRUE(query
!= NULL
);
847 // Disjoint happening before the query should not trigger a disjoint event.
848 fake_timing_queries
.SetDisjoint();
850 fake_timing_queries
.ExpectGPUTimeStampQuery(*gl_
, false);
851 EXPECT_TRUE(manager_
->QueryCounter(query
, kSubmitCount
));
852 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
854 EXPECT_TRUE(query
->IsFinished());
855 EXPECT_EQ(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
857 // Disjoint happening during query should trigger disjoint event.
858 fake_timing_queries
.ExpectGPUTimeStampQuery(*gl_
, false);
859 EXPECT_TRUE(manager_
->QueryCounter(query
, kSubmitCount
));
860 fake_timing_queries
.SetDisjoint();
861 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
863 EXPECT_TRUE(query
->IsFinished());
864 EXPECT_NE(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
866 manager_
->Destroy(false);
869 TEST_F(QueryManagerManualSetupTest
, DisjointContinualTest
) {
870 GpuServiceTest::SetUpWithGLVersion("OpenGL ES 3.0",
871 "GL_EXT_disjoint_timer_query");
872 gfx::GPUTimingFake fake_timing_queries
;
873 fake_timing_queries
.ExpectDisjointCalls(*gl_
);
874 SetUpMockGL("GL_EXT_disjoint_timer_query");
876 DisjointValueSync
* disjoint_sync
=
877 decoder_
->GetSharedMemoryAs
<DisjointValueSync
*>(kSharedMemory2Id
,
878 kSharedMemory2Offset
,
879 sizeof(*disjoint_sync
));
880 manager_
->SetDisjointSync(kSharedMemory2Id
, kSharedMemory2Offset
);
882 const uint32_t current_disjoint_value
= disjoint_sync
->GetDisjointCount();
883 ASSERT_EQ(0u, current_disjoint_value
);
885 // Disjoint value should not be updated until we have a timestamp query.
886 fake_timing_queries
.SetDisjoint();
887 manager_
->ProcessFrameBeginUpdates();
888 EXPECT_EQ(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
890 const GLuint kClient1Id
= 1;
891 const GLenum kTarget
= GL_TIMESTAMP_EXT
;
892 const base::subtle::Atomic32 kSubmitCount
= 123;
894 QueryManager::Query
* query
= manager_
->CreateQuery(
895 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
896 ASSERT_TRUE(query
!= NULL
);
898 fake_timing_queries
.ExpectGPUTimeStampQuery(*gl_
, false);
899 EXPECT_TRUE(manager_
->QueryCounter(query
, kSubmitCount
));
900 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
902 EXPECT_EQ(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
903 fake_timing_queries
.SetDisjoint();
904 manager_
->ProcessFrameBeginUpdates();
905 EXPECT_NE(current_disjoint_value
, disjoint_sync
->GetDisjointCount());
907 manager_
->Destroy(false);
910 TEST_F(QueryManagerTest
, GetErrorQuery
) {
911 const GLuint kClient1Id
= 1;
912 const GLenum kTarget
= GL_GET_ERROR_QUERY_CHROMIUM
;
913 const base::subtle::Atomic32 kSubmitCount
= 123;
915 TestHelper::SetupFeatureInfoInitExpectations(gl_
.get(), "");
916 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
917 feature_info
->Initialize();
918 scoped_ptr
<QueryManager
> manager(
919 new QueryManager(decoder_
.get(), feature_info
.get()));
921 QueryManager::Query
* query
= manager
->CreateQuery(
922 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
923 ASSERT_TRUE(query
!= NULL
);
925 // Setup shared memory like client would.
926 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
927 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
928 ASSERT_TRUE(sync
!= NULL
);
931 EXPECT_TRUE(manager
->BeginQuery(query
));
933 MockErrorState mock_error_state
;
934 EXPECT_CALL(*decoder_
.get(), GetErrorState())
935 .WillRepeatedly(Return(&mock_error_state
));
936 EXPECT_CALL(mock_error_state
, GetGLError())
937 .WillOnce(Return(GL_INVALID_ENUM
))
938 .RetiresOnSaturation();
940 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
941 EXPECT_FALSE(query
->IsPending());
943 EXPECT_EQ(static_cast<GLuint
>(GL_INVALID_ENUM
), sync
->result
);
945 manager
->Destroy(false);