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.
4
5// Tests for the Command Buffer Helper.
6
7#include <list>
8
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/memory/linked_ptr.h"
12#include "base/message_loop/message_loop.h"
13#include "gpu/command_buffer/client/cmd_buffer_helper.h"
14#include "gpu/command_buffer/service/command_buffer_service.h"
15#include "gpu/command_buffer/service/gpu_scheduler.h"
16#include "gpu/command_buffer/service/mocks.h"
17#include "gpu/command_buffer/service/transfer_buffer_manager.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20#if defined(OS_MACOSX)
21#include "base/mac/scoped_nsautorelease_pool.h"
22#endif
23
24namespace gpu {
25
26using testing::Return;
27using testing::Mock;
28using testing::Truly;
29using testing::Sequence;
30using testing::DoAll;
31using testing::Invoke;
32using testing::_;
33
34const int32 kTotalNumCommandEntries = 32;
35const int32 kCommandBufferSizeBytes =
36    kTotalNumCommandEntries * sizeof(CommandBufferEntry);
37const int32 kUnusedCommandId = 5;  // we use 0 and 2 currently.
38
39// Override CommandBufferService::Flush() to lock flushing and simulate
40// the buffer becoming full in asynchronous mode.
41class CommandBufferServiceLocked : public CommandBufferService {
42 public:
43  explicit CommandBufferServiceLocked(
44      TransferBufferManagerInterface* transfer_buffer_manager)
45      : CommandBufferService(transfer_buffer_manager),
46        flush_locked_(false),
47        last_flush_(-1),
48        flush_count_(0) {}
49  virtual ~CommandBufferServiceLocked() {}
50
51  virtual void Flush(int32 put_offset) OVERRIDE {
52    flush_count_++;
53    if (!flush_locked_) {
54      last_flush_ = -1;
55      CommandBufferService::Flush(put_offset);
56    } else {
57      last_flush_ = put_offset;
58    }
59  }
60
61  void LockFlush() { flush_locked_ = true; }
62
63  void UnlockFlush() { flush_locked_ = false; }
64
65  int FlushCount() { return flush_count_; }
66
67  virtual void WaitForGetOffsetInRange(int32 start, int32 end) OVERRIDE {
68    if (last_flush_ != -1) {
69      CommandBufferService::Flush(last_flush_);
70      last_flush_ = -1;
71    }
72    CommandBufferService::WaitForGetOffsetInRange(start, end);
73  }
74
75 private:
76  bool flush_locked_;
77  int last_flush_;
78  int flush_count_;
79  DISALLOW_COPY_AND_ASSIGN(CommandBufferServiceLocked);
80};
81
82// Test fixture for CommandBufferHelper test - Creates a CommandBufferHelper,
83// using a CommandBufferEngine with a mock AsyncAPIInterface for its interface
84// (calling it directly, not through the RPC mechanism).
85class CommandBufferHelperTest : public testing::Test {
86 protected:
87  virtual void SetUp() {
88    api_mock_.reset(new AsyncAPIMock(true));
89
90    // ignore noops in the mock - we don't want to inspect the internals of the
91    // helper.
92    EXPECT_CALL(*api_mock_, DoCommand(cmd::kNoop, _, _))
93        .WillRepeatedly(Return(error::kNoError));
94
95    {
96      TransferBufferManager* manager = new TransferBufferManager();
97      transfer_buffer_manager_.reset(manager);
98      EXPECT_TRUE(manager->Initialize());
99    }
100    command_buffer_.reset(
101        new CommandBufferServiceLocked(transfer_buffer_manager_.get()));
102    EXPECT_TRUE(command_buffer_->Initialize());
103
104    gpu_scheduler_.reset(new GpuScheduler(
105        command_buffer_.get(), api_mock_.get(), NULL));
106    command_buffer_->SetPutOffsetChangeCallback(base::Bind(
107        &GpuScheduler::PutChanged, base::Unretained(gpu_scheduler_.get())));
108    command_buffer_->SetGetBufferChangeCallback(base::Bind(
109        &GpuScheduler::SetGetBuffer, base::Unretained(gpu_scheduler_.get())));
110
111    api_mock_->set_engine(gpu_scheduler_.get());
112
113    helper_.reset(new CommandBufferHelper(command_buffer_.get()));
114    helper_->Initialize(kCommandBufferSizeBytes);
115
116    test_command_next_id_ = kUnusedCommandId;
117  }
118
119  virtual void TearDown() {
120    // If the GpuScheduler posts any tasks, this forces them to run.
121    base::MessageLoop::current()->RunUntilIdle();
122    test_command_args_.clear();
123  }
124
125  const CommandParser* GetParser() const {
126    return gpu_scheduler_->parser();
127  }
128
129  int32 ImmediateEntryCount() const { return helper_->immediate_entry_count_; }
130
131  // Adds a command to the buffer through the helper, while adding it as an
132  // expected call on the API mock.
133  void AddCommandWithExpect(error::Error _return,
134                            unsigned int command,
135                            int arg_count,
136                            CommandBufferEntry *args) {
137    CommandHeader header;
138    header.size = arg_count + 1;
139    header.command = command;
140    CommandBufferEntry* cmds =
141        static_cast<CommandBufferEntry*>(helper_->GetSpace(arg_count + 1));
142    CommandBufferOffset put = 0;
143    cmds[put++].value_header = header;
144    for (int ii = 0; ii < arg_count; ++ii) {
145      cmds[put++] = args[ii];
146    }
147
148    EXPECT_CALL(*api_mock_, DoCommand(command, arg_count,
149        Truly(AsyncAPIMock::IsArgs(arg_count, args))))
150        .InSequence(sequence_)
151        .WillOnce(Return(_return));
152  }
153
154  void AddUniqueCommandWithExpect(error::Error _return, int cmd_size) {
155    EXPECT_GE(cmd_size, 1);
156    EXPECT_LT(cmd_size, kTotalNumCommandEntries);
157    int arg_count = cmd_size - 1;
158
159    // Allocate array for args.
160    linked_ptr<std::vector<CommandBufferEntry> > args_ptr(
161        new std::vector<CommandBufferEntry>(arg_count ? arg_count : 1));
162
163    for (int32 ii = 0; ii < arg_count; ++ii) {
164      (*args_ptr)[ii].value_uint32 = 0xF00DF00D + ii;
165    }
166
167    // Add command and save args in test_command_args_ until the test completes.
168    AddCommandWithExpect(
169        _return, test_command_next_id_++, arg_count, &(*args_ptr)[0]);
170    test_command_args_.insert(test_command_args_.end(), args_ptr);
171  }
172
173  void TestCommandWrappingFull(int32 cmd_size, int32 start_commands) {
174    const int32 num_args = cmd_size - 1;
175    EXPECT_EQ(kTotalNumCommandEntries % cmd_size, 0);
176
177    std::vector<CommandBufferEntry> args(num_args);
178    for (int32 ii = 0; ii < num_args; ++ii) {
179      args[ii].value_uint32 = ii + 1;
180    }
181
182    // Initially insert commands up to start_commands and Finish().
183    for (int32 ii = 0; ii < start_commands; ++ii) {
184      AddCommandWithExpect(
185          error::kNoError, ii + kUnusedCommandId, num_args, &args[0]);
186    }
187    helper_->Finish();
188
189    EXPECT_EQ(GetParser()->put(),
190              (start_commands * cmd_size) % kTotalNumCommandEntries);
191    EXPECT_EQ(GetParser()->get(),
192              (start_commands * cmd_size) % kTotalNumCommandEntries);
193
194    // Lock flushing to force the buffer to get full.
195    command_buffer_->LockFlush();
196
197    // Add enough commands to over fill the buffer.
198    for (int32 ii = 0; ii < kTotalNumCommandEntries / cmd_size + 2; ++ii) {
199      AddCommandWithExpect(error::kNoError,
200                           start_commands + ii + kUnusedCommandId,
201                           num_args,
202                           &args[0]);
203    }
204
205    // Flush all commands.
206    command_buffer_->UnlockFlush();
207    helper_->Finish();
208
209    // Check that the commands did happen.
210    Mock::VerifyAndClearExpectations(api_mock_.get());
211
212    // Check the error status.
213    EXPECT_EQ(error::kNoError, GetError());
214  }
215
216  // Checks that the buffer from put to put+size is free in the parser.
217  void CheckFreeSpace(CommandBufferOffset put, unsigned int size) {
218    CommandBufferOffset parser_put = GetParser()->put();
219    CommandBufferOffset parser_get = GetParser()->get();
220    CommandBufferOffset limit = put + size;
221    if (parser_get > parser_put) {
222      // "busy" buffer wraps, so "free" buffer is between put (inclusive) and
223      // get (exclusive).
224      EXPECT_LE(parser_put, put);
225      EXPECT_GT(parser_get, limit);
226    } else {
227      // "busy" buffer does not wrap, so the "free" buffer is the top side (from
228      // put to the limit) and the bottom side (from 0 to get).
229      if (put >= parser_put) {
230        // we're on the top side, check we are below the limit.
231        EXPECT_GE(kTotalNumCommandEntries, limit);
232      } else {
233        // we're on the bottom side, check we are below get.
234        EXPECT_GT(parser_get, limit);
235      }
236    }
237  }
238
239  int32 GetGetOffset() {
240    return command_buffer_->GetLastState().get_offset;
241  }
242
243  int32 GetPutOffset() {
244    return command_buffer_->GetLastState().put_offset;
245  }
246
247  int32 GetHelperGetOffset() { return helper_->get_offset(); }
248
249  int32 GetHelperPutOffset() { return helper_->put_; }
250
251  uint32 GetHelperFlushGeneration() { return helper_->flush_generation(); }
252
253  error::Error GetError() {
254    return command_buffer_->GetLastState().error;
255  }
256
257  CommandBufferOffset get_helper_put() { return helper_->put_; }
258
259#if defined(OS_MACOSX)
260  base::mac::ScopedNSAutoreleasePool autorelease_pool_;
261#endif
262  base::MessageLoop message_loop_;
263  scoped_ptr<AsyncAPIMock> api_mock_;
264  scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_;
265  scoped_ptr<CommandBufferServiceLocked> command_buffer_;
266  scoped_ptr<GpuScheduler> gpu_scheduler_;
267  scoped_ptr<CommandBufferHelper> helper_;
268  std::list<linked_ptr<std::vector<CommandBufferEntry> > > test_command_args_;
269  unsigned int test_command_next_id_;
270  Sequence sequence_;
271};
272
273// Checks immediate_entry_count_ changes based on 'usable' state.
274TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesNotUsable) {
275  // Auto flushing mode is tested separately.
276  helper_->SetAutomaticFlushes(false);
277  EXPECT_EQ(helper_->usable(), true);
278  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 1);
279  helper_->ClearUsable();
280  EXPECT_EQ(ImmediateEntryCount(), 0);
281}
282
283// Checks immediate_entry_count_ changes based on RingBuffer state.
284TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesNoRingBuffer) {
285  helper_->SetAutomaticFlushes(false);
286  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 1);
287  helper_->FreeRingBuffer();
288  EXPECT_EQ(ImmediateEntryCount(), 0);
289}
290
291// Checks immediate_entry_count_ calc when Put >= Get and Get == 0.
292TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesGetAtZero) {
293  // No internal auto flushing.
294  helper_->SetAutomaticFlushes(false);
295  command_buffer_->LockFlush();
296
297  // Start at Get = Put = 0.
298  EXPECT_EQ(GetHelperPutOffset(), 0);
299  EXPECT_EQ(GetHelperGetOffset(), 0);
300
301  // Immediate count should be 1 less than the end of the buffer.
302  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 1);
303  AddUniqueCommandWithExpect(error::kNoError, 2);
304  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 3);
305
306  helper_->Finish();
307
308  // Check that the commands did happen.
309  Mock::VerifyAndClearExpectations(api_mock_.get());
310
311  // Check the error status.
312  EXPECT_EQ(error::kNoError, GetError());
313}
314
315// Checks immediate_entry_count_ calc when Put >= Get and Get > 0.
316TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesGetInMiddle) {
317  // No internal auto flushing.
318  helper_->SetAutomaticFlushes(false);
319  command_buffer_->LockFlush();
320
321  // Move to Get = Put = 2.
322  AddUniqueCommandWithExpect(error::kNoError, 2);
323  helper_->Finish();
324  EXPECT_EQ(GetHelperPutOffset(), 2);
325  EXPECT_EQ(GetHelperGetOffset(), 2);
326
327  // Immediate count should be up to the end of the buffer.
328  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 2);
329  AddUniqueCommandWithExpect(error::kNoError, 2);
330  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 4);
331
332  helper_->Finish();
333
334  // Check that the commands did happen.
335  Mock::VerifyAndClearExpectations(api_mock_.get());
336
337  // Check the error status.
338  EXPECT_EQ(error::kNoError, GetError());
339}
340
341// Checks immediate_entry_count_ calc when Put < Get.
342TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesGetBeforePut) {
343  // Move to Get = kTotalNumCommandEntries / 4, Put = 0.
344  const int kInitGetOffset = kTotalNumCommandEntries / 4;
345  helper_->SetAutomaticFlushes(false);
346  command_buffer_->LockFlush();
347  AddUniqueCommandWithExpect(error::kNoError, kInitGetOffset);
348  helper_->Finish();
349  AddUniqueCommandWithExpect(error::kNoError,
350                             kTotalNumCommandEntries - kInitGetOffset);
351
352  // Flush instead of Finish will let Put wrap without the command buffer
353  // immediately processing the data between Get and Put.
354  helper_->Flush();
355
356  EXPECT_EQ(GetHelperGetOffset(), kInitGetOffset);
357  EXPECT_EQ(GetHelperPutOffset(), 0);
358
359  // Immediate count should be up to Get - 1.
360  EXPECT_EQ(ImmediateEntryCount(), kInitGetOffset - 1);
361  AddUniqueCommandWithExpect(error::kNoError, 2);
362  EXPECT_EQ(ImmediateEntryCount(), kInitGetOffset - 3);
363
364  helper_->Finish();
365  // Check that the commands did happen.
366  Mock::VerifyAndClearExpectations(api_mock_.get());
367
368  // Check the error status.
369  EXPECT_EQ(error::kNoError, GetError());
370}
371
372// Checks immediate_entry_count_ calc when automatic flushing is enabled.
373TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesAutoFlushing) {
374  command_buffer_->LockFlush();
375
376  // Start at Get = Put = 0.
377  EXPECT_EQ(GetHelperPutOffset(), 0);
378  EXPECT_EQ(GetHelperGetOffset(), 0);
379
380  // Without auto flushes, up to kTotalNumCommandEntries - 1 is available.
381  helper_->SetAutomaticFlushes(false);
382  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries - 1);
383
384  // With auto flushes, and Get == Last Put,
385  // up to kTotalNumCommandEntries / kAutoFlushSmall is available.
386  helper_->SetAutomaticFlushes(true);
387  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries / kAutoFlushSmall);
388
389  // With auto flushes, and Get != Last Put,
390  // up to kTotalNumCommandEntries / kAutoFlushBig is available.
391  AddUniqueCommandWithExpect(error::kNoError, 2);
392  helper_->Flush();
393  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries / kAutoFlushBig);
394
395  helper_->Finish();
396  // Check that the commands did happen.
397  Mock::VerifyAndClearExpectations(api_mock_.get());
398
399  // Check the error status.
400  EXPECT_EQ(error::kNoError, GetError());
401}
402
403// Checks immediate_entry_count_ calc when automatic flushing is enabled, and
404// we allocate commands over the immediate_entry_count_ size.
405TEST_F(CommandBufferHelperTest, TestCalcImmediateEntriesOverFlushLimit) {
406  // Lock internal flushing.
407  command_buffer_->LockFlush();
408
409  // Start at Get = Put = 0.
410  EXPECT_EQ(GetHelperPutOffset(), 0);
411  EXPECT_EQ(GetHelperGetOffset(), 0);
412
413  // Pre-check ImmediateEntryCount is limited with automatic flushing enabled.
414  helper_->SetAutomaticFlushes(true);
415  EXPECT_EQ(ImmediateEntryCount(), kTotalNumCommandEntries / kAutoFlushSmall);
416
417  // Add a command larger than ImmediateEntryCount().
418  AddUniqueCommandWithExpect(error::kNoError, ImmediateEntryCount() + 1);
419
420  // ImmediateEntryCount() should now be 0, to force a flush check on the next
421  // command.
422  EXPECT_EQ(ImmediateEntryCount(), 0);
423
424  // Add a command when ImmediateEntryCount() == 0.
425  AddUniqueCommandWithExpect(error::kNoError, ImmediateEntryCount() + 1);
426
427  helper_->Finish();
428  // Check that the commands did happen.
429  Mock::VerifyAndClearExpectations(api_mock_.get());
430
431  // Check the error status.
432  EXPECT_EQ(error::kNoError, GetError());
433}
434
435// Checks that commands in the buffer are properly executed, and that the
436// status/error stay valid.
437TEST_F(CommandBufferHelperTest, TestCommandProcessing) {
438  // Check initial state of the engine - it should have been configured by the
439  // helper.
440  EXPECT_TRUE(GetParser() != NULL);
441  EXPECT_EQ(error::kNoError, GetError());
442  EXPECT_EQ(0, GetGetOffset());
443
444  // Add 3 commands through the helper
445  AddCommandWithExpect(error::kNoError, kUnusedCommandId, 0, NULL);
446
447  CommandBufferEntry args1[2];
448  args1[0].value_uint32 = 3;
449  args1[1].value_float = 4.f;
450  AddCommandWithExpect(error::kNoError, kUnusedCommandId, 2, args1);
451
452  CommandBufferEntry args2[2];
453  args2[0].value_uint32 = 5;
454  args2[1].value_float = 6.f;
455  AddCommandWithExpect(error::kNoError, kUnusedCommandId, 2, args2);
456
457  // Wait until it's done.
458  helper_->Finish();
459  // Check that the engine has no more work to do.
460  EXPECT_TRUE(GetParser()->IsEmpty());
461
462  // Check that the commands did happen.
463  Mock::VerifyAndClearExpectations(api_mock_.get());
464
465  // Check the error status.
466  EXPECT_EQ(error::kNoError, GetError());
467}
468
469// Checks that commands in the buffer are properly executed when wrapping the
470// buffer, and that the status/error stay valid.
471TEST_F(CommandBufferHelperTest, TestCommandWrapping) {
472  // Add num_commands * commands of size 3 through the helper to make sure we
473  // do wrap.  kTotalNumCommandEntries must not be a multiple of 3.
474  COMPILE_ASSERT(kTotalNumCommandEntries % 3 != 0,
475                 Is_multiple_of_num_command_entries);
476  const int kNumCommands = (kTotalNumCommandEntries / 3) * 2;
477  CommandBufferEntry args1[2];
478  args1[0].value_uint32 = 5;
479  args1[1].value_float = 4.f;
480
481  for (int i = 0; i < kNumCommands; ++i) {
482    AddCommandWithExpect(error::kNoError, kUnusedCommandId + i, 2, args1);
483  }
484
485  helper_->Finish();
486  // Check that the commands did happen.
487  Mock::VerifyAndClearExpectations(api_mock_.get());
488
489  // Check the error status.
490  EXPECT_EQ(error::kNoError, GetError());
491}
492
493// Checks the case where the command inserted exactly matches the space left in
494// the command buffer.
495TEST_F(CommandBufferHelperTest, TestCommandWrappingExactMultiple) {
496  const int32 kCommandSize = kTotalNumCommandEntries / 2;
497  const size_t kNumArgs = kCommandSize - 1;
498  COMPILE_ASSERT(kTotalNumCommandEntries % kCommandSize == 0,
499                 Not_multiple_of_num_command_entries);
500  CommandBufferEntry args1[kNumArgs];
501  for (size_t ii = 0; ii < kNumArgs; ++ii) {
502    args1[ii].value_uint32 = ii + 1;
503  }
504
505  for (unsigned int i = 0; i < 5; ++i) {
506    AddCommandWithExpect(
507        error::kNoError, i + kUnusedCommandId, kNumArgs, args1);
508  }
509
510  helper_->Finish();
511  // Check that the commands did happen.
512  Mock::VerifyAndClearExpectations(api_mock_.get());
513
514  // Check the error status.
515  EXPECT_EQ(error::kNoError, GetError());
516}
517
518// Checks exact wrapping condition with Get = 0.
519TEST_F(CommandBufferHelperTest, TestCommandWrappingFullAtStart) {
520  TestCommandWrappingFull(2, 0);
521}
522
523// Checks exact wrapping condition with 0 < Get < kTotalNumCommandEntries.
524TEST_F(CommandBufferHelperTest, TestCommandWrappingFullInMiddle) {
525  TestCommandWrappingFull(2, 1);
526}
527
528// Checks exact wrapping condition with Get = kTotalNumCommandEntries.
529// Get should wrap back to 0, but making sure.
530TEST_F(CommandBufferHelperTest, TestCommandWrappingFullAtEnd) {
531  TestCommandWrappingFull(2, kTotalNumCommandEntries / 2);
532}
533
534// Checks that asking for available entries work, and that the parser
535// effectively won't use that space.
536TEST_F(CommandBufferHelperTest, TestAvailableEntries) {
537  CommandBufferEntry args[2];
538  args[0].value_uint32 = 3;
539  args[1].value_float = 4.f;
540
541  // Add 2 commands through the helper - 8 entries
542  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 1, 0, NULL);
543  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 2, 0, NULL);
544  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 3, 2, args);
545  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 4, 2, args);
546
547  // Ask for 5 entries.
548  helper_->WaitForAvailableEntries(5);
549
550  CommandBufferOffset put = get_helper_put();
551  CheckFreeSpace(put, 5);
552
553  // Add more commands.
554  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 5, 2, args);
555
556  // Wait until everything is done done.
557  helper_->Finish();
558
559  // Check that the commands did happen.
560  Mock::VerifyAndClearExpectations(api_mock_.get());
561
562  // Check the error status.
563  EXPECT_EQ(error::kNoError, GetError());
564}
565
566// Checks that the InsertToken/WaitForToken work.
567TEST_F(CommandBufferHelperTest, TestToken) {
568  CommandBufferEntry args[2];
569  args[0].value_uint32 = 3;
570  args[1].value_float = 4.f;
571
572  // Add a first command.
573  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 3, 2, args);
574  // keep track of the buffer position.
575  CommandBufferOffset command1_put = get_helper_put();
576  int32 token = helper_->InsertToken();
577
578  EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
579      .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
580                      Return(error::kNoError)));
581  // Add another command.
582  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 4, 2, args);
583  helper_->WaitForToken(token);
584  // check that the get pointer is beyond the first command.
585  EXPECT_LE(command1_put, GetGetOffset());
586  helper_->Finish();
587
588  // Check that the commands did happen.
589  Mock::VerifyAndClearExpectations(api_mock_.get());
590
591  // Check the error status.
592  EXPECT_EQ(error::kNoError, GetError());
593}
594
595// Checks WaitForToken doesn't Flush if token is already read.
596TEST_F(CommandBufferHelperTest, TestWaitForTokenFlush) {
597  CommandBufferEntry args[2];
598  args[0].value_uint32 = 3;
599  args[1].value_float = 4.f;
600
601  // Add a first command.
602  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 3, 2, args);
603  int32 token = helper_->InsertToken();
604
605  EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
606      .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
607                      Return(error::kNoError)));
608
609  int flush_count = command_buffer_->FlushCount();
610
611  // Test that waiting for pending token causes a Flush.
612  helper_->WaitForToken(token);
613  EXPECT_EQ(command_buffer_->FlushCount(), flush_count + 1);
614
615  // Test that we don't Flush repeatedly.
616  helper_->WaitForToken(token);
617  EXPECT_EQ(command_buffer_->FlushCount(), flush_count + 1);
618
619  // Add another command.
620  AddCommandWithExpect(error::kNoError, kUnusedCommandId + 4, 2, args);
621
622  // Test that we don't Flush repeatedly even if commands are pending.
623  helper_->WaitForToken(token);
624  EXPECT_EQ(command_buffer_->FlushCount(), flush_count + 1);
625
626  helper_->Finish();
627
628  // Check that the commands did happen.
629  Mock::VerifyAndClearExpectations(api_mock_.get());
630
631  // Check the error status.
632  EXPECT_EQ(error::kNoError, GetError());
633}
634
635TEST_F(CommandBufferHelperTest, FreeRingBuffer) {
636  EXPECT_TRUE(helper_->HaveRingBuffer());
637
638  // Test freeing ring buffer.
639  helper_->FreeRingBuffer();
640  EXPECT_FALSE(helper_->HaveRingBuffer());
641
642  // Test that InsertToken allocates a new one
643  int32 token = helper_->InsertToken();
644  EXPECT_TRUE(helper_->HaveRingBuffer());
645  EXPECT_CALL(*api_mock_.get(), DoCommand(cmd::kSetToken, 1, _))
646      .WillOnce(DoAll(Invoke(api_mock_.get(), &AsyncAPIMock::SetToken),
647                      Return(error::kNoError)));
648  helper_->WaitForToken(token);
649  helper_->FreeRingBuffer();
650  EXPECT_FALSE(helper_->HaveRingBuffer());
651
652  // Test that WaitForAvailableEntries allocates a new one
653  AddCommandWithExpect(error::kNoError, kUnusedCommandId, 0, NULL);
654  EXPECT_TRUE(helper_->HaveRingBuffer());
655  helper_->Finish();
656  helper_->FreeRingBuffer();
657  EXPECT_FALSE(helper_->HaveRingBuffer());
658
659  // Check that the commands did happen.
660  Mock::VerifyAndClearExpectations(api_mock_.get());
661}
662
663TEST_F(CommandBufferHelperTest, Noop) {
664  for (int ii = 1; ii < 4; ++ii) {
665    CommandBufferOffset put_before = get_helper_put();
666    helper_->Noop(ii);
667    CommandBufferOffset put_after = get_helper_put();
668    EXPECT_EQ(ii, put_after - put_before);
669  }
670}
671
672TEST_F(CommandBufferHelperTest, IsContextLost) {
673  EXPECT_FALSE(helper_->IsContextLost());
674  command_buffer_->SetParseError(error::kGenericError);
675  EXPECT_TRUE(helper_->IsContextLost());
676}
677
678// Checks helper's 'flush generation' updates.
679TEST_F(CommandBufferHelperTest, TestFlushGeneration) {
680  // Explicit flushing only.
681  helper_->SetAutomaticFlushes(false);
682
683  // Generation should change after Flush() but not before.
684  uint32 gen1, gen2, gen3;
685
686  gen1 = GetHelperFlushGeneration();
687  AddUniqueCommandWithExpect(error::kNoError, 2);
688  gen2 = GetHelperFlushGeneration();
689  helper_->Flush();
690  gen3 = GetHelperFlushGeneration();
691  EXPECT_EQ(gen2, gen1);
692  EXPECT_NE(gen3, gen2);
693
694  // Generation should change after Finish() but not before.
695  gen1 = GetHelperFlushGeneration();
696  AddUniqueCommandWithExpect(error::kNoError, 2);
697  gen2 = GetHelperFlushGeneration();
698  helper_->Finish();
699  gen3 = GetHelperFlushGeneration();
700  EXPECT_EQ(gen2, gen1);
701  EXPECT_NE(gen3, gen2);
702
703  helper_->Finish();
704
705  // Check that the commands did happen.
706  Mock::VerifyAndClearExpectations(api_mock_.get());
707
708  // Check the error status.
709  EXPECT_EQ(error::kNoError, GetError());
710}
711
712}  // namespace gpu
713