gles2_implementation_unittest.cc revision c5cede9ae108bb15f6b7a8aea21c7e1fefa2834c
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 GLES2Implementation.
6
7#include "gpu/command_buffer/client/gles2_implementation.h"
8
9#include <limits>
10
11#include <GLES2/gl2ext.h>
12#include <GLES2/gl2extchromium.h>
13#include "base/compiler_specific.h"
14#include "gpu/command_buffer/client/client_test_helper.h"
15#include "gpu/command_buffer/client/program_info_manager.h"
16#include "gpu/command_buffer/client/transfer_buffer.h"
17#include "gpu/command_buffer/common/command_buffer.h"
18#include "testing/gtest/include/gtest/gtest.h"
19#include "testing/gmock/include/gmock/gmock.h"
20
21#if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
22#define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
23#endif
24
25using testing::_;
26using testing::AtLeast;
27using testing::AnyNumber;
28using testing::DoAll;
29using testing::InSequence;
30using testing::Invoke;
31using testing::Mock;
32using testing::Sequence;
33using testing::StrictMock;
34using testing::Truly;
35using testing::Return;
36
37namespace gpu {
38namespace gles2 {
39
40ACTION_P2(SetMemory, dst, obj) {
41  memcpy(dst, &obj, sizeof(obj));
42}
43
44ACTION_P3(SetMemoryFromArray, dst, array, size) {
45  memcpy(dst, array, size);
46}
47
48// Used to help set the transfer buffer result to SizedResult of a single value.
49template <typename T>
50class SizedResultHelper {
51 public:
52  explicit SizedResultHelper(T result)
53      : size_(sizeof(result)),
54        result_(result) {
55  }
56
57 private:
58  uint32 size_;
59  T result_;
60};
61
62// Struct to make it easy to pass a vec4 worth of floats.
63struct FourFloats {
64  FourFloats(float _x, float _y, float _z, float _w)
65      : x(_x),
66        y(_y),
67        z(_z),
68        w(_w) {
69  }
70
71  float x;
72  float y;
73  float z;
74  float w;
75};
76
77#pragma pack(push, 1)
78// Struct that holds 7 characters.
79struct Str7 {
80  char str[7];
81};
82#pragma pack(pop)
83
84class MockTransferBuffer : public TransferBufferInterface {
85 public:
86  struct ExpectedMemoryInfo {
87    uint32 offset;
88    int32 id;
89    uint8* ptr;
90  };
91
92  MockTransferBuffer(
93      CommandBuffer* command_buffer,
94      unsigned int size,
95      unsigned int result_size,
96      unsigned int alignment)
97      : command_buffer_(command_buffer),
98        size_(size),
99        result_size_(result_size),
100        alignment_(alignment),
101        actual_buffer_index_(0),
102        expected_buffer_index_(0),
103        last_alloc_(NULL),
104        expected_offset_(result_size),
105        actual_offset_(result_size) {
106    // We have to allocate the buffers here because
107    // we need to know their address before GLES2Implementation::Initialize
108    // is called.
109    for (int ii = 0; ii < kNumBuffers; ++ii) {
110      buffers_[ii] = command_buffer_->CreateTransferBuffer(
111          size_ + ii * alignment_,
112          &buffer_ids_[ii]);
113      EXPECT_NE(-1, buffer_ids_[ii]);
114    }
115  }
116
117  virtual ~MockTransferBuffer() { }
118
119  virtual bool Initialize(
120      unsigned int starting_buffer_size,
121      unsigned int result_size,
122      unsigned int /* min_buffer_size */,
123      unsigned int /* max_buffer_size */,
124      unsigned int alignment,
125      unsigned int size_to_flush) OVERRIDE;
126  virtual int GetShmId() OVERRIDE;
127  virtual void* GetResultBuffer() OVERRIDE;
128  virtual int GetResultOffset() OVERRIDE;
129  virtual void Free() OVERRIDE;
130  virtual bool HaveBuffer() const OVERRIDE;
131  virtual void* AllocUpTo(
132      unsigned int size, unsigned int* size_allocated) OVERRIDE;
133  virtual void* Alloc(unsigned int size) OVERRIDE;
134  virtual RingBuffer::Offset GetOffset(void* pointer) const OVERRIDE;
135  virtual void FreePendingToken(void* p, unsigned int /* token */) OVERRIDE;
136
137  size_t MaxTransferBufferSize() {
138    return size_ - result_size_;
139  }
140
141  unsigned int RoundToAlignment(unsigned int size) {
142    return (size + alignment_ - 1) & ~(alignment_ - 1);
143  }
144
145  bool InSync() {
146    return expected_buffer_index_ == actual_buffer_index_ &&
147           expected_offset_ == actual_offset_;
148  }
149
150  ExpectedMemoryInfo GetExpectedMemory(size_t size) {
151    ExpectedMemoryInfo mem;
152    mem.offset = AllocateExpectedTransferBuffer(size);
153    mem.id = GetExpectedTransferBufferId();
154    mem.ptr = static_cast<uint8*>(
155       GetExpectedTransferAddressFromOffset(mem.offset, size));
156    return mem;
157  }
158
159  ExpectedMemoryInfo GetExpectedResultMemory(size_t size) {
160    ExpectedMemoryInfo mem;
161    mem.offset = GetExpectedResultBufferOffset();
162    mem.id = GetExpectedResultBufferId();
163    mem.ptr = static_cast<uint8*>(
164        GetExpectedTransferAddressFromOffset(mem.offset, size));
165    return mem;
166  }
167
168 private:
169  static const int kNumBuffers = 2;
170
171  uint8* actual_buffer() const {
172    return static_cast<uint8*>(buffers_[actual_buffer_index_]->memory());
173  }
174
175  uint8* expected_buffer() const {
176    return static_cast<uint8*>(buffers_[expected_buffer_index_]->memory());
177  }
178
179  uint32 AllocateExpectedTransferBuffer(size_t size) {
180    EXPECT_LE(size, MaxTransferBufferSize());
181
182    // Toggle which buffer we get each time to simulate the buffer being
183    // reallocated.
184    expected_buffer_index_ = (expected_buffer_index_ + 1) % kNumBuffers;
185
186    if (expected_offset_ + size > size_) {
187      expected_offset_ = result_size_;
188    }
189    uint32 offset = expected_offset_;
190    expected_offset_ += RoundToAlignment(size);
191
192    // Make sure each buffer has a different offset.
193    return offset + expected_buffer_index_ * alignment_;
194  }
195
196  void* GetExpectedTransferAddressFromOffset(uint32 offset, size_t size) {
197    EXPECT_GE(offset, expected_buffer_index_ * alignment_);
198    EXPECT_LE(offset + size, size_ + expected_buffer_index_ * alignment_);
199    return expected_buffer() + offset;
200  }
201
202  int GetExpectedResultBufferId() {
203    return buffer_ids_[expected_buffer_index_];
204  }
205
206  uint32 GetExpectedResultBufferOffset() {
207    return expected_buffer_index_ * alignment_;
208  }
209
210  int GetExpectedTransferBufferId() {
211    return buffer_ids_[expected_buffer_index_];
212  }
213
214  CommandBuffer* command_buffer_;
215  size_t size_;
216  size_t result_size_;
217  uint32 alignment_;
218  int buffer_ids_[kNumBuffers];
219  scoped_refptr<Buffer> buffers_[kNumBuffers];
220  int actual_buffer_index_;
221  int expected_buffer_index_;
222  void* last_alloc_;
223  uint32 expected_offset_;
224  uint32 actual_offset_;
225
226  DISALLOW_COPY_AND_ASSIGN(MockTransferBuffer);
227};
228
229bool MockTransferBuffer::Initialize(
230    unsigned int starting_buffer_size,
231    unsigned int result_size,
232    unsigned int /* min_buffer_size */,
233    unsigned int /* max_buffer_size */,
234    unsigned int alignment,
235    unsigned int /* size_to_flush */) {
236  // Just check they match.
237  return size_ == starting_buffer_size &&
238         result_size_ == result_size &&
239         alignment_ == alignment;
240};
241
242int MockTransferBuffer::GetShmId() {
243  return buffer_ids_[actual_buffer_index_];
244}
245
246void* MockTransferBuffer::GetResultBuffer() {
247  return actual_buffer() + actual_buffer_index_ * alignment_;
248}
249
250int MockTransferBuffer::GetResultOffset() {
251  return actual_buffer_index_ * alignment_;
252}
253
254void MockTransferBuffer::Free() {
255  NOTREACHED();
256}
257
258bool MockTransferBuffer::HaveBuffer() const {
259  return true;
260}
261
262void* MockTransferBuffer::AllocUpTo(
263    unsigned int size, unsigned int* size_allocated) {
264  EXPECT_TRUE(size_allocated != NULL);
265  EXPECT_TRUE(last_alloc_ == NULL);
266
267  // Toggle which buffer we get each time to simulate the buffer being
268  // reallocated.
269  actual_buffer_index_ = (actual_buffer_index_ + 1) % kNumBuffers;
270
271  size = std::min(static_cast<size_t>(size), MaxTransferBufferSize());
272  if (actual_offset_ + size > size_) {
273    actual_offset_ = result_size_;
274  }
275  uint32 offset = actual_offset_;
276  actual_offset_ += RoundToAlignment(size);
277  *size_allocated = size;
278
279  // Make sure each buffer has a different offset.
280  last_alloc_ = actual_buffer() + offset + actual_buffer_index_ * alignment_;
281  return last_alloc_;
282}
283
284void* MockTransferBuffer::Alloc(unsigned int size) {
285  EXPECT_LE(size, MaxTransferBufferSize());
286  unsigned int temp = 0;
287  void* p = AllocUpTo(size, &temp);
288  EXPECT_EQ(temp, size);
289  return p;
290}
291
292RingBuffer::Offset MockTransferBuffer::GetOffset(void* pointer) const {
293  // Make sure each buffer has a different offset.
294  return static_cast<uint8*>(pointer) - actual_buffer();
295}
296
297void MockTransferBuffer::FreePendingToken(void* p, unsigned int /* token */) {
298  EXPECT_EQ(last_alloc_, p);
299  last_alloc_ = NULL;
300}
301
302// API wrapper for Buffers.
303class GenBuffersAPI {
304 public:
305  static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
306    gl_impl->GenBuffers(n, ids);
307  }
308
309  static void Delete(GLES2Implementation* gl_impl,
310                     GLsizei n,
311                     const GLuint* ids) {
312    gl_impl->DeleteBuffers(n, ids);
313  }
314};
315
316// API wrapper for Framebuffers.
317class GenFramebuffersAPI {
318 public:
319  static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
320    gl_impl->GenFramebuffers(n, ids);
321  }
322
323  static void Delete(GLES2Implementation* gl_impl,
324                     GLsizei n,
325                     const GLuint* ids) {
326    gl_impl->DeleteFramebuffers(n, ids);
327  }
328};
329
330// API wrapper for Renderbuffers.
331class GenRenderbuffersAPI {
332 public:
333  static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
334    gl_impl->GenRenderbuffers(n, ids);
335  }
336
337  static void Delete(GLES2Implementation* gl_impl,
338                     GLsizei n,
339                     const GLuint* ids) {
340    gl_impl->DeleteRenderbuffers(n, ids);
341  }
342};
343
344// API wrapper for Textures.
345class GenTexturesAPI {
346 public:
347  static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
348    gl_impl->GenTextures(n, ids);
349  }
350
351  static void Delete(GLES2Implementation* gl_impl,
352                     GLsizei n,
353                     const GLuint* ids) {
354    gl_impl->DeleteTextures(n, ids);
355  }
356};
357
358class GLES2ImplementationTest : public testing::Test {
359 protected:
360  static const int kNumTestContexts = 2;
361  static const uint8 kInitialValue = 0xBD;
362  static const int32 kNumCommandEntries = 500;
363  static const int32 kCommandBufferSizeBytes =
364      kNumCommandEntries * sizeof(CommandBufferEntry);
365  static const size_t kTransferBufferSize = 512;
366
367  static const GLint kMaxCombinedTextureImageUnits = 8;
368  static const GLint kMaxCubeMapTextureSize = 64;
369  static const GLint kMaxFragmentUniformVectors = 16;
370  static const GLint kMaxRenderbufferSize = 64;
371  static const GLint kMaxTextureImageUnits = 8;
372  static const GLint kMaxTextureSize = 128;
373  static const GLint kMaxVaryingVectors = 8;
374  static const GLint kMaxVertexAttribs = 8;
375  static const GLint kMaxVertexTextureImageUnits = 0;
376  static const GLint kMaxVertexUniformVectors = 128;
377  static const GLint kNumCompressedTextureFormats = 0;
378  static const GLint kNumShaderBinaryFormats = 0;
379  static const GLuint kStartId = 1024;
380  static const GLuint kBuffersStartId =
381      GLES2Implementation::kClientSideArrayId + 2 * kNumTestContexts;
382  static const GLuint kFramebuffersStartId = 1;
383  static const GLuint kProgramsAndShadersStartId = 1;
384  static const GLuint kRenderbuffersStartId = 1;
385  static const GLuint kTexturesStartId = 1;
386  static const GLuint kQueriesStartId = 1;
387  static const GLuint kVertexArraysStartId = 1;
388
389  typedef MockTransferBuffer::ExpectedMemoryInfo ExpectedMemoryInfo;
390
391  class TestContext {
392   public:
393    TestContext() : commands_(NULL), token_(0) {}
394
395    bool Initialize(ShareGroup* share_group,
396                    bool bind_generates_resource,
397                    bool lose_context_when_out_of_memory) {
398      command_buffer_.reset(new StrictMock<MockClientCommandBuffer>());
399      if (!command_buffer_->Initialize())
400        return false;
401
402      transfer_buffer_.reset(
403          new MockTransferBuffer(command_buffer_.get(),
404                                 kTransferBufferSize,
405                                 GLES2Implementation::kStartingOffset,
406                                 GLES2Implementation::kAlignment));
407
408      helper_.reset(new GLES2CmdHelper(command_buffer()));
409      helper_->Initialize(kCommandBufferSizeBytes);
410
411      gpu_control_.reset(new StrictMock<MockClientGpuControl>());
412      EXPECT_CALL(*gpu_control_, GetCapabilities())
413          .WillOnce(testing::Return(Capabilities()));
414
415      GLES2Implementation::GLStaticState state;
416      GLES2Implementation::GLStaticState::IntState& int_state = state.int_state;
417      int_state.max_combined_texture_image_units =
418          kMaxCombinedTextureImageUnits;
419      int_state.max_cube_map_texture_size = kMaxCubeMapTextureSize;
420      int_state.max_fragment_uniform_vectors = kMaxFragmentUniformVectors;
421      int_state.max_renderbuffer_size = kMaxRenderbufferSize;
422      int_state.max_texture_image_units = kMaxTextureImageUnits;
423      int_state.max_texture_size = kMaxTextureSize;
424      int_state.max_varying_vectors = kMaxVaryingVectors;
425      int_state.max_vertex_attribs = kMaxVertexAttribs;
426      int_state.max_vertex_texture_image_units = kMaxVertexTextureImageUnits;
427      int_state.max_vertex_uniform_vectors = kMaxVertexUniformVectors;
428      int_state.num_compressed_texture_formats = kNumCompressedTextureFormats;
429      int_state.num_shader_binary_formats = kNumShaderBinaryFormats;
430      int_state.bind_generates_resource_chromium =
431          bind_generates_resource ? 1 : 0;
432
433      // This just happens to work for now because IntState has 1 GLint per
434      // state.
435      // If IntState gets more complicated this code will need to get more
436      // complicated.
437      ExpectedMemoryInfo mem1 = transfer_buffer_->GetExpectedMemory(
438          sizeof(GLES2Implementation::GLStaticState::IntState) * 2 +
439          sizeof(cmds::GetShaderPrecisionFormat::Result) * 12);
440
441      {
442        InSequence sequence;
443
444        EXPECT_CALL(*command_buffer_, OnFlush())
445            .WillOnce(SetMemory(mem1.ptr + sizeof(int_state), int_state))
446            .RetiresOnSaturation();
447        GetNextToken();  // eat the token that starting up will use.
448
449        gl_.reset(new GLES2Implementation(helper_.get(),
450                                          share_group,
451                                          transfer_buffer_.get(),
452                                          bind_generates_resource,
453                                          lose_context_when_out_of_memory,
454                                          gpu_control_.get()));
455
456        if (!gl_->Initialize(kTransferBufferSize,
457                             kTransferBufferSize,
458                             kTransferBufferSize,
459                             GLES2Implementation::kNoLimit))
460          return false;
461      }
462
463      EXPECT_CALL(*command_buffer_, OnFlush()).Times(1).RetiresOnSaturation();
464      helper_->CommandBufferHelper::Finish();
465      ::testing::Mock::VerifyAndClearExpectations(gl_.get());
466
467      scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
468      commands_ = static_cast<CommandBufferEntry*>(ring_buffer->memory()) +
469                  command_buffer()->GetState().put_offset;
470      ClearCommands();
471      EXPECT_TRUE(transfer_buffer_->InSync());
472
473      ::testing::Mock::VerifyAndClearExpectations(command_buffer());
474      return true;
475    }
476
477    void TearDown() {
478      Mock::VerifyAndClear(gl_.get());
479      EXPECT_CALL(*command_buffer(), OnFlush()).Times(AnyNumber());
480      // For command buffer.
481      EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
482          .Times(AtLeast(1));
483      gl_.reset();
484    }
485
486    MockClientCommandBuffer* command_buffer() const {
487      return command_buffer_.get();
488    }
489
490    int GetNextToken() { return ++token_; }
491
492    void ClearCommands() {
493      scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
494      memset(ring_buffer->memory(), kInitialValue, ring_buffer->size());
495    }
496
497    scoped_ptr<MockClientCommandBuffer> command_buffer_;
498    scoped_ptr<MockClientGpuControl> gpu_control_;
499    scoped_ptr<GLES2CmdHelper> helper_;
500    scoped_ptr<MockTransferBuffer> transfer_buffer_;
501    scoped_ptr<GLES2Implementation> gl_;
502    CommandBufferEntry* commands_;
503    int token_;
504  };
505
506  GLES2ImplementationTest() : commands_(NULL) {}
507
508  virtual void SetUp() OVERRIDE;
509  virtual void TearDown() OVERRIDE;
510
511  bool NoCommandsWritten() {
512    scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
513    const uint8* cmds = reinterpret_cast<const uint8*>(ring_buffer->memory());
514    const uint8* end = cmds + ring_buffer->size();
515    for (; cmds < end; ++cmds) {
516      if (*cmds != kInitialValue) {
517        return false;
518      }
519    }
520    return true;
521  }
522
523  QueryTracker::Query* GetQuery(GLuint id) {
524    return gl_->query_tracker_->GetQuery(id);
525  }
526
527  struct ContextInitOptions {
528    ContextInitOptions()
529        : bind_generates_resource_client(true),
530          bind_generates_resource_service(true),
531          lose_context_when_out_of_memory(false) {}
532
533    bool bind_generates_resource_client;
534    bool bind_generates_resource_service;
535    bool lose_context_when_out_of_memory;
536  };
537
538  bool Initialize(const ContextInitOptions& init_options) {
539    bool success = true;
540    share_group_ = new ShareGroup(init_options.bind_generates_resource_service);
541
542    for (int i = 0; i < kNumTestContexts; i++) {
543      if (!test_contexts_[i].Initialize(
544              share_group_.get(),
545              init_options.bind_generates_resource_client,
546              init_options.lose_context_when_out_of_memory))
547        success = false;
548    }
549
550    // Default to test context 0.
551    gpu_control_ = test_contexts_[0].gpu_control_.get();
552    helper_ = test_contexts_[0].helper_.get();
553    transfer_buffer_ = test_contexts_[0].transfer_buffer_.get();
554    gl_ = test_contexts_[0].gl_.get();
555    commands_ = test_contexts_[0].commands_;
556    return success;
557  }
558
559  MockClientCommandBuffer* command_buffer() const {
560    return test_contexts_[0].command_buffer_.get();
561  }
562
563  int GetNextToken() { return test_contexts_[0].GetNextToken(); }
564
565  const void* GetPut() {
566    return helper_->GetSpace(0);
567  }
568
569  void ClearCommands() {
570    scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
571    memset(ring_buffer->memory(), kInitialValue, ring_buffer->size());
572  }
573
574  size_t MaxTransferBufferSize() {
575    return transfer_buffer_->MaxTransferBufferSize();
576  }
577
578  ExpectedMemoryInfo GetExpectedMemory(size_t size) {
579    return transfer_buffer_->GetExpectedMemory(size);
580  }
581
582  ExpectedMemoryInfo GetExpectedResultMemory(size_t size) {
583    return transfer_buffer_->GetExpectedResultMemory(size);
584  }
585
586  // Sets the ProgramInfoManager. The manager will be owned
587  // by the ShareGroup.
588  void SetProgramInfoManager(ProgramInfoManager* manager) {
589    gl_->share_group()->set_program_info_manager(manager);
590  }
591
592  int CheckError() {
593    ExpectedMemoryInfo result =
594        GetExpectedResultMemory(sizeof(cmds::GetError::Result));
595    EXPECT_CALL(*command_buffer(), OnFlush())
596        .WillOnce(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
597        .RetiresOnSaturation();
598    return gl_->GetError();
599  }
600
601  bool GetBucketContents(uint32 bucket_id, std::vector<int8>* data) {
602    return gl_->GetBucketContents(bucket_id, data);
603  }
604
605  TestContext test_contexts_[kNumTestContexts];
606
607  scoped_refptr<ShareGroup> share_group_;
608  MockClientGpuControl* gpu_control_;
609  GLES2CmdHelper* helper_;
610  MockTransferBuffer* transfer_buffer_;
611  GLES2Implementation* gl_;
612  CommandBufferEntry* commands_;
613};
614
615void GLES2ImplementationTest::SetUp() {
616  ContextInitOptions init_options;
617  ASSERT_TRUE(Initialize(init_options));
618}
619
620void GLES2ImplementationTest::TearDown() {
621  for (int i = 0; i < kNumTestContexts; i++)
622    test_contexts_[i].TearDown();
623}
624
625class GLES2ImplementationManualInitTest : public GLES2ImplementationTest {
626 protected:
627  virtual void SetUp() OVERRIDE {}
628};
629
630class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest {
631 protected:
632  virtual void SetUp() OVERRIDE;
633
634  template <class ResApi>
635  void FlushGenerationTest() {
636    GLuint id1, id2, id3;
637
638    // Generate valid id.
639    ResApi::Gen(gl_, 1, &id1);
640    EXPECT_NE(id1, 0u);
641
642    // Delete id1 and generate id2.  id1 should not be reused.
643    ResApi::Delete(gl_, 1, &id1);
644    ResApi::Gen(gl_, 1, &id2);
645    EXPECT_NE(id2, 0u);
646    EXPECT_NE(id2, id1);
647
648    // Expect id1 reuse after Flush.
649    gl_->Flush();
650    ResApi::Gen(gl_, 1, &id3);
651    EXPECT_EQ(id3, id1);
652  }
653
654  // Ids should not be reused unless the |Deleting| context does a Flush()
655  // AND triggers a lazy release after that.
656  template <class ResApi>
657  void CrossContextGenerationTest() {
658    GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
659    GLES2Implementation* gl2 = test_contexts_[1].gl_.get();
660    GLuint id1, id2, id3;
661
662    // Delete, no flush on context 1.  No reuse.
663    ResApi::Gen(gl1, 1, &id1);
664    ResApi::Delete(gl1, 1, &id1);
665    ResApi::Gen(gl1, 1, &id2);
666    EXPECT_NE(id1, id2);
667
668    // Flush context 2.  Still no reuse.
669    gl2->Flush();
670    ResApi::Gen(gl2, 1, &id3);
671    EXPECT_NE(id1, id3);
672    EXPECT_NE(id2, id3);
673
674    // Flush on context 1, but no lazy release.  Still no reuse.
675    gl1->Flush();
676    ResApi::Gen(gl2, 1, &id3);
677    EXPECT_NE(id1, id3);
678
679    // Lazy release triggered by another Delete.  Should reuse id1.
680    ResApi::Delete(gl1, 1, &id2);
681    ResApi::Gen(gl2, 1, &id3);
682    EXPECT_EQ(id1, id3);
683  }
684
685  // Same as CrossContextGenerationTest(), but triggers an Auto Flush on
686  // the Delete().  Tests an edge case regression.
687  template <class ResApi>
688  void CrossContextGenerationAutoFlushTest() {
689    GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
690    GLES2Implementation* gl2 = test_contexts_[1].gl_.get();
691    GLuint id1, id2, id3;
692
693    // Delete, no flush on context 1.  No reuse.
694    // By half filling the buffer, an internal flush is forced on the Delete().
695    ResApi::Gen(gl1, 1, &id1);
696    gl1->helper()->Noop(kNumCommandEntries / 2);
697    ResApi::Delete(gl1, 1, &id1);
698    ResApi::Gen(gl1, 1, &id2);
699    EXPECT_NE(id1, id2);
700
701    // Flush context 2.  Still no reuse.
702    gl2->Flush();
703    ResApi::Gen(gl2, 1, &id3);
704    EXPECT_NE(id1, id3);
705    EXPECT_NE(id2, id3);
706
707    // Flush on context 1, but no lazy release.  Still no reuse.
708    gl1->Flush();
709    ResApi::Gen(gl2, 1, &id3);
710    EXPECT_NE(id1, id3);
711
712    // Lazy release triggered by another Delete.  Should reuse id1.
713    ResApi::Delete(gl1, 1, &id2);
714    ResApi::Gen(gl2, 1, &id3);
715    EXPECT_EQ(id1, id3);
716  }
717};
718
719void GLES2ImplementationStrictSharedTest::SetUp() {
720  ContextInitOptions init_options;
721  init_options.bind_generates_resource_client = false;
722  init_options.bind_generates_resource_service = false;
723  ASSERT_TRUE(Initialize(init_options));
724}
725
726// GCC requires these declarations, but MSVC requires they not be present
727#ifndef _MSC_VER
728const uint8 GLES2ImplementationTest::kInitialValue;
729const int32 GLES2ImplementationTest::kNumCommandEntries;
730const int32 GLES2ImplementationTest::kCommandBufferSizeBytes;
731const size_t GLES2ImplementationTest::kTransferBufferSize;
732const GLint GLES2ImplementationTest::kMaxCombinedTextureImageUnits;
733const GLint GLES2ImplementationTest::kMaxCubeMapTextureSize;
734const GLint GLES2ImplementationTest::kMaxFragmentUniformVectors;
735const GLint GLES2ImplementationTest::kMaxRenderbufferSize;
736const GLint GLES2ImplementationTest::kMaxTextureImageUnits;
737const GLint GLES2ImplementationTest::kMaxTextureSize;
738const GLint GLES2ImplementationTest::kMaxVaryingVectors;
739const GLint GLES2ImplementationTest::kMaxVertexAttribs;
740const GLint GLES2ImplementationTest::kMaxVertexTextureImageUnits;
741const GLint GLES2ImplementationTest::kMaxVertexUniformVectors;
742const GLint GLES2ImplementationTest::kNumCompressedTextureFormats;
743const GLint GLES2ImplementationTest::kNumShaderBinaryFormats;
744const GLuint GLES2ImplementationTest::kStartId;
745const GLuint GLES2ImplementationTest::kBuffersStartId;
746const GLuint GLES2ImplementationTest::kFramebuffersStartId;
747const GLuint GLES2ImplementationTest::kProgramsAndShadersStartId;
748const GLuint GLES2ImplementationTest::kRenderbuffersStartId;
749const GLuint GLES2ImplementationTest::kTexturesStartId;
750const GLuint GLES2ImplementationTest::kQueriesStartId;
751const GLuint GLES2ImplementationTest::kVertexArraysStartId;
752#endif
753
754TEST_F(GLES2ImplementationTest, Basic) {
755  EXPECT_TRUE(gl_->share_group() != NULL);
756}
757
758TEST_F(GLES2ImplementationTest, GetBucketContents) {
759  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
760  const uint32 kTestSize = MaxTransferBufferSize() + 32;
761
762  scoped_ptr<uint8[]> buf(new uint8 [kTestSize]);
763  uint8* expected_data = buf.get();
764  for (uint32 ii = 0; ii < kTestSize; ++ii) {
765    expected_data[ii] = ii * 3;
766  }
767
768  struct Cmds {
769    cmd::GetBucketStart get_bucket_start;
770    cmd::SetToken set_token1;
771    cmd::GetBucketData get_bucket_data;
772    cmd::SetToken set_token2;
773    cmd::SetBucketSize set_bucket_size2;
774  };
775
776  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
777  ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32));
778  ExpectedMemoryInfo mem2 = GetExpectedMemory(
779      kTestSize - MaxTransferBufferSize());
780
781  Cmds expected;
782  expected.get_bucket_start.Init(
783      kBucketId, result1.id, result1.offset,
784      MaxTransferBufferSize(), mem1.id, mem1.offset);
785  expected.set_token1.Init(GetNextToken());
786  expected.get_bucket_data.Init(
787      kBucketId, MaxTransferBufferSize(),
788      kTestSize - MaxTransferBufferSize(), mem2.id, mem2.offset);
789  expected.set_bucket_size2.Init(kBucketId, 0);
790  expected.set_token2.Init(GetNextToken());
791
792  EXPECT_CALL(*command_buffer(), OnFlush())
793      .WillOnce(DoAll(
794          SetMemory(result1.ptr, kTestSize),
795          SetMemoryFromArray(
796              mem1.ptr, expected_data, MaxTransferBufferSize())))
797      .WillOnce(SetMemoryFromArray(
798          mem2.ptr, expected_data + MaxTransferBufferSize(),
799          kTestSize - MaxTransferBufferSize()))
800      .RetiresOnSaturation();
801
802  std::vector<int8> data;
803  GetBucketContents(kBucketId, &data);
804  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
805  ASSERT_EQ(kTestSize, data.size());
806  EXPECT_EQ(0, memcmp(expected_data, &data[0], data.size()));
807}
808
809TEST_F(GLES2ImplementationTest, GetShaderPrecisionFormat) {
810  struct Cmds {
811    cmds::GetShaderPrecisionFormat cmd;
812  };
813  typedef cmds::GetShaderPrecisionFormat::Result Result;
814
815  // The first call for mediump should trigger a command buffer request.
816  GLint range1[2] = {0, 0};
817  GLint precision1 = 0;
818  Cmds expected1;
819  ExpectedMemoryInfo client_result1 = GetExpectedResultMemory(4);
820  expected1.cmd.Init(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT,
821                     client_result1.id, client_result1.offset);
822  Result server_result1 = {true, 14, 14, 10};
823  EXPECT_CALL(*command_buffer(), OnFlush())
824      .WillOnce(SetMemory(client_result1.ptr, server_result1))
825      .RetiresOnSaturation();
826  gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT,
827                                range1, &precision1);
828  const void* commands2 = GetPut();
829  EXPECT_NE(commands_, commands2);
830  EXPECT_EQ(0, memcmp(&expected1, commands_, sizeof(expected1)));
831  EXPECT_EQ(range1[0], 14);
832  EXPECT_EQ(range1[1], 14);
833  EXPECT_EQ(precision1, 10);
834
835  // The second call for mediump should use the cached value and avoid
836  // triggering a command buffer request, so we do not expect a call to
837  // OnFlush() here. We do expect the results to be correct though.
838  GLint range2[2] = {0, 0};
839  GLint precision2 = 0;
840  gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT,
841                                range2, &precision2);
842  const void* commands3 = GetPut();
843  EXPECT_EQ(commands2, commands3);
844  EXPECT_EQ(range2[0], 14);
845  EXPECT_EQ(range2[1], 14);
846  EXPECT_EQ(precision2, 10);
847
848  // If we then make a request for highp, we should get another command
849  // buffer request since it hasn't been cached yet.
850  GLint range3[2] = {0, 0};
851  GLint precision3 = 0;
852  Cmds expected3;
853  ExpectedMemoryInfo result3 = GetExpectedResultMemory(4);
854  expected3.cmd.Init(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
855                     result3.id, result3.offset);
856  Result result3_source = {true, 62, 62, 16};
857  EXPECT_CALL(*command_buffer(), OnFlush())
858      .WillOnce(SetMemory(result3.ptr, result3_source))
859      .RetiresOnSaturation();
860  gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
861                                range3, &precision3);
862  const void* commands4 = GetPut();
863  EXPECT_NE(commands3, commands4);
864  EXPECT_EQ(0, memcmp(&expected3, commands3, sizeof(expected3)));
865  EXPECT_EQ(range3[0], 62);
866  EXPECT_EQ(range3[1], 62);
867  EXPECT_EQ(precision3, 16);
868}
869
870TEST_F(GLES2ImplementationTest, ShaderSource) {
871  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
872  const GLuint kShaderId = 456;
873  const char* kString1 = "foobar";
874  const char* kString2 = "barfoo";
875  const size_t kString1Size = strlen(kString1);
876  const size_t kString2Size = strlen(kString2);
877  const size_t kString3Size = 1;  // Want the NULL;
878  const size_t kSourceSize = kString1Size + kString2Size + kString3Size;
879  const size_t kPaddedString1Size =
880      transfer_buffer_->RoundToAlignment(kString1Size);
881  const size_t kPaddedString2Size =
882      transfer_buffer_->RoundToAlignment(kString2Size);
883  const size_t kPaddedString3Size =
884      transfer_buffer_->RoundToAlignment(kString3Size);
885  struct Cmds {
886    cmd::SetBucketSize set_bucket_size;
887    cmd::SetBucketData set_bucket_data1;
888    cmd::SetToken set_token1;
889    cmd::SetBucketData set_bucket_data2;
890    cmd::SetToken set_token2;
891    cmd::SetBucketData set_bucket_data3;
892    cmd::SetToken set_token3;
893    cmds::ShaderSourceBucket shader_source_bucket;
894    cmd::SetBucketSize clear_bucket_size;
895  };
896
897  ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size);
898  ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size);
899  ExpectedMemoryInfo mem3 = GetExpectedMemory(kPaddedString3Size);
900
901  Cmds expected;
902  expected.set_bucket_size.Init(kBucketId, kSourceSize);
903  expected.set_bucket_data1.Init(
904      kBucketId, 0, kString1Size, mem1.id, mem1.offset);
905  expected.set_token1.Init(GetNextToken());
906  expected.set_bucket_data2.Init(
907      kBucketId, kString1Size, kString2Size, mem2.id, mem2.offset);
908  expected.set_token2.Init(GetNextToken());
909  expected.set_bucket_data3.Init(
910      kBucketId, kString1Size + kString2Size,
911      kString3Size, mem3.id, mem3.offset);
912  expected.set_token3.Init(GetNextToken());
913  expected.shader_source_bucket.Init(kShaderId, kBucketId);
914  expected.clear_bucket_size.Init(kBucketId, 0);
915  const char* strings[] = {
916    kString1,
917    kString2,
918  };
919  gl_->ShaderSource(kShaderId, 2, strings, NULL);
920  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
921}
922
923TEST_F(GLES2ImplementationTest, GetShaderSource) {
924  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
925  const GLuint kShaderId = 456;
926  const Str7 kString = {"foobar"};
927  const char kBad = 0x12;
928  struct Cmds {
929    cmd::SetBucketSize set_bucket_size1;
930    cmds::GetShaderSource get_shader_source;
931    cmd::GetBucketStart get_bucket_start;
932    cmd::SetToken set_token1;
933    cmd::SetBucketSize set_bucket_size2;
934  };
935
936  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
937  ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32));
938
939  Cmds expected;
940  expected.set_bucket_size1.Init(kBucketId, 0);
941  expected.get_shader_source.Init(kShaderId, kBucketId);
942  expected.get_bucket_start.Init(
943      kBucketId, result1.id, result1.offset,
944      MaxTransferBufferSize(), mem1.id, mem1.offset);
945  expected.set_token1.Init(GetNextToken());
946  expected.set_bucket_size2.Init(kBucketId, 0);
947  char buf[sizeof(kString) + 1];
948  memset(buf, kBad, sizeof(buf));
949
950  EXPECT_CALL(*command_buffer(), OnFlush())
951      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
952                      SetMemory(mem1.ptr, kString)))
953      .RetiresOnSaturation();
954
955  GLsizei length = 0;
956  gl_->GetShaderSource(kShaderId, sizeof(buf), &length, buf);
957  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
958  EXPECT_EQ(sizeof(kString) - 1, static_cast<size_t>(length));
959  EXPECT_STREQ(kString.str, buf);
960  EXPECT_EQ(buf[sizeof(kString)], kBad);
961}
962
963#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
964
965TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) {
966  static const float verts[][4] = {
967    { 12.0f, 23.0f, 34.0f, 45.0f, },
968    { 56.0f, 67.0f, 78.0f, 89.0f, },
969    { 13.0f, 24.0f, 35.0f, 46.0f, },
970  };
971  struct Cmds {
972    cmds::EnableVertexAttribArray enable1;
973    cmds::EnableVertexAttribArray enable2;
974    cmds::BindBuffer bind_to_emu;
975    cmds::BufferData set_size;
976    cmds::BufferSubData copy_data1;
977    cmd::SetToken set_token1;
978    cmds::VertexAttribPointer set_pointer1;
979    cmds::BufferSubData copy_data2;
980    cmd::SetToken set_token2;
981    cmds::VertexAttribPointer set_pointer2;
982    cmds::DrawArrays draw;
983    cmds::BindBuffer restore;
984  };
985  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
986  const GLuint kAttribIndex1 = 1;
987  const GLuint kAttribIndex2 = 3;
988  const GLint kNumComponents1 = 3;
989  const GLint kNumComponents2 = 2;
990  const GLsizei kClientStride = sizeof(verts[0]);
991  const GLint kFirst = 1;
992  const GLsizei kCount = 2;
993  const GLsizei kSize1 =
994      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
995  const GLsizei kSize2 =
996      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
997  const GLsizei kEmuOffset1 = 0;
998  const GLsizei kEmuOffset2 = kSize1;
999  const GLsizei kTotalSize = kSize1 + kSize2;
1000
1001  ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1);
1002  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2);
1003
1004  Cmds expected;
1005  expected.enable1.Init(kAttribIndex1);
1006  expected.enable2.Init(kAttribIndex2);
1007  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1008  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1009  expected.copy_data1.Init(
1010      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset);
1011  expected.set_token1.Init(GetNextToken());
1012  expected.set_pointer1.Init(
1013      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1014  expected.copy_data2.Init(
1015      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset);
1016  expected.set_token2.Init(GetNextToken());
1017  expected.set_pointer2.Init(
1018      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1019  expected.draw.Init(GL_POINTS, kFirst, kCount);
1020  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1021  gl_->EnableVertexAttribArray(kAttribIndex1);
1022  gl_->EnableVertexAttribArray(kAttribIndex2);
1023  gl_->VertexAttribPointer(
1024      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts);
1025  gl_->VertexAttribPointer(
1026      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts);
1027  gl_->DrawArrays(GL_POINTS, kFirst, kCount);
1028  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1029}
1030
1031TEST_F(GLES2ImplementationTest, DrawArraysInstancedANGLEClientSideBuffers) {
1032  static const float verts[][4] = {
1033    { 12.0f, 23.0f, 34.0f, 45.0f, },
1034    { 56.0f, 67.0f, 78.0f, 89.0f, },
1035    { 13.0f, 24.0f, 35.0f, 46.0f, },
1036  };
1037  struct Cmds {
1038    cmds::EnableVertexAttribArray enable1;
1039    cmds::EnableVertexAttribArray enable2;
1040    cmds::VertexAttribDivisorANGLE divisor;
1041    cmds::BindBuffer bind_to_emu;
1042    cmds::BufferData set_size;
1043    cmds::BufferSubData copy_data1;
1044    cmd::SetToken set_token1;
1045    cmds::VertexAttribPointer set_pointer1;
1046    cmds::BufferSubData copy_data2;
1047    cmd::SetToken set_token2;
1048    cmds::VertexAttribPointer set_pointer2;
1049    cmds::DrawArraysInstancedANGLE draw;
1050    cmds::BindBuffer restore;
1051  };
1052  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1053  const GLuint kAttribIndex1 = 1;
1054  const GLuint kAttribIndex2 = 3;
1055  const GLint kNumComponents1 = 3;
1056  const GLint kNumComponents2 = 2;
1057  const GLsizei kClientStride = sizeof(verts[0]);
1058  const GLint kFirst = 1;
1059  const GLsizei kCount = 2;
1060  const GLuint kDivisor = 1;
1061  const GLsizei kSize1 =
1062      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1063  const GLsizei kSize2 =
1064      1 * kNumComponents2 * sizeof(verts[0][0]);
1065  const GLsizei kEmuOffset1 = 0;
1066  const GLsizei kEmuOffset2 = kSize1;
1067  const GLsizei kTotalSize = kSize1 + kSize2;
1068
1069  ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1);
1070  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2);
1071
1072  Cmds expected;
1073  expected.enable1.Init(kAttribIndex1);
1074  expected.enable2.Init(kAttribIndex2);
1075  expected.divisor.Init(kAttribIndex2, kDivisor);
1076  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1077  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1078  expected.copy_data1.Init(
1079      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset);
1080  expected.set_token1.Init(GetNextToken());
1081  expected.set_pointer1.Init(
1082      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1083  expected.copy_data2.Init(
1084      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset);
1085  expected.set_token2.Init(GetNextToken());
1086  expected.set_pointer2.Init(
1087      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1088  expected.draw.Init(GL_POINTS, kFirst, kCount, 1);
1089  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1090  gl_->EnableVertexAttribArray(kAttribIndex1);
1091  gl_->EnableVertexAttribArray(kAttribIndex2);
1092  gl_->VertexAttribPointer(
1093      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts);
1094  gl_->VertexAttribPointer(
1095      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts);
1096  gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor);
1097  gl_->DrawArraysInstancedANGLE(GL_POINTS, kFirst, kCount, 1);
1098  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1099}
1100
1101TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) {
1102  static const float verts[][4] = {
1103    { 12.0f, 23.0f, 34.0f, 45.0f, },
1104    { 56.0f, 67.0f, 78.0f, 89.0f, },
1105    { 13.0f, 24.0f, 35.0f, 46.0f, },
1106  };
1107  static const uint16 indices[] = {
1108    1, 2,
1109  };
1110  struct Cmds {
1111    cmds::EnableVertexAttribArray enable1;
1112    cmds::EnableVertexAttribArray enable2;
1113    cmds::BindBuffer bind_to_index_emu;
1114    cmds::BufferData set_index_size;
1115    cmds::BufferSubData copy_data0;
1116    cmd::SetToken set_token0;
1117    cmds::BindBuffer bind_to_emu;
1118    cmds::BufferData set_size;
1119    cmds::BufferSubData copy_data1;
1120    cmd::SetToken set_token1;
1121    cmds::VertexAttribPointer set_pointer1;
1122    cmds::BufferSubData copy_data2;
1123    cmd::SetToken set_token2;
1124    cmds::VertexAttribPointer set_pointer2;
1125    cmds::DrawElements draw;
1126    cmds::BindBuffer restore;
1127    cmds::BindBuffer restore_element;
1128  };
1129  const GLsizei kIndexSize = sizeof(indices);
1130  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1131  const GLuint kEmuIndexBufferId =
1132      GLES2Implementation::kClientSideElementArrayId;
1133  const GLuint kAttribIndex1 = 1;
1134  const GLuint kAttribIndex2 = 3;
1135  const GLint kNumComponents1 = 3;
1136  const GLint kNumComponents2 = 2;
1137  const GLsizei kClientStride = sizeof(verts[0]);
1138  const GLsizei kCount = 2;
1139  const GLsizei kSize1 =
1140      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1141  const GLsizei kSize2 =
1142      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1143  const GLsizei kEmuOffset1 = 0;
1144  const GLsizei kEmuOffset2 = kSize1;
1145  const GLsizei kTotalSize = kSize1 + kSize2;
1146
1147  ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1148  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1149  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1150
1151  Cmds expected;
1152  expected.enable1.Init(kAttribIndex1);
1153  expected.enable2.Init(kAttribIndex2);
1154  expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1155  expected.set_index_size.Init(
1156      GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1157  expected.copy_data0.Init(
1158      GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1159  expected.set_token0.Init(GetNextToken());
1160  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1161  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1162  expected.copy_data1.Init(
1163      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1164  expected.set_token1.Init(GetNextToken());
1165  expected.set_pointer1.Init(
1166      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1167  expected.copy_data2.Init(
1168      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1169  expected.set_token2.Init(GetNextToken());
1170  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1171                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1172  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0);
1173  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1174  expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1175  gl_->EnableVertexAttribArray(kAttribIndex1);
1176  gl_->EnableVertexAttribArray(kAttribIndex2);
1177  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1178                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1179  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1180                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1181  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices);
1182  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1183}
1184
1185TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersIndexUint) {
1186  static const float verts[][4] = {
1187    { 12.0f, 23.0f, 34.0f, 45.0f, },
1188    { 56.0f, 67.0f, 78.0f, 89.0f, },
1189    { 13.0f, 24.0f, 35.0f, 46.0f, },
1190  };
1191  static const uint32 indices[] = {
1192    1, 2,
1193  };
1194  struct Cmds {
1195    cmds::EnableVertexAttribArray enable1;
1196    cmds::EnableVertexAttribArray enable2;
1197    cmds::BindBuffer bind_to_index_emu;
1198    cmds::BufferData set_index_size;
1199    cmds::BufferSubData copy_data0;
1200    cmd::SetToken set_token0;
1201    cmds::BindBuffer bind_to_emu;
1202    cmds::BufferData set_size;
1203    cmds::BufferSubData copy_data1;
1204    cmd::SetToken set_token1;
1205    cmds::VertexAttribPointer set_pointer1;
1206    cmds::BufferSubData copy_data2;
1207    cmd::SetToken set_token2;
1208    cmds::VertexAttribPointer set_pointer2;
1209    cmds::DrawElements draw;
1210    cmds::BindBuffer restore;
1211    cmds::BindBuffer restore_element;
1212  };
1213  const GLsizei kIndexSize = sizeof(indices);
1214  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1215  const GLuint kEmuIndexBufferId =
1216      GLES2Implementation::kClientSideElementArrayId;
1217  const GLuint kAttribIndex1 = 1;
1218  const GLuint kAttribIndex2 = 3;
1219  const GLint kNumComponents1 = 3;
1220  const GLint kNumComponents2 = 2;
1221  const GLsizei kClientStride = sizeof(verts[0]);
1222  const GLsizei kCount = 2;
1223  const GLsizei kSize1 =
1224      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1225  const GLsizei kSize2 =
1226      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1227  const GLsizei kEmuOffset1 = 0;
1228  const GLsizei kEmuOffset2 = kSize1;
1229  const GLsizei kTotalSize = kSize1 + kSize2;
1230
1231  ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1232  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1233  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1234
1235  Cmds expected;
1236  expected.enable1.Init(kAttribIndex1);
1237  expected.enable2.Init(kAttribIndex2);
1238  expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1239  expected.set_index_size.Init(
1240      GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1241  expected.copy_data0.Init(
1242      GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1243  expected.set_token0.Init(GetNextToken());
1244  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1245  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1246  expected.copy_data1.Init(
1247      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1248  expected.set_token1.Init(GetNextToken());
1249  expected.set_pointer1.Init(
1250      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1251  expected.copy_data2.Init(
1252      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1253  expected.set_token2.Init(GetNextToken());
1254  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1255                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1256  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_INT, 0);
1257  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1258  expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1259  gl_->EnableVertexAttribArray(kAttribIndex1);
1260  gl_->EnableVertexAttribArray(kAttribIndex2);
1261  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1262                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1263  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1264                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1265  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices);
1266  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1267}
1268
1269TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersInvalidIndexUint) {
1270  static const float verts[][4] = {
1271    { 12.0f, 23.0f, 34.0f, 45.0f, },
1272    { 56.0f, 67.0f, 78.0f, 89.0f, },
1273    { 13.0f, 24.0f, 35.0f, 46.0f, },
1274  };
1275  static const uint32 indices[] = {
1276    1, 0x90000000
1277  };
1278
1279  const GLuint kAttribIndex1 = 1;
1280  const GLuint kAttribIndex2 = 3;
1281  const GLint kNumComponents1 = 3;
1282  const GLint kNumComponents2 = 2;
1283  const GLsizei kClientStride = sizeof(verts[0]);
1284  const GLsizei kCount = 2;
1285
1286  EXPECT_CALL(*command_buffer(), OnFlush())
1287      .Times(1)
1288      .RetiresOnSaturation();
1289
1290  gl_->EnableVertexAttribArray(kAttribIndex1);
1291  gl_->EnableVertexAttribArray(kAttribIndex2);
1292  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1293                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1294  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1295                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1296  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices);
1297
1298  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
1299}
1300
1301TEST_F(GLES2ImplementationTest,
1302       DrawElementsClientSideBuffersServiceSideIndices) {
1303  static const float verts[][4] = {
1304    { 12.0f, 23.0f, 34.0f, 45.0f, },
1305    { 56.0f, 67.0f, 78.0f, 89.0f, },
1306    { 13.0f, 24.0f, 35.0f, 46.0f, },
1307  };
1308  struct Cmds {
1309    cmds::EnableVertexAttribArray enable1;
1310    cmds::EnableVertexAttribArray enable2;
1311    cmds::BindBuffer bind_to_index;
1312    cmds::GetMaxValueInBufferCHROMIUM get_max;
1313    cmds::BindBuffer bind_to_emu;
1314    cmds::BufferData set_size;
1315    cmds::BufferSubData copy_data1;
1316    cmd::SetToken set_token1;
1317    cmds::VertexAttribPointer set_pointer1;
1318    cmds::BufferSubData copy_data2;
1319    cmd::SetToken set_token2;
1320    cmds::VertexAttribPointer set_pointer2;
1321    cmds::DrawElements draw;
1322    cmds::BindBuffer restore;
1323  };
1324  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1325  const GLuint kClientIndexBufferId = 0x789;
1326  const GLuint kIndexOffset = 0x40;
1327  const GLuint kMaxIndex = 2;
1328  const GLuint kAttribIndex1 = 1;
1329  const GLuint kAttribIndex2 = 3;
1330  const GLint kNumComponents1 = 3;
1331  const GLint kNumComponents2 = 2;
1332  const GLsizei kClientStride = sizeof(verts[0]);
1333  const GLsizei kCount = 2;
1334  const GLsizei kSize1 =
1335      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1336  const GLsizei kSize2 =
1337      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1338  const GLsizei kEmuOffset1 = 0;
1339  const GLsizei kEmuOffset2 = kSize1;
1340  const GLsizei kTotalSize = kSize1 + kSize2;
1341
1342  ExpectedMemoryInfo mem1 = GetExpectedResultMemory(sizeof(uint32));
1343  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1344  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1345
1346
1347  Cmds expected;
1348  expected.enable1.Init(kAttribIndex1);
1349  expected.enable2.Init(kAttribIndex2);
1350  expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId);
1351  expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT,
1352                        kIndexOffset, mem1.id, mem1.offset);
1353  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1354  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1355  expected.copy_data1.Init(
1356      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1357  expected.set_token1.Init(GetNextToken());
1358  expected.set_pointer1.Init(kAttribIndex1, kNumComponents1,
1359                             GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1360  expected.copy_data2.Init(
1361      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1362  expected.set_token2.Init(GetNextToken());
1363  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1364                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1365  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, kIndexOffset);
1366  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1367
1368  EXPECT_CALL(*command_buffer(), OnFlush())
1369      .WillOnce(SetMemory(mem1.ptr,kMaxIndex))
1370      .RetiresOnSaturation();
1371
1372  gl_->EnableVertexAttribArray(kAttribIndex1);
1373  gl_->EnableVertexAttribArray(kAttribIndex2);
1374  gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId);
1375  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1376                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1377  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1378                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1379  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT,
1380                    reinterpret_cast<const void*>(kIndexOffset));
1381  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1382}
1383
1384TEST_F(GLES2ImplementationTest, DrawElementsInstancedANGLEClientSideBuffers) {
1385  static const float verts[][4] = {
1386    { 12.0f, 23.0f, 34.0f, 45.0f, },
1387    { 56.0f, 67.0f, 78.0f, 89.0f, },
1388    { 13.0f, 24.0f, 35.0f, 46.0f, },
1389  };
1390  static const uint16 indices[] = {
1391    1, 2,
1392  };
1393  struct Cmds {
1394    cmds::EnableVertexAttribArray enable1;
1395    cmds::EnableVertexAttribArray enable2;
1396    cmds::VertexAttribDivisorANGLE divisor;
1397    cmds::BindBuffer bind_to_index_emu;
1398    cmds::BufferData set_index_size;
1399    cmds::BufferSubData copy_data0;
1400    cmd::SetToken set_token0;
1401    cmds::BindBuffer bind_to_emu;
1402    cmds::BufferData set_size;
1403    cmds::BufferSubData copy_data1;
1404    cmd::SetToken set_token1;
1405    cmds::VertexAttribPointer set_pointer1;
1406    cmds::BufferSubData copy_data2;
1407    cmd::SetToken set_token2;
1408    cmds::VertexAttribPointer set_pointer2;
1409    cmds::DrawElementsInstancedANGLE draw;
1410    cmds::BindBuffer restore;
1411    cmds::BindBuffer restore_element;
1412  };
1413  const GLsizei kIndexSize = sizeof(indices);
1414  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1415  const GLuint kEmuIndexBufferId =
1416      GLES2Implementation::kClientSideElementArrayId;
1417  const GLuint kAttribIndex1 = 1;
1418  const GLuint kAttribIndex2 = 3;
1419  const GLint kNumComponents1 = 3;
1420  const GLint kNumComponents2 = 2;
1421  const GLsizei kClientStride = sizeof(verts[0]);
1422  const GLsizei kCount = 2;
1423  const GLsizei kSize1 =
1424      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1425  const GLsizei kSize2 =
1426      1 * kNumComponents2 * sizeof(verts[0][0]);
1427  const GLuint kDivisor = 1;
1428  const GLsizei kEmuOffset1 = 0;
1429  const GLsizei kEmuOffset2 = kSize1;
1430  const GLsizei kTotalSize = kSize1 + kSize2;
1431
1432  ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1433  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1434  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1435
1436  Cmds expected;
1437  expected.enable1.Init(kAttribIndex1);
1438  expected.enable2.Init(kAttribIndex2);
1439  expected.divisor.Init(kAttribIndex2, kDivisor);
1440  expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1441  expected.set_index_size.Init(
1442      GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1443  expected.copy_data0.Init(
1444      GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1445  expected.set_token0.Init(GetNextToken());
1446  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1447  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1448  expected.copy_data1.Init(
1449      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1450  expected.set_token1.Init(GetNextToken());
1451  expected.set_pointer1.Init(
1452      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1453  expected.copy_data2.Init(
1454      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1455  expected.set_token2.Init(GetNextToken());
1456  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1457                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1458  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0, 1);
1459  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1460  expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1461  gl_->EnableVertexAttribArray(kAttribIndex1);
1462  gl_->EnableVertexAttribArray(kAttribIndex2);
1463  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1464                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1465  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1466                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1467  gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor);
1468  gl_->DrawElementsInstancedANGLE(
1469      GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices, 1);
1470  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1471}
1472
1473TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) {
1474  static const float verts[1] = { 0.0f, };
1475  const GLuint kAttribIndex1 = 1;
1476  const GLuint kAttribIndex2 = 3;
1477  const GLint kNumComponents1 = 3;
1478  const GLint kNumComponents2 = 2;
1479  const GLsizei kStride1 = 12;
1480  const GLsizei kStride2 = 0;
1481  const GLuint kBufferId = 0x123;
1482  const GLint kOffset2 = 0x456;
1483
1484  // It's all cached on the client side so no get commands are issued.
1485  struct Cmds {
1486    cmds::BindBuffer bind;
1487    cmds::VertexAttribPointer set_pointer;
1488  };
1489
1490  Cmds expected;
1491  expected.bind.Init(GL_ARRAY_BUFFER, kBufferId);
1492  expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE,
1493                            kStride2, kOffset2);
1494
1495  // Set one client side buffer.
1496  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1497                           GL_FLOAT, GL_FALSE, kStride1, verts);
1498  // Set one VBO
1499  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
1500  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1501                           GL_FLOAT, GL_FALSE, kStride2,
1502                           reinterpret_cast<const void*>(kOffset2));
1503  // now get them both.
1504  void* ptr1 = NULL;
1505  void* ptr2 = NULL;
1506
1507  gl_->GetVertexAttribPointerv(
1508      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr1);
1509  gl_->GetVertexAttribPointerv(
1510      kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr2);
1511
1512  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1513  EXPECT_TRUE(static_cast<const void*>(&verts) == ptr1);
1514  EXPECT_TRUE(ptr2 == reinterpret_cast<void*>(kOffset2));
1515}
1516
1517TEST_F(GLES2ImplementationTest, GetVertexAttrib) {
1518  static const float verts[1] = { 0.0f, };
1519  const GLuint kAttribIndex1 = 1;
1520  const GLuint kAttribIndex2 = 3;
1521  const GLint kNumComponents1 = 3;
1522  const GLint kNumComponents2 = 2;
1523  const GLsizei kStride1 = 12;
1524  const GLsizei kStride2 = 0;
1525  const GLuint kBufferId = 0x123;
1526  const GLint kOffset2 = 0x456;
1527
1528  // Only one set and one get because the client side buffer's info is stored
1529  // on the client side.
1530  struct Cmds {
1531    cmds::EnableVertexAttribArray enable;
1532    cmds::BindBuffer bind;
1533    cmds::VertexAttribPointer set_pointer;
1534    cmds::GetVertexAttribfv get2;  // for getting the value from attrib1
1535  };
1536
1537  ExpectedMemoryInfo mem2 = GetExpectedResultMemory(16);
1538
1539  Cmds expected;
1540  expected.enable.Init(kAttribIndex1);
1541  expected.bind.Init(GL_ARRAY_BUFFER, kBufferId);
1542  expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE,
1543                            kStride2, kOffset2);
1544  expected.get2.Init(kAttribIndex1,
1545                     GL_CURRENT_VERTEX_ATTRIB,
1546                     mem2.id, mem2.offset);
1547
1548  FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f);
1549
1550  // One call to flush to wait for last call to GetVertexAttribiv
1551  // as others are all cached.
1552  EXPECT_CALL(*command_buffer(), OnFlush())
1553      .WillOnce(SetMemory(
1554          mem2.ptr, SizedResultHelper<FourFloats>(current_attrib)))
1555      .RetiresOnSaturation();
1556
1557  gl_->EnableVertexAttribArray(kAttribIndex1);
1558  // Set one client side buffer.
1559  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1560                           GL_FLOAT, GL_FALSE, kStride1, verts);
1561  // Set one VBO
1562  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
1563  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1564                           GL_FLOAT, GL_FALSE, kStride2,
1565                           reinterpret_cast<const void*>(kOffset2));
1566  // first get the service side once to see that we make a command
1567  GLint buffer_id = 0;
1568  GLint enabled = 0;
1569  GLint size = 0;
1570  GLint stride = 0;
1571  GLint type = 0;
1572  GLint normalized = 1;
1573  float current[4] = { 0.0f, };
1574
1575  gl_->GetVertexAttribiv(
1576      kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id);
1577  EXPECT_EQ(kBufferId, static_cast<GLuint>(buffer_id));
1578  gl_->GetVertexAttribiv(
1579      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id);
1580  gl_->GetVertexAttribiv(
1581      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1582  gl_->GetVertexAttribiv(
1583      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size);
1584  gl_->GetVertexAttribiv(
1585      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride);
1586  gl_->GetVertexAttribiv(
1587      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type);
1588  gl_->GetVertexAttribiv(
1589      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized);
1590  gl_->GetVertexAttribfv(
1591      kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, &current[0]);
1592
1593  EXPECT_EQ(0, buffer_id);
1594  EXPECT_EQ(GL_TRUE, enabled);
1595  EXPECT_EQ(kNumComponents1, size);
1596  EXPECT_EQ(kStride1, stride);
1597  EXPECT_EQ(GL_FLOAT, type);
1598  EXPECT_EQ(GL_FALSE, normalized);
1599  EXPECT_EQ(0, memcmp(&current_attrib, &current, sizeof(current_attrib)));
1600
1601  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1602}
1603
1604TEST_F(GLES2ImplementationTest, ReservedIds) {
1605  // Only the get error command should be issued.
1606  struct Cmds {
1607    cmds::GetError get;
1608  };
1609  Cmds expected;
1610
1611  ExpectedMemoryInfo mem1 = GetExpectedResultMemory(
1612      sizeof(cmds::GetError::Result));
1613
1614  expected.get.Init(mem1.id, mem1.offset);
1615
1616  // One call to flush to wait for GetError
1617  EXPECT_CALL(*command_buffer(), OnFlush())
1618      .WillOnce(SetMemory(mem1.ptr, GLuint(GL_NO_ERROR)))
1619      .RetiresOnSaturation();
1620
1621  gl_->BindBuffer(
1622      GL_ARRAY_BUFFER,
1623      GLES2Implementation::kClientSideArrayId);
1624  gl_->BindBuffer(
1625      GL_ARRAY_BUFFER,
1626      GLES2Implementation::kClientSideElementArrayId);
1627  GLenum err = gl_->GetError();
1628  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), err);
1629  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1630}
1631
1632#endif  // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1633
1634TEST_F(GLES2ImplementationTest, ReadPixels2Reads) {
1635  struct Cmds {
1636    cmds::ReadPixels read1;
1637    cmd::SetToken set_token1;
1638    cmds::ReadPixels read2;
1639    cmd::SetToken set_token2;
1640  };
1641  const GLint kBytesPerPixel = 4;
1642  const GLint kWidth =
1643      (kTransferBufferSize - GLES2Implementation::kStartingOffset) /
1644      kBytesPerPixel;
1645  const GLint kHeight = 2;
1646  const GLenum kFormat = GL_RGBA;
1647  const GLenum kType = GL_UNSIGNED_BYTE;
1648
1649  ExpectedMemoryInfo mem1 =
1650      GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel);
1651  ExpectedMemoryInfo result1 =
1652      GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1653  ExpectedMemoryInfo mem2 =
1654      GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel);
1655  ExpectedMemoryInfo result2 =
1656      GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1657
1658  Cmds expected;
1659  expected.read1.Init(
1660      0, 0, kWidth, kHeight / 2, kFormat, kType,
1661      mem1.id, mem1.offset, result1.id, result1.offset,
1662      false);
1663  expected.set_token1.Init(GetNextToken());
1664  expected.read2.Init(
1665      0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
1666      mem2.id, mem2.offset, result2.id, result2.offset, false);
1667  expected.set_token2.Init(GetNextToken());
1668  scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]);
1669
1670  EXPECT_CALL(*command_buffer(), OnFlush())
1671      .WillOnce(SetMemory(result1.ptr, static_cast<uint32>(1)))
1672      .WillOnce(SetMemory(result2.ptr, static_cast<uint32>(1)))
1673      .RetiresOnSaturation();
1674
1675  gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get());
1676  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1677}
1678
1679TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) {
1680  struct Cmds {
1681    cmds::ReadPixels read;
1682    cmd::SetToken set_token;
1683  };
1684  const GLint kBytesPerPixel = 4;
1685  const GLint kWidth = 2;
1686  const GLint kHeight = 2;
1687  const GLenum kFormat = 0;
1688  const GLenum kType = 0;
1689
1690  ExpectedMemoryInfo mem1 =
1691      GetExpectedMemory(kWidth * kHeight * kBytesPerPixel);
1692  ExpectedMemoryInfo result1 =
1693      GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1694
1695  Cmds expected;
1696  expected.read.Init(
1697      0, 0, kWidth, kHeight, kFormat, kType,
1698      mem1.id, mem1.offset, result1.id, result1.offset, false);
1699  expected.set_token.Init(GetNextToken());
1700  scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]);
1701
1702  EXPECT_CALL(*command_buffer(), OnFlush())
1703      .Times(1)
1704      .RetiresOnSaturation();
1705
1706  gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get());
1707}
1708
1709TEST_F(GLES2ImplementationTest, FreeUnusedSharedMemory) {
1710  struct Cmds {
1711    cmds::BufferSubData buf;
1712    cmd::SetToken set_token;
1713  };
1714  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1715  const GLintptr kOffset = 15;
1716  const GLsizeiptr kSize = 16;
1717
1718  ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize);
1719
1720  Cmds expected;
1721  expected.buf.Init(
1722    kTarget, kOffset, kSize, mem1.id, mem1.offset);
1723  expected.set_token.Init(GetNextToken());
1724
1725  void* mem = gl_->MapBufferSubDataCHROMIUM(
1726      kTarget, kOffset, kSize, GL_WRITE_ONLY);
1727  ASSERT_TRUE(mem != NULL);
1728  gl_->UnmapBufferSubDataCHROMIUM(mem);
1729  EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
1730      .Times(1)
1731      .RetiresOnSaturation();
1732  gl_->FreeUnusedSharedMemory();
1733}
1734
1735TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUM) {
1736  struct Cmds {
1737    cmds::BufferSubData buf;
1738    cmd::SetToken set_token;
1739  };
1740  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1741  const GLintptr kOffset = 15;
1742  const GLsizeiptr kSize = 16;
1743
1744  uint32 offset = 0;
1745  Cmds expected;
1746  expected.buf.Init(
1747      kTarget, kOffset, kSize,
1748      command_buffer()->GetNextFreeTransferBufferId(), offset);
1749  expected.set_token.Init(GetNextToken());
1750
1751  void* mem = gl_->MapBufferSubDataCHROMIUM(
1752      kTarget, kOffset, kSize, GL_WRITE_ONLY);
1753  ASSERT_TRUE(mem != NULL);
1754  gl_->UnmapBufferSubDataCHROMIUM(mem);
1755  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1756}
1757
1758TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUMBadArgs) {
1759  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1760  const GLintptr kOffset = 15;
1761  const GLsizeiptr kSize = 16;
1762
1763  ExpectedMemoryInfo result1 =
1764      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1765  ExpectedMemoryInfo result2 =
1766      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1767  ExpectedMemoryInfo result3 =
1768      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1769  ExpectedMemoryInfo result4 =
1770      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1771
1772  // Calls to flush to wait for GetError
1773  EXPECT_CALL(*command_buffer(), OnFlush())
1774      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1775      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1776      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1777      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1778      .RetiresOnSaturation();
1779
1780  void* mem;
1781  mem = gl_->MapBufferSubDataCHROMIUM(kTarget, -1, kSize, GL_WRITE_ONLY);
1782  ASSERT_TRUE(mem == NULL);
1783  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1784  mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, -1, GL_WRITE_ONLY);
1785  ASSERT_TRUE(mem == NULL);
1786  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1787  mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, kSize, GL_READ_ONLY);
1788  ASSERT_TRUE(mem == NULL);
1789  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
1790  const char* kPtr = "something";
1791  gl_->UnmapBufferSubDataCHROMIUM(kPtr);
1792  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1793}
1794
1795TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUM) {
1796  struct Cmds {
1797    cmds::TexSubImage2D tex;
1798    cmd::SetToken set_token;
1799  };
1800  const GLint kLevel = 1;
1801  const GLint kXOffset = 2;
1802  const GLint kYOffset = 3;
1803  const GLint kWidth = 4;
1804  const GLint kHeight = 5;
1805  const GLenum kFormat = GL_RGBA;
1806  const GLenum kType = GL_UNSIGNED_BYTE;
1807
1808  uint32 offset = 0;
1809  Cmds expected;
1810  expected.tex.Init(
1811      GL_TEXTURE_2D, kLevel, kXOffset, kYOffset, kWidth, kHeight, kFormat,
1812      kType,
1813      command_buffer()->GetNextFreeTransferBufferId(), offset, GL_FALSE);
1814  expected.set_token.Init(GetNextToken());
1815
1816  void* mem = gl_->MapTexSubImage2DCHROMIUM(
1817      GL_TEXTURE_2D,
1818      kLevel,
1819      kXOffset,
1820      kYOffset,
1821      kWidth,
1822      kHeight,
1823      kFormat,
1824      kType,
1825      GL_WRITE_ONLY);
1826  ASSERT_TRUE(mem != NULL);
1827  gl_->UnmapTexSubImage2DCHROMIUM(mem);
1828  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1829}
1830
1831TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUMBadArgs) {
1832  const GLint kLevel = 1;
1833  const GLint kXOffset = 2;
1834  const GLint kYOffset = 3;
1835  const GLint kWidth = 4;
1836  const GLint kHeight = 5;
1837  const GLenum kFormat = GL_RGBA;
1838  const GLenum kType = GL_UNSIGNED_BYTE;
1839
1840  ExpectedMemoryInfo result1 =
1841      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1842  ExpectedMemoryInfo result2 =
1843      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1844  ExpectedMemoryInfo result3 =
1845      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1846  ExpectedMemoryInfo result4 =
1847      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1848  ExpectedMemoryInfo result5 =
1849      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1850  ExpectedMemoryInfo result6 =
1851      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1852  ExpectedMemoryInfo result7 =
1853      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1854
1855  // Calls to flush to wait for GetError
1856  EXPECT_CALL(*command_buffer(), OnFlush())
1857      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1858      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1859      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1860      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1861      .WillOnce(SetMemory(result5.ptr, GLuint(GL_NO_ERROR)))
1862      .WillOnce(SetMemory(result6.ptr, GLuint(GL_NO_ERROR)))
1863      .WillOnce(SetMemory(result7.ptr, GLuint(GL_NO_ERROR)))
1864      .RetiresOnSaturation();
1865
1866  void* mem;
1867  mem = gl_->MapTexSubImage2DCHROMIUM(
1868    GL_TEXTURE_2D,
1869    -1,
1870    kXOffset,
1871    kYOffset,
1872    kWidth,
1873    kHeight,
1874    kFormat,
1875    kType,
1876    GL_WRITE_ONLY);
1877  EXPECT_TRUE(mem == NULL);
1878  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1879  mem = gl_->MapTexSubImage2DCHROMIUM(
1880    GL_TEXTURE_2D,
1881    kLevel,
1882    -1,
1883    kYOffset,
1884    kWidth,
1885    kHeight,
1886    kFormat,
1887    kType,
1888    GL_WRITE_ONLY);
1889  EXPECT_TRUE(mem == NULL);
1890  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1891  mem = gl_->MapTexSubImage2DCHROMIUM(
1892    GL_TEXTURE_2D,
1893    kLevel,
1894    kXOffset,
1895    -1,
1896    kWidth,
1897    kHeight,
1898    kFormat,
1899    kType,
1900    GL_WRITE_ONLY);
1901  EXPECT_TRUE(mem == NULL);
1902  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1903  mem = gl_->MapTexSubImage2DCHROMIUM(
1904    GL_TEXTURE_2D,
1905    kLevel,
1906    kXOffset,
1907    kYOffset,
1908    -1,
1909    kHeight,
1910    kFormat,
1911    kType,
1912    GL_WRITE_ONLY);
1913  EXPECT_TRUE(mem == NULL);
1914  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1915  mem = gl_->MapTexSubImage2DCHROMIUM(
1916    GL_TEXTURE_2D,
1917    kLevel,
1918    kXOffset,
1919    kYOffset,
1920    kWidth,
1921    -1,
1922    kFormat,
1923    kType,
1924    GL_WRITE_ONLY);
1925  EXPECT_TRUE(mem == NULL);
1926  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1927  mem = gl_->MapTexSubImage2DCHROMIUM(
1928    GL_TEXTURE_2D,
1929    kLevel,
1930    kXOffset,
1931    kYOffset,
1932    kWidth,
1933    kHeight,
1934    kFormat,
1935    kType,
1936    GL_READ_ONLY);
1937  EXPECT_TRUE(mem == NULL);
1938  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
1939  const char* kPtr = "something";
1940  gl_->UnmapTexSubImage2DCHROMIUM(kPtr);
1941  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1942}
1943
1944TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMValidArgs) {
1945  const GLenum pnames[] = {
1946    GL_DEPTH_WRITEMASK,
1947    GL_COLOR_WRITEMASK,
1948    GL_STENCIL_WRITEMASK,
1949  };
1950  const GLint num_results = 6;
1951  GLint results[num_results + 1];
1952  struct Cmds {
1953    cmds::GetMultipleIntegervCHROMIUM get_multiple;
1954    cmd::SetToken set_token;
1955  };
1956  const GLsizei kNumPnames = arraysize(pnames);
1957  const GLsizeiptr kResultsSize = num_results * sizeof(results[0]);
1958  const size_t kPNamesSize = kNumPnames * sizeof(pnames[0]);
1959
1960  ExpectedMemoryInfo mem1 = GetExpectedMemory(kPNamesSize + kResultsSize);
1961  ExpectedMemoryInfo result1 = GetExpectedResultMemory(
1962      sizeof(cmds::GetError::Result));
1963
1964  const uint32 kPnamesOffset = mem1.offset;
1965  const uint32 kResultsOffset = mem1.offset + kPNamesSize;
1966  Cmds expected;
1967  expected.get_multiple.Init(
1968      mem1.id, kPnamesOffset, kNumPnames,
1969      mem1.id, kResultsOffset, kResultsSize);
1970  expected.set_token.Init(GetNextToken());
1971
1972  const GLint kSentinel = 0x12345678;
1973  memset(results, 0, sizeof(results));
1974  results[num_results] = kSentinel;
1975  const GLint returned_results[] = {
1976    1, 0, 1, 0, 1, -1,
1977  };
1978  // One call to flush to wait for results
1979  EXPECT_CALL(*command_buffer(), OnFlush())
1980      .WillOnce(SetMemoryFromArray(mem1.ptr + kPNamesSize,
1981                                   returned_results, sizeof(returned_results)))
1982      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1983      .RetiresOnSaturation();
1984
1985  gl_->GetMultipleIntegervCHROMIUM(
1986      &pnames[0], kNumPnames, &results[0], kResultsSize);
1987  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1988  EXPECT_EQ(0, memcmp(&returned_results, results, sizeof(returned_results)));
1989  EXPECT_EQ(kSentinel, results[num_results]);
1990  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
1991}
1992
1993TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMBadArgs) {
1994  GLenum pnames[] = {
1995    GL_DEPTH_WRITEMASK,
1996    GL_COLOR_WRITEMASK,
1997    GL_STENCIL_WRITEMASK,
1998  };
1999  const GLint num_results = 6;
2000  GLint results[num_results + 1];
2001  const GLsizei kNumPnames = arraysize(pnames);
2002  const GLsizeiptr kResultsSize = num_results * sizeof(results[0]);
2003
2004  ExpectedMemoryInfo result1 =
2005      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2006  ExpectedMemoryInfo result2 =
2007      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2008  ExpectedMemoryInfo result3 =
2009      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2010  ExpectedMemoryInfo result4 =
2011      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2012
2013  // Calls to flush to wait for GetError
2014  EXPECT_CALL(*command_buffer(), OnFlush())
2015      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2016      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
2017      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
2018      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
2019      .RetiresOnSaturation();
2020
2021  const GLint kSentinel = 0x12345678;
2022  memset(results, 0, sizeof(results));
2023  results[num_results] = kSentinel;
2024  // try bad size.
2025  gl_->GetMultipleIntegervCHROMIUM(
2026      &pnames[0], kNumPnames, &results[0], kResultsSize + 1);
2027  EXPECT_TRUE(NoCommandsWritten());
2028  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2029  EXPECT_EQ(0, results[0]);
2030  EXPECT_EQ(kSentinel, results[num_results]);
2031  // try bad size.
2032  ClearCommands();
2033  gl_->GetMultipleIntegervCHROMIUM(
2034      &pnames[0], kNumPnames, &results[0], kResultsSize - 1);
2035  EXPECT_TRUE(NoCommandsWritten());
2036  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2037  EXPECT_EQ(0, results[0]);
2038  EXPECT_EQ(kSentinel, results[num_results]);
2039  // try uncleared results.
2040  ClearCommands();
2041  results[2] = 1;
2042  gl_->GetMultipleIntegervCHROMIUM(
2043      &pnames[0], kNumPnames, &results[0], kResultsSize);
2044  EXPECT_TRUE(NoCommandsWritten());
2045  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2046  EXPECT_EQ(0, results[0]);
2047  EXPECT_EQ(kSentinel, results[num_results]);
2048  // try bad enum results.
2049  ClearCommands();
2050  results[2] = 0;
2051  pnames[1] = GL_TRUE;
2052  gl_->GetMultipleIntegervCHROMIUM(
2053      &pnames[0], kNumPnames, &results[0], kResultsSize);
2054  EXPECT_TRUE(NoCommandsWritten());
2055  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
2056  EXPECT_EQ(0, results[0]);
2057  EXPECT_EQ(kSentinel, results[num_results]);
2058}
2059
2060TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMGoodArgs) {
2061  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2062  const GLuint kProgramId = 123;
2063  const char kBad = 0x12;
2064  GLsizei size = 0;
2065  const Str7 kString = {"foobar"};
2066  char buf[20];
2067
2068  ExpectedMemoryInfo mem1 =
2069      GetExpectedMemory(MaxTransferBufferSize());
2070  ExpectedMemoryInfo result1 =
2071      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2072  ExpectedMemoryInfo result2 =
2073      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2074
2075  memset(buf, kBad, sizeof(buf));
2076  EXPECT_CALL(*command_buffer(), OnFlush())
2077      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2078                      SetMemory(mem1.ptr, kString)))
2079      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
2080      .RetiresOnSaturation();
2081
2082  struct Cmds {
2083    cmd::SetBucketSize set_bucket_size1;
2084    cmds::GetProgramInfoCHROMIUM get_program_info;
2085    cmd::GetBucketStart get_bucket_start;
2086    cmd::SetToken set_token1;
2087    cmd::SetBucketSize set_bucket_size2;
2088  };
2089  Cmds expected;
2090  expected.set_bucket_size1.Init(kBucketId, 0);
2091  expected.get_program_info.Init(kProgramId, kBucketId);
2092  expected.get_bucket_start.Init(
2093      kBucketId, result1.id, result1.offset,
2094      MaxTransferBufferSize(), mem1.id, mem1.offset);
2095  expected.set_token1.Init(GetNextToken());
2096  expected.set_bucket_size2.Init(kBucketId, 0);
2097  gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), &size, &buf);
2098  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2099  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2100  EXPECT_EQ(sizeof(kString), static_cast<size_t>(size));
2101  EXPECT_STREQ(kString.str, buf);
2102  EXPECT_EQ(buf[sizeof(kString)], kBad);
2103}
2104
2105TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) {
2106  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2107  const GLuint kProgramId = 123;
2108  GLsizei size = 0;
2109  const Str7 kString = {"foobar"};
2110  char buf[20];
2111
2112  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
2113  ExpectedMemoryInfo result1 =
2114      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2115  ExpectedMemoryInfo result2 =
2116      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2117  ExpectedMemoryInfo result3 =
2118      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2119  ExpectedMemoryInfo result4 =
2120      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2121
2122  EXPECT_CALL(*command_buffer(), OnFlush())
2123      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2124                      SetMemory(mem1.ptr,  kString)))
2125      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
2126      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
2127      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
2128      .RetiresOnSaturation();
2129
2130  // try bufsize not big enough.
2131  struct Cmds {
2132    cmd::SetBucketSize set_bucket_size1;
2133    cmds::GetProgramInfoCHROMIUM get_program_info;
2134    cmd::GetBucketStart get_bucket_start;
2135    cmd::SetToken set_token1;
2136    cmd::SetBucketSize set_bucket_size2;
2137  };
2138  Cmds expected;
2139  expected.set_bucket_size1.Init(kBucketId, 0);
2140  expected.get_program_info.Init(kProgramId, kBucketId);
2141  expected.get_bucket_start.Init(
2142      kBucketId, result1.id, result1.offset,
2143      MaxTransferBufferSize(), mem1.id, mem1.offset);
2144  expected.set_token1.Init(GetNextToken());
2145  expected.set_bucket_size2.Init(kBucketId, 0);
2146  gl_->GetProgramInfoCHROMIUM(kProgramId, 6, &size, &buf);
2147  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2148  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
2149  ClearCommands();
2150
2151  // try bad bufsize
2152  gl_->GetProgramInfoCHROMIUM(kProgramId, -1, &size, &buf);
2153  EXPECT_TRUE(NoCommandsWritten());
2154  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2155  ClearCommands();
2156  // try no size ptr.
2157  gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), NULL, &buf);
2158  EXPECT_TRUE(NoCommandsWritten());
2159  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2160}
2161
2162// Test that things are cached
2163TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) {
2164  struct PNameValue {
2165    GLenum pname;
2166    GLint expected;
2167  };
2168  const PNameValue pairs[] = {
2169      {GL_ACTIVE_TEXTURE, GL_TEXTURE0, },
2170      {GL_TEXTURE_BINDING_2D, 0, },
2171      {GL_TEXTURE_BINDING_CUBE_MAP, 0, },
2172      {GL_TEXTURE_BINDING_EXTERNAL_OES, 0, },
2173      {GL_FRAMEBUFFER_BINDING, 0, },
2174      {GL_RENDERBUFFER_BINDING, 0, },
2175      {GL_ARRAY_BUFFER_BINDING, 0, },
2176      {GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, },
2177      {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kMaxCombinedTextureImageUnits, },
2178      {GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMaxCubeMapTextureSize, },
2179      {GL_MAX_FRAGMENT_UNIFORM_VECTORS, kMaxFragmentUniformVectors, },
2180      {GL_MAX_RENDERBUFFER_SIZE, kMaxRenderbufferSize, },
2181      {GL_MAX_TEXTURE_IMAGE_UNITS, kMaxTextureImageUnits, },
2182      {GL_MAX_TEXTURE_SIZE, kMaxTextureSize, },
2183      {GL_MAX_VARYING_VECTORS, kMaxVaryingVectors, },
2184      {GL_MAX_VERTEX_ATTRIBS, kMaxVertexAttribs, },
2185      {GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMaxVertexTextureImageUnits, },
2186      {GL_MAX_VERTEX_UNIFORM_VECTORS, kMaxVertexUniformVectors, },
2187      {GL_NUM_COMPRESSED_TEXTURE_FORMATS, kNumCompressedTextureFormats, },
2188      {GL_NUM_SHADER_BINARY_FORMATS, kNumShaderBinaryFormats, }, };
2189  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2190  for (size_t ii = 0; ii < num_pairs; ++ii) {
2191    const PNameValue& pv = pairs[ii];
2192    GLint v = -1;
2193    gl_->GetIntegerv(pv.pname, &v);
2194    EXPECT_TRUE(NoCommandsWritten());
2195    EXPECT_EQ(pv.expected, v);
2196  }
2197
2198  ExpectedMemoryInfo result1 =
2199      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2200
2201  EXPECT_CALL(*command_buffer(), OnFlush())
2202      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2203      .RetiresOnSaturation();
2204  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2205}
2206
2207TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) {
2208  struct PNameValue {
2209    GLenum pname;
2210    GLint expected;
2211  };
2212  gl_->ActiveTexture(GL_TEXTURE4);
2213  gl_->BindBuffer(GL_ARRAY_BUFFER, 2);
2214  gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 3);
2215  gl_->BindFramebuffer(GL_FRAMEBUFFER, 4);
2216  gl_->BindRenderbuffer(GL_RENDERBUFFER, 5);
2217  gl_->BindTexture(GL_TEXTURE_2D, 6);
2218  gl_->BindTexture(GL_TEXTURE_CUBE_MAP, 7);
2219  gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, 8);
2220
2221  const PNameValue pairs[] = {{GL_ACTIVE_TEXTURE, GL_TEXTURE4, },
2222                              {GL_ARRAY_BUFFER_BINDING, 2, },
2223                              {GL_ELEMENT_ARRAY_BUFFER_BINDING, 3, },
2224                              {GL_FRAMEBUFFER_BINDING, 4, },
2225                              {GL_RENDERBUFFER_BINDING, 5, },
2226                              {GL_TEXTURE_BINDING_2D, 6, },
2227                              {GL_TEXTURE_BINDING_CUBE_MAP, 7, },
2228                              {GL_TEXTURE_BINDING_EXTERNAL_OES, 8, }, };
2229  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2230  for (size_t ii = 0; ii < num_pairs; ++ii) {
2231    const PNameValue& pv = pairs[ii];
2232    GLint v = -1;
2233    gl_->GetIntegerv(pv.pname, &v);
2234    EXPECT_EQ(pv.expected, v);
2235  }
2236
2237  ExpectedMemoryInfo result1 =
2238      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2239
2240  EXPECT_CALL(*command_buffer(), OnFlush())
2241      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2242      .RetiresOnSaturation();
2243  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2244}
2245
2246static bool CheckRect(
2247    int width, int height, GLenum format, GLenum type, int alignment,
2248    bool flip_y, const uint8* r1, const uint8* r2) {
2249  uint32 size = 0;
2250  uint32 unpadded_row_size = 0;
2251  uint32 padded_row_size = 0;
2252  if (!GLES2Util::ComputeImageDataSizes(
2253      width, height, format, type, alignment, &size, &unpadded_row_size,
2254      &padded_row_size)) {
2255    return false;
2256  }
2257
2258  int r2_stride = flip_y ?
2259      -static_cast<int>(padded_row_size) :
2260      static_cast<int>(padded_row_size);
2261  r2 = flip_y ? (r2 + (height - 1) * padded_row_size) : r2;
2262
2263  for (int y = 0; y < height; ++y) {
2264    if (memcmp(r1, r2, unpadded_row_size) != 0) {
2265      return false;
2266    }
2267    r1 += padded_row_size;
2268    r2 += r2_stride;
2269  }
2270  return true;
2271}
2272
2273ACTION_P8(CheckRectAction, width, height, format, type, alignment, flip_y,
2274          r1, r2) {
2275  EXPECT_TRUE(CheckRect(
2276      width, height, format, type, alignment, flip_y, r1, r2));
2277}
2278
2279// Test TexImage2D with and without flip_y
2280TEST_F(GLES2ImplementationTest, TexImage2D) {
2281  struct Cmds {
2282    cmds::TexImage2D tex_image_2d;
2283    cmd::SetToken set_token;
2284  };
2285  struct Cmds2 {
2286    cmds::TexImage2D tex_image_2d;
2287    cmd::SetToken set_token;
2288  };
2289  const GLenum kTarget = GL_TEXTURE_2D;
2290  const GLint kLevel = 0;
2291  const GLenum kFormat = GL_RGB;
2292  const GLsizei kWidth = 3;
2293  const GLsizei kHeight = 4;
2294  const GLint kBorder = 0;
2295  const GLenum kType = GL_UNSIGNED_BYTE;
2296  const GLint kPixelStoreUnpackAlignment = 4;
2297  static uint8 pixels[] = {
2298    11, 12, 13, 13, 14, 15, 15, 16, 17, 101, 102, 103,
2299    21, 22, 23, 23, 24, 25, 25, 26, 27, 201, 202, 203,
2300    31, 32, 33, 33, 34, 35, 35, 36, 37, 123, 124, 125,
2301    41, 42, 43, 43, 44, 45, 45, 46, 47,
2302  };
2303
2304  ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels));
2305
2306  Cmds expected;
2307  expected.tex_image_2d.Init(
2308      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2309      mem1.id, mem1.offset);
2310  expected.set_token.Init(GetNextToken());
2311  gl_->TexImage2D(
2312      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2313      pixels);
2314  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2315  EXPECT_TRUE(CheckRect(
2316      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false,
2317      pixels, mem1.ptr));
2318
2319  ClearCommands();
2320  gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2321
2322  ExpectedMemoryInfo mem2 = GetExpectedMemory(sizeof(pixels));
2323  Cmds2 expected2;
2324  expected2.tex_image_2d.Init(
2325      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2326      mem2.id, mem2.offset);
2327  expected2.set_token.Init(GetNextToken());
2328  const void* commands2 = GetPut();
2329  gl_->TexImage2D(
2330      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2331      pixels);
2332  EXPECT_EQ(0, memcmp(&expected2, commands2, sizeof(expected2)));
2333  EXPECT_TRUE(CheckRect(
2334      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, true,
2335      pixels, mem2.ptr));
2336}
2337
2338// Test TexImage2D with 2 writes
2339TEST_F(GLES2ImplementationTest, TexImage2D2Writes) {
2340  struct Cmds {
2341    cmds::TexImage2D tex_image_2d;
2342    cmds::TexSubImage2D tex_sub_image_2d1;
2343    cmd::SetToken set_token1;
2344    cmds::TexSubImage2D tex_sub_image_2d2;
2345    cmd::SetToken set_token2;
2346  };
2347  const GLenum kTarget = GL_TEXTURE_2D;
2348  const GLint kLevel = 0;
2349  const GLenum kFormat = GL_RGB;
2350  const GLint kBorder = 0;
2351  const GLenum kType = GL_UNSIGNED_BYTE;
2352  const GLint kPixelStoreUnpackAlignment = 4;
2353  const GLsizei kWidth = 3;
2354
2355  uint32 size = 0;
2356  uint32 unpadded_row_size = 0;
2357  uint32 padded_row_size = 0;
2358  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2359      kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment,
2360      &size, &unpadded_row_size, &padded_row_size));
2361  const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2;
2362  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2363      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment,
2364      &size, NULL, NULL));
2365  uint32 half_size = 0;
2366  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2367      kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2368      &half_size, NULL, NULL));
2369
2370  scoped_ptr<uint8[]> pixels(new uint8[size]);
2371  for (uint32 ii = 0; ii < size; ++ii) {
2372    pixels[ii] = static_cast<uint8>(ii);
2373  }
2374
2375  ExpectedMemoryInfo mem1 = GetExpectedMemory(half_size);
2376  ExpectedMemoryInfo mem2 = GetExpectedMemory(half_size);
2377
2378  Cmds expected;
2379  expected.tex_image_2d.Init(
2380      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2381      0, 0);
2382  expected.tex_sub_image_2d1.Init(
2383      kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType,
2384      mem1.id, mem1.offset, true);
2385  expected.set_token1.Init(GetNextToken());
2386  expected.tex_sub_image_2d2.Init(
2387      kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
2388      mem2.id, mem2.offset, true);
2389  expected.set_token2.Init(GetNextToken());
2390
2391  // TODO(gman): Make it possible to run this test
2392  // EXPECT_CALL(*command_buffer(), OnFlush())
2393  //     .WillOnce(CheckRectAction(
2394  //         kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2395  //         false, pixels.get(),
2396  //         GetExpectedTransferAddressFromOffsetAs<uint8>(offset1, half_size)))
2397  //     .RetiresOnSaturation();
2398
2399  gl_->TexImage2D(
2400      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2401      pixels.get());
2402  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2403  EXPECT_TRUE(CheckRect(
2404      kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, false,
2405      pixels.get() + kHeight / 2 * padded_row_size, mem2.ptr));
2406
2407  ClearCommands();
2408  gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2409  const void* commands2 = GetPut();
2410  ExpectedMemoryInfo mem3 = GetExpectedMemory(half_size);
2411  ExpectedMemoryInfo mem4 = GetExpectedMemory(half_size);
2412  expected.tex_image_2d.Init(
2413      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2414      0, 0);
2415  expected.tex_sub_image_2d1.Init(
2416      kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
2417      mem3.id, mem3.offset, true);
2418  expected.set_token1.Init(GetNextToken());
2419  expected.tex_sub_image_2d2.Init(
2420      kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType,
2421      mem4.id, mem4.offset, true);
2422  expected.set_token2.Init(GetNextToken());
2423
2424  // TODO(gman): Make it possible to run this test
2425  // EXPECT_CALL(*command_buffer(), OnFlush())
2426  //     .WillOnce(CheckRectAction(
2427  //         kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2428  //         true, pixels.get(),
2429  //         GetExpectedTransferAddressFromOffsetAs<uint8>(offset3, half_size)))
2430  //     .RetiresOnSaturation();
2431
2432  gl_->TexImage2D(
2433      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2434      pixels.get());
2435  EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected)));
2436  EXPECT_TRUE(CheckRect(
2437      kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, true,
2438      pixels.get() + kHeight / 2 * padded_row_size, mem4.ptr));
2439}
2440
2441// Test TexSubImage2D with GL_PACK_FLIP_Y set and partial multirow transfers
2442TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) {
2443  const GLsizei kTextureWidth = MaxTransferBufferSize() / 4;
2444  const GLsizei kTextureHeight = 7;
2445  const GLsizei kSubImageWidth = MaxTransferBufferSize() / 8;
2446  const GLsizei kSubImageHeight = 4;
2447  const GLint kSubImageXOffset = 1;
2448  const GLint kSubImageYOffset = 2;
2449  const GLenum kFormat = GL_RGBA;
2450  const GLenum kType = GL_UNSIGNED_BYTE;
2451  const GLenum kTarget = GL_TEXTURE_2D;
2452  const GLint kLevel = 0;
2453  const GLint kBorder = 0;
2454  const GLint kPixelStoreUnpackAlignment = 4;
2455
2456  struct Cmds {
2457    cmds::PixelStorei pixel_store_i1;
2458    cmds::TexImage2D tex_image_2d;
2459    cmds::PixelStorei pixel_store_i2;
2460    cmds::TexSubImage2D tex_sub_image_2d1;
2461    cmd::SetToken set_token1;
2462    cmds::TexSubImage2D tex_sub_image_2d2;
2463    cmd::SetToken set_token2;
2464  };
2465
2466  uint32 sub_2_high_size = 0;
2467  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2468      kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment,
2469      &sub_2_high_size, NULL, NULL));
2470
2471  ExpectedMemoryInfo mem1 = GetExpectedMemory(sub_2_high_size);
2472  ExpectedMemoryInfo mem2 = GetExpectedMemory(sub_2_high_size);
2473
2474  Cmds expected;
2475  expected.pixel_store_i1.Init(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment);
2476  expected.tex_image_2d.Init(
2477      kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat,
2478      kType, 0, 0);
2479  expected.pixel_store_i2.Init(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2480  expected.tex_sub_image_2d1.Init(kTarget, kLevel, kSubImageXOffset,
2481      kSubImageYOffset + 2, kSubImageWidth, 2, kFormat, kType,
2482      mem1.id, mem1.offset, false);
2483  expected.set_token1.Init(GetNextToken());
2484  expected.tex_sub_image_2d2.Init(kTarget, kLevel, kSubImageXOffset,
2485      kSubImageYOffset, kSubImageWidth , 2, kFormat, kType,
2486      mem2.id, mem2.offset, false);
2487  expected.set_token2.Init(GetNextToken());
2488
2489  gl_->PixelStorei(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment);
2490  gl_->TexImage2D(
2491      kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat,
2492      kType, NULL);
2493  gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2494  scoped_ptr<uint32[]> pixels(new uint32[kSubImageWidth * kSubImageHeight]);
2495  for (int y = 0; y < kSubImageHeight; ++y) {
2496    for (int x = 0; x < kSubImageWidth; ++x) {
2497      pixels.get()[kSubImageWidth * y + x] = x | (y << 16);
2498    }
2499  }
2500  gl_->TexSubImage2D(
2501      GL_TEXTURE_2D, 0, kSubImageXOffset, kSubImageYOffset, kSubImageWidth,
2502      kSubImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
2503
2504  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2505  EXPECT_TRUE(CheckRect(
2506      kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, true,
2507      reinterpret_cast<uint8*>(pixels.get() + 2 * kSubImageWidth),
2508      mem2.ptr));
2509}
2510
2511TEST_F(GLES2ImplementationTest, SubImageUnpack) {
2512  static const GLint unpack_alignments[] = { 1, 2, 4, 8 };
2513
2514  static const GLenum kFormat = GL_RGB;
2515  static const GLenum kType = GL_UNSIGNED_BYTE;
2516  static const GLint kLevel = 0;
2517  static const GLint kBorder = 0;
2518  // We're testing using the unpack params to pull a subimage out of a larger
2519  // source of pixels. Here we specify the subimage by its border rows /
2520  // columns.
2521  static const GLint kSrcWidth = 33;
2522  static const GLint kSrcSubImageX0 = 11;
2523  static const GLint kSrcSubImageX1 = 20;
2524  static const GLint kSrcSubImageY0 = 18;
2525  static const GLint kSrcSubImageY1 = 23;
2526  static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0;
2527  static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0;
2528
2529  // these are only used in the texsubimage tests
2530  static const GLint kTexWidth = 1023;
2531  static const GLint kTexHeight = 511;
2532  static const GLint kTexSubXOffset = 419;
2533  static const GLint kTexSubYOffset = 103;
2534
2535  struct {
2536    cmds::PixelStorei pixel_store_i;
2537    cmds::PixelStorei pixel_store_i2;
2538    cmds::TexImage2D tex_image_2d;
2539  } texImageExpected;
2540
2541  struct  {
2542    cmds::PixelStorei pixel_store_i;
2543    cmds::PixelStorei pixel_store_i2;
2544    cmds::TexImage2D tex_image_2d;
2545    cmds::TexSubImage2D tex_sub_image_2d;
2546  } texSubImageExpected;
2547
2548  uint32 src_size;
2549  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2550      kSrcWidth, kSrcSubImageY1, kFormat, kType, 8, &src_size, NULL, NULL));
2551  scoped_ptr<uint8[]> src_pixels;
2552  src_pixels.reset(new uint8[src_size]);
2553  for (size_t i = 0; i < src_size; ++i) {
2554    src_pixels[i] = static_cast<int8>(i);
2555  }
2556
2557  for (int sub = 0; sub < 2; ++sub) {
2558    for (int flip_y = 0; flip_y < 2; ++flip_y) {
2559      for (size_t a = 0; a < arraysize(unpack_alignments); ++a) {
2560        GLint alignment = unpack_alignments[a];
2561        uint32 size;
2562        uint32 unpadded_row_size;
2563        uint32 padded_row_size;
2564        ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2565            kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, alignment,
2566            &size, &unpadded_row_size, &padded_row_size));
2567        ASSERT_TRUE(size <= MaxTransferBufferSize());
2568        ExpectedMemoryInfo mem = GetExpectedMemory(size);
2569
2570        const void* commands = GetPut();
2571        gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment);
2572        gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, kSrcWidth);
2573        gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, kSrcSubImageX0);
2574        gl_->PixelStorei(GL_UNPACK_SKIP_ROWS_EXT, kSrcSubImageY0);
2575        gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
2576        if (sub) {
2577          gl_->TexImage2D(
2578              GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder,
2579              kFormat, kType, NULL);
2580          gl_->TexSubImage2D(
2581              GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset,
2582              kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType,
2583              src_pixels.get());
2584          texSubImageExpected.pixel_store_i.Init(
2585              GL_UNPACK_ALIGNMENT, alignment);
2586          texSubImageExpected.pixel_store_i2.Init(
2587              GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
2588          texSubImageExpected.tex_image_2d.Init(
2589              GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder,
2590              kFormat, kType, 0, 0);
2591          texSubImageExpected.tex_sub_image_2d.Init(
2592              GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset,
2593              kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id,
2594              mem.offset, GL_FALSE);
2595          EXPECT_EQ(0, memcmp(
2596              &texSubImageExpected, commands, sizeof(texSubImageExpected)));
2597        } else {
2598          gl_->TexImage2D(
2599              GL_TEXTURE_2D, kLevel, kFormat,
2600              kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType,
2601              src_pixels.get());
2602          texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment);
2603          texImageExpected.pixel_store_i2.Init(
2604              GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
2605          texImageExpected.tex_image_2d.Init(
2606              GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth,
2607              kSrcSubImageHeight, kBorder, kFormat, kType, mem.id, mem.offset);
2608          EXPECT_EQ(0, memcmp(
2609              &texImageExpected, commands, sizeof(texImageExpected)));
2610        }
2611        uint32 src_padded_row_size;
2612        ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize(
2613            kSrcWidth, kFormat, kType, alignment, &src_padded_row_size));
2614        uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize(
2615            kFormat, kType);
2616        for (int y = 0; y < kSrcSubImageHeight; ++y) {
2617          GLint src_sub_y = flip_y ? kSrcSubImageHeight - y - 1 : y;
2618          const uint8* src_row = src_pixels.get() +
2619              (kSrcSubImageY0 + src_sub_y) * src_padded_row_size +
2620              bytes_per_group * kSrcSubImageX0;
2621          const uint8* dst_row = mem.ptr + y * padded_row_size;
2622          EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size));
2623        }
2624        ClearCommands();
2625      }
2626    }
2627  }
2628}
2629
2630// Binds can not be cached with bind_generates_resource = false because
2631// our id might not be valid. More specifically if you bind on contextA then
2632// delete on contextB the resource is still bound on contextA but GetInterger
2633// won't return an id.
2634TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) {
2635  struct PNameValue {
2636    GLenum pname;
2637    GLint expected;
2638  };
2639  const PNameValue pairs[] = {{GL_TEXTURE_BINDING_2D, 1, },
2640                              {GL_TEXTURE_BINDING_CUBE_MAP, 2, },
2641                              {GL_TEXTURE_BINDING_EXTERNAL_OES, 3, },
2642                              {GL_FRAMEBUFFER_BINDING, 4, },
2643                              {GL_RENDERBUFFER_BINDING, 5, },
2644                              {GL_ARRAY_BUFFER_BINDING, 6, },
2645                              {GL_ELEMENT_ARRAY_BUFFER_BINDING, 7, }, };
2646  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2647  for (size_t ii = 0; ii < num_pairs; ++ii) {
2648    const PNameValue& pv = pairs[ii];
2649    GLint v = -1;
2650    ExpectedMemoryInfo result1 =
2651        GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result));
2652    EXPECT_CALL(*command_buffer(), OnFlush())
2653        .WillOnce(SetMemory(result1.ptr,
2654                            SizedResultHelper<GLuint>(pv.expected)))
2655        .RetiresOnSaturation();
2656    gl_->GetIntegerv(pv.pname, &v);
2657    EXPECT_EQ(pv.expected, v);
2658  }
2659}
2660
2661// glGen* Ids must not be reused until glDelete* commands have been
2662// flushed by glFlush.
2663TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestBuffers) {
2664  FlushGenerationTest<GenBuffersAPI>();
2665}
2666TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestFramebuffers) {
2667  FlushGenerationTest<GenFramebuffersAPI>();
2668}
2669TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestRenderbuffers) {
2670  FlushGenerationTest<GenRenderbuffersAPI>();
2671}
2672TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestTextures) {
2673  FlushGenerationTest<GenTexturesAPI>();
2674}
2675
2676// glGen* Ids must not be reused cross-context until glDelete* commands are
2677// flushed by glFlush, and the Ids are lazily freed after.
2678TEST_F(GLES2ImplementationStrictSharedTest, CrossContextGenerationTestBuffers) {
2679  CrossContextGenerationTest<GenBuffersAPI>();
2680}
2681TEST_F(GLES2ImplementationStrictSharedTest,
2682       CrossContextGenerationTestFramebuffers) {
2683  CrossContextGenerationTest<GenFramebuffersAPI>();
2684}
2685TEST_F(GLES2ImplementationStrictSharedTest,
2686       CrossContextGenerationTestRenderbuffers) {
2687  CrossContextGenerationTest<GenRenderbuffersAPI>();
2688}
2689TEST_F(GLES2ImplementationStrictSharedTest,
2690       CrossContextGenerationTestTextures) {
2691  CrossContextGenerationTest<GenTexturesAPI>();
2692}
2693
2694// Test Delete which causes auto flush.  Tests a regression case that occurred
2695// in testing.
2696TEST_F(GLES2ImplementationStrictSharedTest,
2697       CrossContextGenerationAutoFlushTestBuffers) {
2698  CrossContextGenerationAutoFlushTest<GenBuffersAPI>();
2699}
2700TEST_F(GLES2ImplementationStrictSharedTest,
2701       CrossContextGenerationAutoFlushTestFramebuffers) {
2702  CrossContextGenerationAutoFlushTest<GenFramebuffersAPI>();
2703}
2704TEST_F(GLES2ImplementationStrictSharedTest,
2705       CrossContextGenerationAutoFlushTestRenderbuffers) {
2706  CrossContextGenerationAutoFlushTest<GenRenderbuffersAPI>();
2707}
2708TEST_F(GLES2ImplementationStrictSharedTest,
2709       CrossContextGenerationAutoFlushTestTextures) {
2710  CrossContextGenerationAutoFlushTest<GenTexturesAPI>();
2711}
2712
2713TEST_F(GLES2ImplementationTest, GetString) {
2714  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2715  const Str7 kString = {"foobar"};
2716  // GL_CHROMIUM_map_sub GL_CHROMIUM_flipy are hard coded into
2717  // GLES2Implementation.
2718  const char* expected_str =
2719      "foobar "
2720      "GL_CHROMIUM_flipy "
2721      "GL_EXT_unpack_subimage";
2722  const char kBad = 0x12;
2723  struct Cmds {
2724    cmd::SetBucketSize set_bucket_size1;
2725    cmds::GetString get_string;
2726    cmd::GetBucketStart get_bucket_start;
2727    cmd::SetToken set_token1;
2728    cmd::SetBucketSize set_bucket_size2;
2729  };
2730  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
2731  ExpectedMemoryInfo result1 =
2732      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2733  Cmds expected;
2734  expected.set_bucket_size1.Init(kBucketId, 0);
2735  expected.get_string.Init(GL_EXTENSIONS, kBucketId);
2736  expected.get_bucket_start.Init(
2737      kBucketId, result1.id, result1.offset,
2738      MaxTransferBufferSize(), mem1.id, mem1.offset);
2739  expected.set_token1.Init(GetNextToken());
2740  expected.set_bucket_size2.Init(kBucketId, 0);
2741  char buf[sizeof(kString) + 1];
2742  memset(buf, kBad, sizeof(buf));
2743
2744  EXPECT_CALL(*command_buffer(), OnFlush())
2745      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2746                      SetMemory(mem1.ptr, kString)))
2747      .RetiresOnSaturation();
2748
2749  const GLubyte* result = gl_->GetString(GL_EXTENSIONS);
2750  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2751  EXPECT_STREQ(expected_str, reinterpret_cast<const char*>(result));
2752}
2753
2754TEST_F(GLES2ImplementationTest, PixelStoreiGLPackReverseRowOrderANGLE) {
2755  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2756  const Str7 kString = {"foobar"};
2757  struct Cmds {
2758    cmd::SetBucketSize set_bucket_size1;
2759    cmds::GetString get_string;
2760    cmd::GetBucketStart get_bucket_start;
2761    cmd::SetToken set_token1;
2762    cmd::SetBucketSize set_bucket_size2;
2763    cmds::PixelStorei pixel_store;
2764  };
2765
2766  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
2767  ExpectedMemoryInfo result1 =
2768      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2769
2770  Cmds expected;
2771  expected.set_bucket_size1.Init(kBucketId, 0);
2772  expected.get_string.Init(GL_EXTENSIONS, kBucketId);
2773  expected.get_bucket_start.Init(
2774      kBucketId, result1.id, result1.offset,
2775      MaxTransferBufferSize(), mem1.id, mem1.offset);
2776  expected.set_token1.Init(GetNextToken());
2777  expected.set_bucket_size2.Init(kBucketId, 0);
2778  expected.pixel_store.Init(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1);
2779
2780  EXPECT_CALL(*command_buffer(), OnFlush())
2781      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2782                      SetMemory(mem1.ptr, kString)))
2783      .RetiresOnSaturation();
2784
2785  gl_->PixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1);
2786  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2787}
2788
2789TEST_F(GLES2ImplementationTest, CreateProgram) {
2790  struct Cmds {
2791    cmds::CreateProgram cmd;
2792  };
2793
2794  Cmds expected;
2795  expected.cmd.Init(kProgramsAndShadersStartId);
2796  GLuint id = gl_->CreateProgram();
2797  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2798  EXPECT_EQ(kProgramsAndShadersStartId, id);
2799}
2800
2801TEST_F(GLES2ImplementationTest, BufferDataLargerThanTransferBuffer) {
2802  struct Cmds {
2803    cmds::BufferData set_size;
2804    cmds::BufferSubData copy_data1;
2805    cmd::SetToken set_token1;
2806    cmds::BufferSubData copy_data2;
2807    cmd::SetToken set_token2;
2808  };
2809  const unsigned kUsableSize =
2810      kTransferBufferSize - GLES2Implementation::kStartingOffset;
2811  uint8 buf[kUsableSize * 2] = { 0, };
2812
2813  ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize);
2814  ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize);
2815
2816  Cmds expected;
2817  expected.set_size.Init(
2818      GL_ARRAY_BUFFER, arraysize(buf), 0, 0, GL_DYNAMIC_DRAW);
2819  expected.copy_data1.Init(
2820      GL_ARRAY_BUFFER, 0, kUsableSize, mem1.id, mem1.offset);
2821  expected.set_token1.Init(GetNextToken());
2822  expected.copy_data2.Init(
2823      GL_ARRAY_BUFFER, kUsableSize, kUsableSize, mem2.id, mem2.offset);
2824  expected.set_token2.Init(GetNextToken());
2825  gl_->BufferData(GL_ARRAY_BUFFER, arraysize(buf), buf, GL_DYNAMIC_DRAW);
2826  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2827}
2828
2829TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) {
2830  static const GLenum kStates[] = {
2831    GL_DITHER,
2832    GL_BLEND,
2833    GL_CULL_FACE,
2834    GL_DEPTH_TEST,
2835    GL_POLYGON_OFFSET_FILL,
2836    GL_SAMPLE_ALPHA_TO_COVERAGE,
2837    GL_SAMPLE_COVERAGE,
2838    GL_SCISSOR_TEST,
2839    GL_STENCIL_TEST,
2840  };
2841  struct Cmds {
2842    cmds::Enable enable_cmd;
2843  };
2844  Cmds expected;
2845
2846  for (size_t ii = 0; ii < arraysize(kStates); ++ii) {
2847    GLenum state = kStates[ii];
2848    expected.enable_cmd.Init(state);
2849    GLboolean result = gl_->IsEnabled(state);
2850    EXPECT_EQ(static_cast<GLboolean>(ii == 0), result);
2851    EXPECT_TRUE(NoCommandsWritten());
2852    const void* commands = GetPut();
2853    if (!result) {
2854      gl_->Enable(state);
2855      EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
2856    }
2857    ClearCommands();
2858    result = gl_->IsEnabled(state);
2859    EXPECT_TRUE(result);
2860    EXPECT_TRUE(NoCommandsWritten());
2861  }
2862}
2863
2864TEST_F(GLES2ImplementationTest, BindVertexArrayOES) {
2865  GLuint id = 0;
2866  gl_->GenVertexArraysOES(1, &id);
2867  ClearCommands();
2868
2869  struct Cmds {
2870    cmds::BindVertexArrayOES cmd;
2871  };
2872  Cmds expected;
2873  expected.cmd.Init(id);
2874
2875  const void* commands = GetPut();
2876  gl_->BindVertexArrayOES(id);
2877  EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
2878  ClearCommands();
2879  gl_->BindVertexArrayOES(id);
2880  EXPECT_TRUE(NoCommandsWritten());
2881}
2882
2883TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) {
2884  // Test GetQueryivEXT returns 0 if no current query.
2885  GLint param = -1;
2886  gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, &param);
2887  EXPECT_EQ(0, param);
2888
2889  GLuint expected_ids[2] = { 1, 2 }; // These must match what's actually genned.
2890  struct GenCmds {
2891    cmds::GenQueriesEXTImmediate gen;
2892    GLuint data[2];
2893  };
2894  GenCmds expected_gen_cmds;
2895  expected_gen_cmds.gen.Init(arraysize(expected_ids), &expected_ids[0]);
2896  GLuint ids[arraysize(expected_ids)] = { 0, };
2897  gl_->GenQueriesEXT(arraysize(expected_ids), &ids[0]);
2898  EXPECT_EQ(0, memcmp(
2899      &expected_gen_cmds, commands_, sizeof(expected_gen_cmds)));
2900  GLuint id1 = ids[0];
2901  GLuint id2 = ids[1];
2902  ClearCommands();
2903
2904  // Test BeginQueryEXT fails if id = 0.
2905  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0);
2906  EXPECT_TRUE(NoCommandsWritten());
2907  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2908
2909  // Test BeginQueryEXT fails if id not GENed.
2910  // TODO(gman):
2911
2912  // Test BeginQueryEXT inserts command.
2913  struct BeginCmds {
2914    cmds::BeginQueryEXT begin_query;
2915  };
2916  BeginCmds expected_begin_cmds;
2917  const void* commands = GetPut();
2918  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1);
2919  QueryTracker::Query* query = GetQuery(id1);
2920  ASSERT_TRUE(query != NULL);
2921  expected_begin_cmds.begin_query.Init(
2922      GL_ANY_SAMPLES_PASSED_EXT, id1, query->shm_id(), query->shm_offset());
2923  EXPECT_EQ(0, memcmp(
2924      &expected_begin_cmds, commands, sizeof(expected_begin_cmds)));
2925  ClearCommands();
2926
2927  // Test GetQueryivEXT returns id.
2928  param = -1;
2929  gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, &param);
2930  EXPECT_EQ(id1, static_cast<GLuint>(param));
2931  gl_->GetQueryivEXT(
2932      GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_CURRENT_QUERY_EXT, &param);
2933  EXPECT_EQ(0, param);
2934
2935  // Test BeginQueryEXT fails if between Begin/End.
2936  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id2);
2937  EXPECT_TRUE(NoCommandsWritten());
2938  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2939
2940  // Test EndQueryEXT fails if target not same as current query.
2941  ClearCommands();
2942  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
2943  EXPECT_TRUE(NoCommandsWritten());
2944  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2945
2946  // Test EndQueryEXT sends command
2947  struct EndCmds {
2948    cmds::EndQueryEXT end_query;
2949  };
2950  EndCmds expected_end_cmds;
2951  expected_end_cmds.end_query.Init(
2952      GL_ANY_SAMPLES_PASSED_EXT, query->submit_count());
2953  commands = GetPut();
2954  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
2955  EXPECT_EQ(0, memcmp(
2956      &expected_end_cmds, commands, sizeof(expected_end_cmds)));
2957
2958  // Test EndQueryEXT fails if no current query.
2959  ClearCommands();
2960  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
2961  EXPECT_TRUE(NoCommandsWritten());
2962  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2963
2964  // Test 2nd Begin/End increments count.
2965  base::subtle::Atomic32 old_submit_count = query->submit_count();
2966  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1);
2967  EXPECT_NE(old_submit_count, query->submit_count());
2968  expected_end_cmds.end_query.Init(
2969      GL_ANY_SAMPLES_PASSED_EXT, query->submit_count());
2970  commands = GetPut();
2971  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
2972  EXPECT_EQ(0, memcmp(
2973      &expected_end_cmds, commands, sizeof(expected_end_cmds)));
2974
2975  // Test BeginQueryEXT fails if target changed.
2976  ClearCommands();
2977  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, id1);
2978  EXPECT_TRUE(NoCommandsWritten());
2979  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2980
2981  // Test GetQueryObjectuivEXT fails if unused id
2982  GLuint available = 0xBDu;
2983  ClearCommands();
2984  gl_->GetQueryObjectuivEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
2985  EXPECT_TRUE(NoCommandsWritten());
2986  EXPECT_EQ(0xBDu, available);
2987  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2988
2989  // Test GetQueryObjectuivEXT fails if bad id
2990  ClearCommands();
2991  gl_->GetQueryObjectuivEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
2992  EXPECT_TRUE(NoCommandsWritten());
2993  EXPECT_EQ(0xBDu, available);
2994  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
2995
2996  // Test GetQueryObjectuivEXT CheckResultsAvailable
2997  ClearCommands();
2998  gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
2999  EXPECT_TRUE(NoCommandsWritten());
3000  EXPECT_EQ(0u, available);
3001}
3002
3003TEST_F(GLES2ImplementationTest, ErrorQuery) {
3004  GLuint id = 0;
3005  gl_->GenQueriesEXT(1, &id);
3006  ClearCommands();
3007
3008  // Test BeginQueryEXT does NOT insert commands.
3009  gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id);
3010  EXPECT_TRUE(NoCommandsWritten());
3011  QueryTracker::Query* query = GetQuery(id);
3012  ASSERT_TRUE(query != NULL);
3013
3014  // Test EndQueryEXT sends both begin and end command
3015  struct EndCmds {
3016    cmds::BeginQueryEXT begin_query;
3017    cmds::EndQueryEXT end_query;
3018  };
3019  EndCmds expected_end_cmds;
3020  expected_end_cmds.begin_query.Init(
3021      GL_GET_ERROR_QUERY_CHROMIUM, id, query->shm_id(), query->shm_offset());
3022  expected_end_cmds.end_query.Init(
3023      GL_GET_ERROR_QUERY_CHROMIUM, query->submit_count());
3024  const void* commands = GetPut();
3025  gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM);
3026  EXPECT_EQ(0, memcmp(
3027      &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3028  ClearCommands();
3029
3030  // Check result is not yet available.
3031  GLuint available = 0xBDu;
3032  gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3033  EXPECT_TRUE(NoCommandsWritten());
3034  EXPECT_EQ(0u, available);
3035
3036  // Test no commands are sent if there is a client side error.
3037
3038  // Generate a client side error
3039  gl_->ActiveTexture(GL_TEXTURE0 - 1);
3040
3041  gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id);
3042  gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM);
3043  EXPECT_TRUE(NoCommandsWritten());
3044
3045  // Check result is available.
3046  gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3047  EXPECT_TRUE(NoCommandsWritten());
3048  EXPECT_NE(0u, available);
3049
3050  // Check result.
3051  GLuint result = 0xBDu;
3052  gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_EXT, &result);
3053  EXPECT_TRUE(NoCommandsWritten());
3054  EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), result);
3055}
3056
3057#if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
3058TEST_F(GLES2ImplementationTest, VertexArrays) {
3059  const GLuint kAttribIndex1 = 1;
3060  const GLint kNumComponents1 = 3;
3061  const GLsizei kClientStride = 12;
3062
3063  GLuint id = 0;
3064  gl_->GenVertexArraysOES(1, &id);
3065  ClearCommands();
3066
3067  gl_->BindVertexArrayOES(id);
3068
3069  // Test that VertexAttribPointer cannot be called with a bound buffer of 0
3070  // unless the offset is NULL
3071  gl_->BindBuffer(GL_ARRAY_BUFFER, 0);
3072
3073  gl_->VertexAttribPointer(
3074      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride,
3075      reinterpret_cast<const void*>(4));
3076  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3077
3078  gl_->VertexAttribPointer(
3079      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, NULL);
3080  EXPECT_EQ(GL_NO_ERROR, CheckError());
3081}
3082#endif
3083
3084TEST_F(GLES2ImplementationTest, Disable) {
3085  struct Cmds {
3086    cmds::Disable cmd;
3087  };
3088  Cmds expected;
3089  expected.cmd.Init(GL_DITHER);  // Note: DITHER defaults to enabled.
3090
3091  gl_->Disable(GL_DITHER);
3092  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3093  // Check it's cached and not called again.
3094  ClearCommands();
3095  gl_->Disable(GL_DITHER);
3096  EXPECT_TRUE(NoCommandsWritten());
3097}
3098
3099TEST_F(GLES2ImplementationTest, Enable) {
3100  struct Cmds {
3101    cmds::Enable cmd;
3102  };
3103  Cmds expected;
3104  expected.cmd.Init(GL_BLEND);  // Note: BLEND defaults to disabled.
3105
3106  gl_->Enable(GL_BLEND);
3107  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3108  // Check it's cached and not called again.
3109  ClearCommands();
3110  gl_->Enable(GL_BLEND);
3111  EXPECT_TRUE(NoCommandsWritten());
3112}
3113
3114TEST_F(GLES2ImplementationTest, ConsumeTextureCHROMIUM) {
3115  struct Cmds {
3116    cmds::ConsumeTextureCHROMIUMImmediate cmd;
3117    GLbyte data[64];
3118  };
3119
3120  Mailbox mailbox = Mailbox::Generate();
3121  Cmds expected;
3122  expected.cmd.Init(GL_TEXTURE_2D, mailbox.name);
3123  gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
3124  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3125}
3126
3127TEST_F(GLES2ImplementationTest, ProduceTextureCHROMIUM) {
3128  struct Cmds {
3129    cmds::ProduceTextureCHROMIUMImmediate cmd;
3130    GLbyte data[64];
3131  };
3132
3133  Mailbox mailbox = Mailbox::Generate();
3134  Cmds expected;
3135  expected.cmd.Init(GL_TEXTURE_2D, mailbox.name);
3136  gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
3137  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3138}
3139
3140TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) {
3141  ContextInitOptions init_options;
3142  init_options.lose_context_when_out_of_memory = true;
3143  ASSERT_TRUE(Initialize(init_options));
3144
3145  struct Cmds {
3146    cmds::LoseContextCHROMIUM cmd;
3147  };
3148
3149  GLsizei max = std::numeric_limits<GLsizei>::max();
3150  EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _))
3151      .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL)));
3152  gl_->CreateImageCHROMIUM(max, max, 0);
3153  // The context should be lost.
3154  Cmds expected;
3155  expected.cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_UNKNOWN_CONTEXT_RESET_ARB);
3156  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3157}
3158
3159TEST_F(GLES2ImplementationManualInitTest, NoLoseContextOnOOM) {
3160  ContextInitOptions init_options;
3161  ASSERT_TRUE(Initialize(init_options));
3162
3163  struct Cmds {
3164    cmds::LoseContextCHROMIUM cmd;
3165  };
3166
3167  GLsizei max = std::numeric_limits<GLsizei>::max();
3168  EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _))
3169      .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL)));
3170  gl_->CreateImageCHROMIUM(max, max, 0);
3171  // The context should not be lost.
3172  EXPECT_TRUE(NoCommandsWritten());
3173}
3174
3175TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch1) {
3176  ContextInitOptions init_options;
3177  init_options.bind_generates_resource_client = false;
3178  init_options.bind_generates_resource_service = true;
3179  EXPECT_FALSE(Initialize(init_options));
3180}
3181
3182TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch2) {
3183  ContextInitOptions init_options;
3184  init_options.bind_generates_resource_client = true;
3185  init_options.bind_generates_resource_service = false;
3186  EXPECT_FALSE(Initialize(init_options));
3187}
3188
3189#include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h"
3190
3191}  // namespace gles2
3192}  // namespace gpu
3193