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 size_t kSharedBufferSize
= 2048;
32 static const uint32 kSharedMemoryOffset
= 132;
33 static const int32 kInvalidSharedMemoryId
= 402;
34 static const uint32 kInvalidSharedMemoryOffset
= kSharedBufferSize
+ 1;
35 static const uint32 kInitialResult
= 0xBDBDBDBDu
;
36 static const uint8 kInitialMemoryValue
= 0xBDu
;
40 ~QueryManagerTest() override
{}
43 void SetUp() override
{
44 GpuServiceTest::SetUpWithGLVersion("3.2",
45 "GL_ARB_occlusion_query, "
46 "GL_ARB_timer_query");
47 engine_
.reset(new MockCommandBufferEngine());
48 decoder_
.reset(new MockGLES2Decoder());
49 decoder_
->set_engine(engine_
.get());
50 TestHelper::SetupFeatureInfoInitExpectations(
52 "GL_EXT_occlusion_query_boolean, GL_ARB_timer_query");
53 EXPECT_CALL(*decoder_
.get(), GetGLContext())
54 .WillRepeatedly(Return(GetGLContext()));
55 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
56 feature_info
->Initialize();
57 manager_
.reset(new QueryManager(decoder_
.get(), feature_info
.get()));
60 void TearDown() override
{
62 manager_
->Destroy(false);
65 GpuServiceTest::TearDown();
68 QueryManager::Query
* CreateQuery(
69 GLenum target
, GLuint client_id
, int32 shm_id
, uint32 shm_offset
,
71 EXPECT_CALL(*gl_
, GenQueries(1, _
))
72 .WillOnce(SetArgumentPointee
<1>(service_id
))
73 .RetiresOnSaturation();
74 return manager_
->CreateQuery(target
, client_id
, shm_id
, shm_offset
);
77 void QueueQuery(QueryManager::Query
* query
,
79 base::subtle::Atomic32 submit_count
) {
80 EXPECT_CALL(*gl_
, BeginQuery(query
->target(), service_id
))
82 .RetiresOnSaturation();
83 EXPECT_CALL(*gl_
, EndQuery(query
->target()))
85 .RetiresOnSaturation();
86 EXPECT_TRUE(manager_
->BeginQuery(query
));
87 EXPECT_TRUE(manager_
->EndQuery(query
, submit_count
));
90 scoped_ptr
<MockGLES2Decoder
> decoder_
;
91 scoped_ptr
<QueryManager
> manager_
;
94 class MockCommandBufferEngine
: public CommandBufferEngine
{
96 MockCommandBufferEngine() {
97 scoped_ptr
<base::SharedMemory
> shared_memory(new base::SharedMemory());
98 shared_memory
->CreateAndMapAnonymous(kSharedBufferSize
);
100 MakeBufferFromSharedMemory(shared_memory
.Pass(), kSharedBufferSize
);
101 data_
= static_cast<uint8
*>(valid_buffer_
->memory());
105 ~MockCommandBufferEngine() override
{}
107 scoped_refptr
<gpu::Buffer
> GetSharedMemoryBuffer(int32 shm_id
) override
{
108 return shm_id
== kSharedMemoryId
? valid_buffer_
: invalid_buffer_
;
111 void ClearSharedMemory() {
112 memset(data_
, kInitialMemoryValue
, kSharedBufferSize
);
115 void set_token(int32 token
) override
{ DCHECK(false); }
117 bool SetGetBuffer(int32
/* transfer_buffer_id */) override
{
122 // Overridden from CommandBufferEngine.
123 bool SetGetOffset(int32 offset
) override
{
128 // Overridden from CommandBufferEngine.
129 int32
GetGetOffset() override
{
136 scoped_refptr
<gpu::Buffer
> valid_buffer_
;
137 scoped_refptr
<gpu::Buffer
> invalid_buffer_
;
140 scoped_ptr
<MockCommandBufferEngine
> engine_
;
143 // GCC requires these declarations, but MSVC requires they not be present
144 #ifndef COMPILER_MSVC
145 const int32
QueryManagerTest::kSharedMemoryId
;
146 const size_t QueryManagerTest::kSharedBufferSize
;
147 const uint32
QueryManagerTest::kSharedMemoryOffset
;
148 const int32
QueryManagerTest::kInvalidSharedMemoryId
;
149 const uint32
QueryManagerTest::kInvalidSharedMemoryOffset
;
150 const uint32
QueryManagerTest::kInitialResult
;
151 const uint8
QueryManagerTest::kInitialMemoryValue
;
154 TEST_F(QueryManagerTest
, Basic
) {
155 const GLuint kClient1Id
= 1;
156 const GLuint kService1Id
= 11;
157 const GLuint kClient2Id
= 2;
159 EXPECT_FALSE(manager_
->HavePendingQueries());
160 // Check we can create a Query.
161 scoped_refptr
<QueryManager::Query
> query(
162 CreateQuery(GL_ANY_SAMPLES_PASSED_EXT
, kClient1Id
,
163 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
164 ASSERT_TRUE(query
.get() != NULL
);
165 // Check we can get the same Query.
166 EXPECT_EQ(query
.get(), manager_
->GetQuery(kClient1Id
));
167 // Check we get nothing for a non-existent query.
168 EXPECT_TRUE(manager_
->GetQuery(kClient2Id
) == NULL
);
169 // Check we can delete the query.
170 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService1Id
)))
172 .RetiresOnSaturation();
173 manager_
->RemoveQuery(kClient1Id
);
174 // Check we get nothing for a non-existent query.
175 EXPECT_TRUE(manager_
->GetQuery(kClient1Id
) == NULL
);
176 // Check query is deleted
177 EXPECT_TRUE(query
->IsDeleted());
178 EXPECT_FALSE(manager_
->HavePendingQueries());
181 TEST_F(QueryManagerTest
, Destroy
) {
182 const GLuint kClient1Id
= 1;
183 const GLuint kService1Id
= 11;
186 scoped_refptr
<QueryManager::Query
> query(
187 CreateQuery(GL_ANY_SAMPLES_PASSED_EXT
, kClient1Id
,
188 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
189 ASSERT_TRUE(query
.get() != NULL
);
190 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService1Id
)))
192 .RetiresOnSaturation();
193 manager_
->Destroy(true);
194 // Check we get nothing for a non-existent query.
195 EXPECT_TRUE(manager_
->GetQuery(kClient1Id
) == NULL
);
196 // Check query is deleted
197 EXPECT_TRUE(query
->IsDeleted());
200 TEST_F(QueryManagerTest
, QueryBasic
) {
201 const GLuint kClient1Id
= 1;
202 const GLuint kService1Id
= 11;
203 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
206 scoped_refptr
<QueryManager::Query
> query(
207 CreateQuery(kTarget
, kClient1Id
,
208 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
209 ASSERT_TRUE(query
.get() != NULL
);
211 EXPECT_TRUE(query
->IsValid());
212 EXPECT_FALSE(query
->IsDeleted());
213 EXPECT_FALSE(query
->IsPending());
214 EXPECT_EQ(kTarget
, query
->target());
215 EXPECT_EQ(kSharedMemoryId
, query
->shm_id());
216 EXPECT_EQ(kSharedMemoryOffset
, query
->shm_offset());
219 TEST_F(QueryManagerTest
, ProcessPendingQuery
) {
220 const GLuint kClient1Id
= 1;
221 const GLuint kService1Id
= 11;
222 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
223 const base::subtle::Atomic32 kSubmitCount
= 123;
224 const GLuint kResult
= 1;
226 // Check nothing happens if there are no pending queries.
227 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
230 scoped_refptr
<QueryManager::Query
> query(
231 CreateQuery(kTarget
, kClient1Id
,
232 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
233 ASSERT_TRUE(query
.get() != NULL
);
235 // Setup shared memory like client would.
236 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
237 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
238 ASSERT_TRUE(sync
!= NULL
);
242 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
243 EXPECT_TRUE(query
->IsPending());
244 EXPECT_TRUE(manager_
->HavePendingQueries());
246 // Process with return not available.
247 // Expect 1 GL command.
249 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
250 .WillOnce(SetArgumentPointee
<2>(0))
251 .RetiresOnSaturation();
252 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
253 EXPECT_TRUE(query
->IsPending());
254 EXPECT_EQ(0, sync
->process_count
);
255 EXPECT_EQ(0u, sync
->result
);
257 // Process with return available.
258 // Expect 2 GL commands.
260 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
261 .WillOnce(SetArgumentPointee
<2>(1))
262 .RetiresOnSaturation();
264 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
265 .WillOnce(SetArgumentPointee
<2>(kResult
))
266 .RetiresOnSaturation();
267 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
268 EXPECT_FALSE(query
->IsPending());
269 EXPECT_EQ(kSubmitCount
, sync
->process_count
);
270 EXPECT_EQ(kResult
, sync
->result
);
271 EXPECT_FALSE(manager_
->HavePendingQueries());
273 // Process with no queries.
274 // Expect no GL commands/
275 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
278 TEST_F(QueryManagerTest
, ProcessPendingQueries
) {
279 const GLuint kClient1Id
= 1;
280 const GLuint kService1Id
= 11;
281 const GLuint kClient2Id
= 2;
282 const GLuint kService2Id
= 12;
283 const GLuint kClient3Id
= 3;
284 const GLuint kService3Id
= 13;
285 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
286 const base::subtle::Atomic32 kSubmitCount1
= 123;
287 const base::subtle::Atomic32 kSubmitCount2
= 123;
288 const base::subtle::Atomic32 kSubmitCount3
= 123;
289 const GLuint kResult1
= 1;
290 const GLuint kResult2
= 1;
291 const GLuint kResult3
= 1;
293 // Setup shared memory like client would.
294 QuerySync
* sync1
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
295 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync1
) * 3);
296 ASSERT_TRUE(sync1
!= NULL
);
297 QuerySync
* sync2
= sync1
+ 1;
298 QuerySync
* sync3
= sync2
+ 1;
301 scoped_refptr
<QueryManager::Query
> query1(
302 CreateQuery(kTarget
, kClient1Id
,
303 kSharedMemoryId
, kSharedMemoryOffset
+ sizeof(*sync1
) * 0,
305 scoped_refptr
<QueryManager::Query
> query2(
306 CreateQuery(kTarget
, kClient2Id
,
307 kSharedMemoryId
, kSharedMemoryOffset
+ sizeof(*sync1
) * 1,
309 scoped_refptr
<QueryManager::Query
> query3(
310 CreateQuery(kTarget
, kClient3Id
,
311 kSharedMemoryId
, kSharedMemoryOffset
+ sizeof(*sync1
) * 2,
313 ASSERT_TRUE(query1
.get() != NULL
);
314 ASSERT_TRUE(query2
.get() != NULL
);
315 ASSERT_TRUE(query3
.get() != NULL
);
316 EXPECT_FALSE(manager_
->HavePendingQueries());
323 QueueQuery(query1
.get(), kService1Id
, kSubmitCount1
);
324 QueueQuery(query2
.get(), kService2Id
, kSubmitCount2
);
325 QueueQuery(query3
.get(), kService3Id
, kSubmitCount3
);
326 EXPECT_TRUE(query1
->IsPending());
327 EXPECT_TRUE(query2
->IsPending());
328 EXPECT_TRUE(query3
->IsPending());
329 EXPECT_TRUE(manager_
->HavePendingQueries());
331 // Process with return available for first 2 queries.
332 // Expect 4 GL commands.
336 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
337 .WillOnce(SetArgumentPointee
<2>(1))
338 .RetiresOnSaturation();
340 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
341 .WillOnce(SetArgumentPointee
<2>(kResult1
))
342 .RetiresOnSaturation();
344 GetQueryObjectuiv(kService2Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
345 .WillOnce(SetArgumentPointee
<2>(1))
346 .RetiresOnSaturation();
348 GetQueryObjectuiv(kService2Id
, GL_QUERY_RESULT_EXT
, _
))
349 .WillOnce(SetArgumentPointee
<2>(kResult2
))
350 .RetiresOnSaturation();
352 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
353 .WillOnce(SetArgumentPointee
<2>(0))
354 .RetiresOnSaturation();
355 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
357 EXPECT_FALSE(query1
->IsPending());
358 EXPECT_FALSE(query2
->IsPending());
359 EXPECT_TRUE(query3
->IsPending());
360 EXPECT_EQ(kSubmitCount1
, sync1
->process_count
);
361 EXPECT_EQ(kSubmitCount2
, sync2
->process_count
);
362 EXPECT_EQ(kResult1
, sync1
->result
);
363 EXPECT_EQ(kResult2
, sync2
->result
);
364 EXPECT_EQ(0, sync3
->process_count
);
365 EXPECT_EQ(0u, sync3
->result
);
366 EXPECT_TRUE(manager_
->HavePendingQueries());
368 // Process with renaming query. No result.
369 // Expect 1 GL commands.
371 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
372 .WillOnce(SetArgumentPointee
<2>(0))
373 .RetiresOnSaturation();
374 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
375 EXPECT_TRUE(query3
->IsPending());
376 EXPECT_EQ(0, sync3
->process_count
);
377 EXPECT_EQ(0u, sync3
->result
);
378 EXPECT_TRUE(manager_
->HavePendingQueries());
380 // Process with renaming query. With result.
381 // Expect 2 GL commands.
383 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
384 .WillOnce(SetArgumentPointee
<2>(1))
385 .RetiresOnSaturation();
387 GetQueryObjectuiv(kService3Id
, GL_QUERY_RESULT_EXT
, _
))
388 .WillOnce(SetArgumentPointee
<2>(kResult3
))
389 .RetiresOnSaturation();
390 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
391 EXPECT_FALSE(query3
->IsPending());
392 EXPECT_EQ(kSubmitCount3
, sync3
->process_count
);
393 EXPECT_EQ(kResult3
, sync3
->result
);
394 EXPECT_FALSE(manager_
->HavePendingQueries());
397 TEST_F(QueryManagerTest
, ProcessPendingBadSharedMemoryId
) {
398 const GLuint kClient1Id
= 1;
399 const GLuint kService1Id
= 11;
400 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
401 const base::subtle::Atomic32 kSubmitCount
= 123;
402 const GLuint kResult
= 1;
405 scoped_refptr
<QueryManager::Query
> query(
406 CreateQuery(kTarget
, kClient1Id
,
407 kInvalidSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
408 ASSERT_TRUE(query
.get() != NULL
);
411 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
413 // Process with return available.
414 // Expect 2 GL commands.
416 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
417 .WillOnce(SetArgumentPointee
<2>(1))
418 .RetiresOnSaturation();
420 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
421 .WillOnce(SetArgumentPointee
<2>(kResult
))
422 .RetiresOnSaturation();
423 EXPECT_FALSE(manager_
->ProcessPendingQueries(false));
426 TEST_F(QueryManagerTest
, ProcessPendingBadSharedMemoryOffset
) {
427 const GLuint kClient1Id
= 1;
428 const GLuint kService1Id
= 11;
429 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
430 const base::subtle::Atomic32 kSubmitCount
= 123;
431 const GLuint kResult
= 1;
434 scoped_refptr
<QueryManager::Query
> query(
435 CreateQuery(kTarget
, kClient1Id
,
436 kSharedMemoryId
, kInvalidSharedMemoryOffset
, kService1Id
));
437 ASSERT_TRUE(query
.get() != NULL
);
440 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
442 // Process with return available.
443 // Expect 2 GL commands.
445 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
446 .WillOnce(SetArgumentPointee
<2>(1))
447 .RetiresOnSaturation();
449 GetQueryObjectuiv(kService1Id
, GL_QUERY_RESULT_EXT
, _
))
450 .WillOnce(SetArgumentPointee
<2>(kResult
))
451 .RetiresOnSaturation();
452 EXPECT_FALSE(manager_
->ProcessPendingQueries(false));
455 TEST_F(QueryManagerTest
, ExitWithPendingQuery
) {
456 const GLuint kClient1Id
= 1;
457 const GLuint kService1Id
= 11;
458 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
459 const base::subtle::Atomic32 kSubmitCount
= 123;
462 scoped_refptr
<QueryManager::Query
> query(
463 CreateQuery(kTarget
, kClient1Id
,
464 kSharedMemoryId
, kSharedMemoryOffset
, kService1Id
));
465 ASSERT_TRUE(query
.get() != NULL
);
468 QueueQuery(query
.get(), kService1Id
, kSubmitCount
);
471 // Test that when based on ARB_occlusion_query2 we use GL_ANY_SAMPLES_PASSED_ARB
472 // for GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
473 TEST_F(QueryManagerTest
, ARBOcclusionQuery2
) {
474 const GLuint kClient1Id
= 1;
475 const GLuint kService1Id
= 11;
476 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT
;
477 const base::subtle::Atomic32 kSubmitCount
= 123;
479 TestHelper::SetupFeatureInfoInitExpectations(
481 "GL_ARB_occlusion_query2");
482 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
483 feature_info
->Initialize();
484 scoped_ptr
<QueryManager
> manager(
485 new QueryManager(decoder_
.get(), feature_info
.get()));
487 EXPECT_CALL(*gl_
, GenQueries(1, _
))
488 .WillOnce(SetArgumentPointee
<1>(kService1Id
))
489 .RetiresOnSaturation();
490 QueryManager::Query
* query
= manager
->CreateQuery(
491 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
492 ASSERT_TRUE(query
!= NULL
);
494 EXPECT_CALL(*gl_
, BeginQuery(GL_ANY_SAMPLES_PASSED_EXT
, kService1Id
))
496 .RetiresOnSaturation();
497 EXPECT_CALL(*gl_
, EndQuery(GL_ANY_SAMPLES_PASSED_EXT
))
499 .RetiresOnSaturation();
500 EXPECT_TRUE(manager
->BeginQuery(query
));
501 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
502 manager
->Destroy(false);
505 // Test that when based on ARB_occlusion_query we use GL_SAMPLES_PASSED_ARB
506 // for GL_ANY_SAMPLES_PASSED_EXT
507 TEST_F(QueryManagerTest
, ARBOcclusionQuery
) {
508 const GLuint kClient1Id
= 1;
509 const GLuint kService1Id
= 11;
510 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
511 const base::subtle::Atomic32 kSubmitCount
= 123;
513 TestHelper::SetupFeatureInfoInitExpectations(
515 "GL_ARB_occlusion_query");
516 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
517 feature_info
->Initialize();
518 scoped_ptr
<QueryManager
> manager(
519 new QueryManager(decoder_
.get(), feature_info
.get()));
521 EXPECT_CALL(*gl_
, GenQueries(1, _
))
522 .WillOnce(SetArgumentPointee
<1>(kService1Id
))
523 .RetiresOnSaturation();
524 QueryManager::Query
* query
= manager
->CreateQuery(
525 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
526 ASSERT_TRUE(query
!= NULL
);
528 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService1Id
))
530 .RetiresOnSaturation();
531 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
533 .RetiresOnSaturation();
534 EXPECT_TRUE(manager
->BeginQuery(query
));
535 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
536 manager
->Destroy(false);
539 TEST_F(QueryManagerTest
, ARBOcclusionPauseResume
) {
540 const GLuint kClient1Id
= 1;
541 const GLuint kService1Id
= 11;
542 const GLuint kService2Id
= 12;
543 const GLenum kTarget
= GL_ANY_SAMPLES_PASSED_EXT
;
544 const base::subtle::Atomic32 kSubmitCount
= 123;
546 TestHelper::SetupFeatureInfoInitExpectations(
548 "GL_ARB_occlusion_query");
549 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
550 feature_info
->Initialize();
551 scoped_ptr
<QueryManager
> manager(
552 new QueryManager(decoder_
.get(), feature_info
.get()));
554 EXPECT_CALL(*gl_
, GenQueries(1, _
))
555 .WillOnce(SetArgumentPointee
<1>(kService1Id
))
556 .RetiresOnSaturation();
557 QueryManager::Query
* query
= manager
->CreateQuery(
558 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
559 ASSERT_TRUE(query
!= NULL
);
561 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService1Id
))
563 .RetiresOnSaturation();
564 EXPECT_TRUE(manager
->BeginQuery(query
));
566 // Pause and Resume the manager.
567 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
569 .RetiresOnSaturation();
570 manager
->PauseQueries();
572 EXPECT_CALL(*gl_
, GenQueries(1, _
))
573 .WillOnce(SetArgumentPointee
<1>(kService2Id
))
574 .RetiresOnSaturation();
575 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService2Id
))
577 .RetiresOnSaturation();
578 manager
->ResumeQueries();
580 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
582 .RetiresOnSaturation();
583 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
585 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService2Id
,
586 GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
587 .WillOnce(SetArgumentPointee
<2>(1u))
588 .RetiresOnSaturation();
589 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService1Id
,
590 GL_QUERY_RESULT_EXT
, _
))
591 .WillOnce(SetArgumentPointee
<2>(0u))
592 .RetiresOnSaturation();
593 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService2Id
,
594 GL_QUERY_RESULT_EXT
, _
))
595 .WillOnce(SetArgumentPointee
<2>(1u))
596 .RetiresOnSaturation();
597 EXPECT_TRUE(manager
->ProcessPendingQueries(false));
598 EXPECT_TRUE(query
->IsFinished());
600 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
601 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
602 EXPECT_EQ(1u, sync
->result
);
604 // Make sure new query still works.
605 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService2Id
)))
607 .RetiresOnSaturation();
608 EXPECT_CALL(*gl_
, BeginQuery(GL_SAMPLES_PASSED_ARB
, kService1Id
))
610 .RetiresOnSaturation();
611 EXPECT_CALL(*gl_
, EndQuery(GL_SAMPLES_PASSED_ARB
))
613 .RetiresOnSaturation();
614 EXPECT_TRUE(manager
->BeginQuery(query
));
615 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
+ 1));
617 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService1Id
,
618 GL_QUERY_RESULT_AVAILABLE_EXT
, _
))
619 .WillOnce(SetArgumentPointee
<2>(1u))
620 .RetiresOnSaturation();
621 EXPECT_CALL(*gl_
, GetQueryObjectuiv(kService1Id
,
622 GL_QUERY_RESULT_EXT
, _
))
623 .WillOnce(SetArgumentPointee
<2>(0u))
624 .RetiresOnSaturation();
625 EXPECT_TRUE(manager
->ProcessPendingQueries(false));
626 EXPECT_TRUE(query
->IsFinished());
628 EXPECT_EQ(0u, sync
->result
);
629 EXPECT_CALL(*gl_
, DeleteQueries(1, ::testing::Pointee(kService1Id
)))
631 .RetiresOnSaturation();
632 manager
->Destroy(true);
635 TEST_F(QueryManagerTest
, TimeElapsedQuery
) {
636 const GLuint kClient1Id
= 1;
637 const GLenum kTarget
= GL_TIME_ELAPSED_EXT
;
638 const base::subtle::Atomic32 kSubmitCount
= 123;
639 gfx::GPUTimingFake fake_timing_queries
;
640 decoder_
->GetGLContext()->CreateGPUTimingClient()->SetCpuTimeForTesting(
641 base::Bind(&gfx::GPUTimingFake::GetFakeCPUTime
));
643 QueryManager::Query
* query
= manager_
->CreateQuery(
644 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
645 ASSERT_TRUE(query
!= NULL
);
647 fake_timing_queries
.ExpectGPUTimerQuery(*gl_
, true);
648 fake_timing_queries
.SetCurrentGLTime(
649 200 * base::Time::kNanosecondsPerMicrosecond
);
650 EXPECT_TRUE(manager_
->BeginQuery(query
));
651 fake_timing_queries
.SetCurrentGLTime(
652 300 * base::Time::kNanosecondsPerMicrosecond
);
653 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
));
654 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
656 EXPECT_TRUE(query
->IsFinished());
658 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
659 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
660 const uint64_t expected_result
=
661 100u * base::Time::kNanosecondsPerMicrosecond
;
662 EXPECT_EQ(expected_result
, sync
->result
);
664 manager_
->Destroy(false);
667 TEST_F(QueryManagerTest
, TimeElapsedPauseResume
) {
668 const GLuint kClient1Id
= 1;
669 const GLenum kTarget
= GL_TIME_ELAPSED_EXT
;
670 const base::subtle::Atomic32 kSubmitCount
= 123;
671 gfx::GPUTimingFake fake_timing_queries
;
672 decoder_
->GetGLContext()->CreateGPUTimingClient()->SetCpuTimeForTesting(
673 base::Bind(&gfx::GPUTimingFake::GetFakeCPUTime
));
675 QueryManager::Query
* query
= manager_
->CreateQuery(
676 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
677 ASSERT_TRUE(query
!= NULL
);
679 fake_timing_queries
.ExpectGPUTimerQuery(*gl_
, true);
680 fake_timing_queries
.SetCurrentGLTime(
681 200 * base::Time::kNanosecondsPerMicrosecond
);
682 EXPECT_TRUE(manager_
->BeginQuery(query
));
684 // Pause and Resume here.
685 fake_timing_queries
.SetCurrentGLTime(
686 300 * base::Time::kNanosecondsPerMicrosecond
);
687 manager_
->PauseQueries();
689 fake_timing_queries
.SetCurrentGLTime(
690 400 * base::Time::kNanosecondsPerMicrosecond
);
691 manager_
->ResumeQueries();
693 fake_timing_queries
.SetCurrentGLTime(
694 500 * base::Time::kNanosecondsPerMicrosecond
);
695 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
));
697 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
698 EXPECT_TRUE(query
->IsFinished());
700 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
701 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
702 const uint64_t expected_result
=
703 300u * base::Time::kNanosecondsPerMicrosecond
;
704 EXPECT_EQ(expected_result
, sync
->result
);
706 // Make sure next query works properly.
707 fake_timing_queries
.SetCurrentGLTime(
708 600 * base::Time::kNanosecondsPerMicrosecond
);
709 EXPECT_TRUE(manager_
->BeginQuery(query
));
710 fake_timing_queries
.SetCurrentGLTime(
711 700 * base::Time::kNanosecondsPerMicrosecond
);
712 EXPECT_TRUE(manager_
->EndQuery(query
, kSubmitCount
+ 1));
713 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
715 EXPECT_TRUE(query
->IsFinished());
717 const uint64_t expected_result2
=
718 100u * base::Time::kNanosecondsPerMicrosecond
;
719 EXPECT_EQ(expected_result2
, sync
->result
);
721 manager_
->Destroy(false);
724 TEST_F(QueryManagerTest
, TimeStampQuery
) {
725 const GLuint kClient1Id
= 1;
726 const GLenum kTarget
= GL_TIMESTAMP_EXT
;
727 const base::subtle::Atomic32 kSubmitCount
= 123;
728 gfx::GPUTimingFake fake_timing_queries
;
730 QueryManager::Query
* query
= manager_
->CreateQuery(
731 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
732 ASSERT_TRUE(query
!= NULL
);
734 fake_timing_queries
.ExpectGPUTimeStampQuery(*gl_
, false);
735 EXPECT_TRUE(manager_
->QueryCounter(query
, kSubmitCount
));
736 EXPECT_TRUE(manager_
->ProcessPendingQueries(false));
737 manager_
->Destroy(false);
740 TEST_F(QueryManagerTest
, GetErrorQuery
) {
741 const GLuint kClient1Id
= 1;
742 const GLenum kTarget
= GL_GET_ERROR_QUERY_CHROMIUM
;
743 const base::subtle::Atomic32 kSubmitCount
= 123;
745 TestHelper::SetupFeatureInfoInitExpectations(gl_
.get(), "");
746 scoped_refptr
<FeatureInfo
> feature_info(new FeatureInfo());
747 feature_info
->Initialize();
748 scoped_ptr
<QueryManager
> manager(
749 new QueryManager(decoder_
.get(), feature_info
.get()));
751 QueryManager::Query
* query
= manager
->CreateQuery(
752 kTarget
, kClient1Id
, kSharedMemoryId
, kSharedMemoryOffset
);
753 ASSERT_TRUE(query
!= NULL
);
755 // Setup shared memory like client would.
756 QuerySync
* sync
= decoder_
->GetSharedMemoryAs
<QuerySync
*>(
757 kSharedMemoryId
, kSharedMemoryOffset
, sizeof(*sync
));
758 ASSERT_TRUE(sync
!= NULL
);
761 EXPECT_TRUE(manager
->BeginQuery(query
));
763 MockErrorState mock_error_state
;
764 EXPECT_CALL(*decoder_
.get(), GetErrorState())
765 .WillRepeatedly(Return(&mock_error_state
));
766 EXPECT_CALL(mock_error_state
, GetGLError())
767 .WillOnce(Return(GL_INVALID_ENUM
))
768 .RetiresOnSaturation();
770 EXPECT_TRUE(manager
->EndQuery(query
, kSubmitCount
));
771 EXPECT_FALSE(query
->IsPending());
773 EXPECT_EQ(static_cast<GLuint
>(GL_INVALID_ENUM
), sync
->result
);
775 manager
->Destroy(false);