gles2_implementation_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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()->GetLastState().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  const std::string& GetLastError() {
602    return gl_->GetLastError();
603  }
604
605  bool GetBucketContents(uint32 bucket_id, std::vector<int8>* data) {
606    return gl_->GetBucketContents(bucket_id, data);
607  }
608
609  TestContext test_contexts_[kNumTestContexts];
610
611  scoped_refptr<ShareGroup> share_group_;
612  MockClientGpuControl* gpu_control_;
613  GLES2CmdHelper* helper_;
614  MockTransferBuffer* transfer_buffer_;
615  GLES2Implementation* gl_;
616  CommandBufferEntry* commands_;
617};
618
619void GLES2ImplementationTest::SetUp() {
620  ContextInitOptions init_options;
621  ASSERT_TRUE(Initialize(init_options));
622}
623
624void GLES2ImplementationTest::TearDown() {
625  for (int i = 0; i < kNumTestContexts; i++)
626    test_contexts_[i].TearDown();
627}
628
629class GLES2ImplementationManualInitTest : public GLES2ImplementationTest {
630 protected:
631  virtual void SetUp() OVERRIDE {}
632};
633
634class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest {
635 protected:
636  virtual void SetUp() OVERRIDE;
637
638  template <class ResApi>
639  void FlushGenerationTest() {
640    GLuint id1, id2, id3;
641
642    // Generate valid id.
643    ResApi::Gen(gl_, 1, &id1);
644    EXPECT_NE(id1, 0u);
645
646    // Delete id1 and generate id2.  id1 should not be reused.
647    ResApi::Delete(gl_, 1, &id1);
648    ResApi::Gen(gl_, 1, &id2);
649    EXPECT_NE(id2, 0u);
650    EXPECT_NE(id2, id1);
651
652    // Expect id1 reuse after Flush.
653    gl_->Flush();
654    ResApi::Gen(gl_, 1, &id3);
655    EXPECT_EQ(id3, id1);
656  }
657
658  // Ids should not be reused unless the |Deleting| context does a Flush()
659  // AND triggers a lazy release after that.
660  template <class ResApi>
661  void CrossContextGenerationTest() {
662    GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
663    GLES2Implementation* gl2 = test_contexts_[1].gl_.get();
664    GLuint id1, id2, id3;
665
666    // Delete, no flush on context 1.  No reuse.
667    ResApi::Gen(gl1, 1, &id1);
668    ResApi::Delete(gl1, 1, &id1);
669    ResApi::Gen(gl1, 1, &id2);
670    EXPECT_NE(id1, id2);
671
672    // Flush context 2.  Still no reuse.
673    gl2->Flush();
674    ResApi::Gen(gl2, 1, &id3);
675    EXPECT_NE(id1, id3);
676    EXPECT_NE(id2, id3);
677
678    // Flush on context 1, but no lazy release.  Still no reuse.
679    gl1->Flush();
680    ResApi::Gen(gl2, 1, &id3);
681    EXPECT_NE(id1, id3);
682
683    // Lazy release triggered by another Delete.  Should reuse id1.
684    ResApi::Delete(gl1, 1, &id2);
685    ResApi::Gen(gl2, 1, &id3);
686    EXPECT_EQ(id1, id3);
687  }
688
689  // Same as CrossContextGenerationTest(), but triggers an Auto Flush on
690  // the Delete().  Tests an edge case regression.
691  template <class ResApi>
692  void CrossContextGenerationAutoFlushTest() {
693    GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
694    GLES2Implementation* gl2 = test_contexts_[1].gl_.get();
695    GLuint id1, id2, id3;
696
697    // Delete, no flush on context 1.  No reuse.
698    // By half filling the buffer, an internal flush is forced on the Delete().
699    ResApi::Gen(gl1, 1, &id1);
700    gl1->helper()->Noop(kNumCommandEntries / 2);
701    ResApi::Delete(gl1, 1, &id1);
702    ResApi::Gen(gl1, 1, &id2);
703    EXPECT_NE(id1, id2);
704
705    // Flush context 2.  Still no reuse.
706    gl2->Flush();
707    ResApi::Gen(gl2, 1, &id3);
708    EXPECT_NE(id1, id3);
709    EXPECT_NE(id2, id3);
710
711    // Flush on context 1, but no lazy release.  Still no reuse.
712    gl1->Flush();
713    ResApi::Gen(gl2, 1, &id3);
714    EXPECT_NE(id1, id3);
715
716    // Lazy release triggered by another Delete.  Should reuse id1.
717    ResApi::Delete(gl1, 1, &id2);
718    ResApi::Gen(gl2, 1, &id3);
719    EXPECT_EQ(id1, id3);
720  }
721};
722
723void GLES2ImplementationStrictSharedTest::SetUp() {
724  ContextInitOptions init_options;
725  init_options.bind_generates_resource_client = false;
726  init_options.bind_generates_resource_service = false;
727  ASSERT_TRUE(Initialize(init_options));
728}
729
730// GCC requires these declarations, but MSVC requires they not be present
731#ifndef _MSC_VER
732const uint8 GLES2ImplementationTest::kInitialValue;
733const int32 GLES2ImplementationTest::kNumCommandEntries;
734const int32 GLES2ImplementationTest::kCommandBufferSizeBytes;
735const size_t GLES2ImplementationTest::kTransferBufferSize;
736const GLint GLES2ImplementationTest::kMaxCombinedTextureImageUnits;
737const GLint GLES2ImplementationTest::kMaxCubeMapTextureSize;
738const GLint GLES2ImplementationTest::kMaxFragmentUniformVectors;
739const GLint GLES2ImplementationTest::kMaxRenderbufferSize;
740const GLint GLES2ImplementationTest::kMaxTextureImageUnits;
741const GLint GLES2ImplementationTest::kMaxTextureSize;
742const GLint GLES2ImplementationTest::kMaxVaryingVectors;
743const GLint GLES2ImplementationTest::kMaxVertexAttribs;
744const GLint GLES2ImplementationTest::kMaxVertexTextureImageUnits;
745const GLint GLES2ImplementationTest::kMaxVertexUniformVectors;
746const GLint GLES2ImplementationTest::kNumCompressedTextureFormats;
747const GLint GLES2ImplementationTest::kNumShaderBinaryFormats;
748const GLuint GLES2ImplementationTest::kStartId;
749const GLuint GLES2ImplementationTest::kBuffersStartId;
750const GLuint GLES2ImplementationTest::kFramebuffersStartId;
751const GLuint GLES2ImplementationTest::kProgramsAndShadersStartId;
752const GLuint GLES2ImplementationTest::kRenderbuffersStartId;
753const GLuint GLES2ImplementationTest::kTexturesStartId;
754const GLuint GLES2ImplementationTest::kQueriesStartId;
755const GLuint GLES2ImplementationTest::kVertexArraysStartId;
756#endif
757
758TEST_F(GLES2ImplementationTest, Basic) {
759  EXPECT_TRUE(gl_->share_group() != NULL);
760}
761
762TEST_F(GLES2ImplementationTest, GetBucketContents) {
763  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
764  const uint32 kTestSize = MaxTransferBufferSize() + 32;
765
766  scoped_ptr<uint8[]> buf(new uint8 [kTestSize]);
767  uint8* expected_data = buf.get();
768  for (uint32 ii = 0; ii < kTestSize; ++ii) {
769    expected_data[ii] = ii * 3;
770  }
771
772  struct Cmds {
773    cmd::GetBucketStart get_bucket_start;
774    cmd::SetToken set_token1;
775    cmd::GetBucketData get_bucket_data;
776    cmd::SetToken set_token2;
777    cmd::SetBucketSize set_bucket_size2;
778  };
779
780  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
781  ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32));
782  ExpectedMemoryInfo mem2 = GetExpectedMemory(
783      kTestSize - MaxTransferBufferSize());
784
785  Cmds expected;
786  expected.get_bucket_start.Init(
787      kBucketId, result1.id, result1.offset,
788      MaxTransferBufferSize(), mem1.id, mem1.offset);
789  expected.set_token1.Init(GetNextToken());
790  expected.get_bucket_data.Init(
791      kBucketId, MaxTransferBufferSize(),
792      kTestSize - MaxTransferBufferSize(), mem2.id, mem2.offset);
793  expected.set_bucket_size2.Init(kBucketId, 0);
794  expected.set_token2.Init(GetNextToken());
795
796  EXPECT_CALL(*command_buffer(), OnFlush())
797      .WillOnce(DoAll(
798          SetMemory(result1.ptr, kTestSize),
799          SetMemoryFromArray(
800              mem1.ptr, expected_data, MaxTransferBufferSize())))
801      .WillOnce(SetMemoryFromArray(
802          mem2.ptr, expected_data + MaxTransferBufferSize(),
803          kTestSize - MaxTransferBufferSize()))
804      .RetiresOnSaturation();
805
806  std::vector<int8> data;
807  GetBucketContents(kBucketId, &data);
808  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
809  ASSERT_EQ(kTestSize, data.size());
810  EXPECT_EQ(0, memcmp(expected_data, &data[0], data.size()));
811}
812
813TEST_F(GLES2ImplementationTest, GetShaderPrecisionFormat) {
814  struct Cmds {
815    cmds::GetShaderPrecisionFormat cmd;
816  };
817  typedef cmds::GetShaderPrecisionFormat::Result Result;
818
819  // The first call for mediump should trigger a command buffer request.
820  GLint range1[2] = {0, 0};
821  GLint precision1 = 0;
822  Cmds expected1;
823  ExpectedMemoryInfo client_result1 = GetExpectedResultMemory(4);
824  expected1.cmd.Init(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT,
825                     client_result1.id, client_result1.offset);
826  Result server_result1 = {true, 14, 14, 10};
827  EXPECT_CALL(*command_buffer(), OnFlush())
828      .WillOnce(SetMemory(client_result1.ptr, server_result1))
829      .RetiresOnSaturation();
830  gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT,
831                                range1, &precision1);
832  const void* commands2 = GetPut();
833  EXPECT_NE(commands_, commands2);
834  EXPECT_EQ(0, memcmp(&expected1, commands_, sizeof(expected1)));
835  EXPECT_EQ(range1[0], 14);
836  EXPECT_EQ(range1[1], 14);
837  EXPECT_EQ(precision1, 10);
838
839  // The second call for mediump should use the cached value and avoid
840  // triggering a command buffer request, so we do not expect a call to
841  // OnFlush() here. We do expect the results to be correct though.
842  GLint range2[2] = {0, 0};
843  GLint precision2 = 0;
844  gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT,
845                                range2, &precision2);
846  const void* commands3 = GetPut();
847  EXPECT_EQ(commands2, commands3);
848  EXPECT_EQ(range2[0], 14);
849  EXPECT_EQ(range2[1], 14);
850  EXPECT_EQ(precision2, 10);
851
852  // If we then make a request for highp, we should get another command
853  // buffer request since it hasn't been cached yet.
854  GLint range3[2] = {0, 0};
855  GLint precision3 = 0;
856  Cmds expected3;
857  ExpectedMemoryInfo result3 = GetExpectedResultMemory(4);
858  expected3.cmd.Init(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
859                     result3.id, result3.offset);
860  Result result3_source = {true, 62, 62, 16};
861  EXPECT_CALL(*command_buffer(), OnFlush())
862      .WillOnce(SetMemory(result3.ptr, result3_source))
863      .RetiresOnSaturation();
864  gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT,
865                                range3, &precision3);
866  const void* commands4 = GetPut();
867  EXPECT_NE(commands3, commands4);
868  EXPECT_EQ(0, memcmp(&expected3, commands3, sizeof(expected3)));
869  EXPECT_EQ(range3[0], 62);
870  EXPECT_EQ(range3[1], 62);
871  EXPECT_EQ(precision3, 16);
872}
873
874TEST_F(GLES2ImplementationTest, ShaderSource) {
875  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
876  const GLuint kShaderId = 456;
877  const char* kString1 = "foobar";
878  const char* kString2 = "barfoo";
879  const size_t kString1Size = strlen(kString1);
880  const size_t kString2Size = strlen(kString2);
881  const size_t kString3Size = 1;  // Want the NULL;
882  const size_t kSourceSize = kString1Size + kString2Size + kString3Size;
883  const size_t kPaddedString1Size =
884      transfer_buffer_->RoundToAlignment(kString1Size);
885  const size_t kPaddedString2Size =
886      transfer_buffer_->RoundToAlignment(kString2Size);
887  const size_t kPaddedString3Size =
888      transfer_buffer_->RoundToAlignment(kString3Size);
889  struct Cmds {
890    cmd::SetBucketSize set_bucket_size;
891    cmd::SetBucketData set_bucket_data1;
892    cmd::SetToken set_token1;
893    cmd::SetBucketData set_bucket_data2;
894    cmd::SetToken set_token2;
895    cmd::SetBucketData set_bucket_data3;
896    cmd::SetToken set_token3;
897    cmds::ShaderSourceBucket shader_source_bucket;
898    cmd::SetBucketSize clear_bucket_size;
899  };
900
901  ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size);
902  ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size);
903  ExpectedMemoryInfo mem3 = GetExpectedMemory(kPaddedString3Size);
904
905  Cmds expected;
906  expected.set_bucket_size.Init(kBucketId, kSourceSize);
907  expected.set_bucket_data1.Init(
908      kBucketId, 0, kString1Size, mem1.id, mem1.offset);
909  expected.set_token1.Init(GetNextToken());
910  expected.set_bucket_data2.Init(
911      kBucketId, kString1Size, kString2Size, mem2.id, mem2.offset);
912  expected.set_token2.Init(GetNextToken());
913  expected.set_bucket_data3.Init(
914      kBucketId, kString1Size + kString2Size,
915      kString3Size, mem3.id, mem3.offset);
916  expected.set_token3.Init(GetNextToken());
917  expected.shader_source_bucket.Init(kShaderId, kBucketId);
918  expected.clear_bucket_size.Init(kBucketId, 0);
919  const char* strings[] = {
920    kString1,
921    kString2,
922  };
923  gl_->ShaderSource(kShaderId, 2, strings, NULL);
924  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
925}
926
927TEST_F(GLES2ImplementationTest, GetShaderSource) {
928  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
929  const GLuint kShaderId = 456;
930  const Str7 kString = {"foobar"};
931  const char kBad = 0x12;
932  struct Cmds {
933    cmd::SetBucketSize set_bucket_size1;
934    cmds::GetShaderSource get_shader_source;
935    cmd::GetBucketStart get_bucket_start;
936    cmd::SetToken set_token1;
937    cmd::SetBucketSize set_bucket_size2;
938  };
939
940  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
941  ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32));
942
943  Cmds expected;
944  expected.set_bucket_size1.Init(kBucketId, 0);
945  expected.get_shader_source.Init(kShaderId, kBucketId);
946  expected.get_bucket_start.Init(
947      kBucketId, result1.id, result1.offset,
948      MaxTransferBufferSize(), mem1.id, mem1.offset);
949  expected.set_token1.Init(GetNextToken());
950  expected.set_bucket_size2.Init(kBucketId, 0);
951  char buf[sizeof(kString) + 1];
952  memset(buf, kBad, sizeof(buf));
953
954  EXPECT_CALL(*command_buffer(), OnFlush())
955      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
956                      SetMemory(mem1.ptr, kString)))
957      .RetiresOnSaturation();
958
959  GLsizei length = 0;
960  gl_->GetShaderSource(kShaderId, sizeof(buf), &length, buf);
961  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
962  EXPECT_EQ(sizeof(kString) - 1, static_cast<size_t>(length));
963  EXPECT_STREQ(kString.str, buf);
964  EXPECT_EQ(buf[sizeof(kString)], kBad);
965}
966
967#if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
968
969TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) {
970  static const float verts[][4] = {
971    { 12.0f, 23.0f, 34.0f, 45.0f, },
972    { 56.0f, 67.0f, 78.0f, 89.0f, },
973    { 13.0f, 24.0f, 35.0f, 46.0f, },
974  };
975  struct Cmds {
976    cmds::EnableVertexAttribArray enable1;
977    cmds::EnableVertexAttribArray enable2;
978    cmds::BindBuffer bind_to_emu;
979    cmds::BufferData set_size;
980    cmds::BufferSubData copy_data1;
981    cmd::SetToken set_token1;
982    cmds::VertexAttribPointer set_pointer1;
983    cmds::BufferSubData copy_data2;
984    cmd::SetToken set_token2;
985    cmds::VertexAttribPointer set_pointer2;
986    cmds::DrawArrays draw;
987    cmds::BindBuffer restore;
988  };
989  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
990  const GLuint kAttribIndex1 = 1;
991  const GLuint kAttribIndex2 = 3;
992  const GLint kNumComponents1 = 3;
993  const GLint kNumComponents2 = 2;
994  const GLsizei kClientStride = sizeof(verts[0]);
995  const GLint kFirst = 1;
996  const GLsizei kCount = 2;
997  const GLsizei kSize1 =
998      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
999  const GLsizei kSize2 =
1000      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1001  const GLsizei kEmuOffset1 = 0;
1002  const GLsizei kEmuOffset2 = kSize1;
1003  const GLsizei kTotalSize = kSize1 + kSize2;
1004
1005  ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1);
1006  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2);
1007
1008  Cmds expected;
1009  expected.enable1.Init(kAttribIndex1);
1010  expected.enable2.Init(kAttribIndex2);
1011  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1012  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1013  expected.copy_data1.Init(
1014      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset);
1015  expected.set_token1.Init(GetNextToken());
1016  expected.set_pointer1.Init(
1017      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1018  expected.copy_data2.Init(
1019      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset);
1020  expected.set_token2.Init(GetNextToken());
1021  expected.set_pointer2.Init(
1022      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1023  expected.draw.Init(GL_POINTS, kFirst, kCount);
1024  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1025  gl_->EnableVertexAttribArray(kAttribIndex1);
1026  gl_->EnableVertexAttribArray(kAttribIndex2);
1027  gl_->VertexAttribPointer(
1028      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts);
1029  gl_->VertexAttribPointer(
1030      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts);
1031  gl_->DrawArrays(GL_POINTS, kFirst, kCount);
1032  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1033}
1034
1035TEST_F(GLES2ImplementationTest, DrawArraysInstancedANGLEClientSideBuffers) {
1036  static const float verts[][4] = {
1037    { 12.0f, 23.0f, 34.0f, 45.0f, },
1038    { 56.0f, 67.0f, 78.0f, 89.0f, },
1039    { 13.0f, 24.0f, 35.0f, 46.0f, },
1040  };
1041  struct Cmds {
1042    cmds::EnableVertexAttribArray enable1;
1043    cmds::EnableVertexAttribArray enable2;
1044    cmds::VertexAttribDivisorANGLE divisor;
1045    cmds::BindBuffer bind_to_emu;
1046    cmds::BufferData set_size;
1047    cmds::BufferSubData copy_data1;
1048    cmd::SetToken set_token1;
1049    cmds::VertexAttribPointer set_pointer1;
1050    cmds::BufferSubData copy_data2;
1051    cmd::SetToken set_token2;
1052    cmds::VertexAttribPointer set_pointer2;
1053    cmds::DrawArraysInstancedANGLE draw;
1054    cmds::BindBuffer restore;
1055  };
1056  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1057  const GLuint kAttribIndex1 = 1;
1058  const GLuint kAttribIndex2 = 3;
1059  const GLint kNumComponents1 = 3;
1060  const GLint kNumComponents2 = 2;
1061  const GLsizei kClientStride = sizeof(verts[0]);
1062  const GLint kFirst = 1;
1063  const GLsizei kCount = 2;
1064  const GLuint kDivisor = 1;
1065  const GLsizei kSize1 =
1066      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1067  const GLsizei kSize2 =
1068      1 * kNumComponents2 * sizeof(verts[0][0]);
1069  const GLsizei kEmuOffset1 = 0;
1070  const GLsizei kEmuOffset2 = kSize1;
1071  const GLsizei kTotalSize = kSize1 + kSize2;
1072
1073  ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1);
1074  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2);
1075
1076  Cmds expected;
1077  expected.enable1.Init(kAttribIndex1);
1078  expected.enable2.Init(kAttribIndex2);
1079  expected.divisor.Init(kAttribIndex2, kDivisor);
1080  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1081  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1082  expected.copy_data1.Init(
1083      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset);
1084  expected.set_token1.Init(GetNextToken());
1085  expected.set_pointer1.Init(
1086      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1087  expected.copy_data2.Init(
1088      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset);
1089  expected.set_token2.Init(GetNextToken());
1090  expected.set_pointer2.Init(
1091      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1092  expected.draw.Init(GL_POINTS, kFirst, kCount, 1);
1093  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1094  gl_->EnableVertexAttribArray(kAttribIndex1);
1095  gl_->EnableVertexAttribArray(kAttribIndex2);
1096  gl_->VertexAttribPointer(
1097      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts);
1098  gl_->VertexAttribPointer(
1099      kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts);
1100  gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor);
1101  gl_->DrawArraysInstancedANGLE(GL_POINTS, kFirst, kCount, 1);
1102  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1103}
1104
1105TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) {
1106  static const float verts[][4] = {
1107    { 12.0f, 23.0f, 34.0f, 45.0f, },
1108    { 56.0f, 67.0f, 78.0f, 89.0f, },
1109    { 13.0f, 24.0f, 35.0f, 46.0f, },
1110  };
1111  static const uint16 indices[] = {
1112    1, 2,
1113  };
1114  struct Cmds {
1115    cmds::EnableVertexAttribArray enable1;
1116    cmds::EnableVertexAttribArray enable2;
1117    cmds::BindBuffer bind_to_index_emu;
1118    cmds::BufferData set_index_size;
1119    cmds::BufferSubData copy_data0;
1120    cmd::SetToken set_token0;
1121    cmds::BindBuffer bind_to_emu;
1122    cmds::BufferData set_size;
1123    cmds::BufferSubData copy_data1;
1124    cmd::SetToken set_token1;
1125    cmds::VertexAttribPointer set_pointer1;
1126    cmds::BufferSubData copy_data2;
1127    cmd::SetToken set_token2;
1128    cmds::VertexAttribPointer set_pointer2;
1129    cmds::DrawElements draw;
1130    cmds::BindBuffer restore;
1131    cmds::BindBuffer restore_element;
1132  };
1133  const GLsizei kIndexSize = sizeof(indices);
1134  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1135  const GLuint kEmuIndexBufferId =
1136      GLES2Implementation::kClientSideElementArrayId;
1137  const GLuint kAttribIndex1 = 1;
1138  const GLuint kAttribIndex2 = 3;
1139  const GLint kNumComponents1 = 3;
1140  const GLint kNumComponents2 = 2;
1141  const GLsizei kClientStride = sizeof(verts[0]);
1142  const GLsizei kCount = 2;
1143  const GLsizei kSize1 =
1144      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1145  const GLsizei kSize2 =
1146      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1147  const GLsizei kEmuOffset1 = 0;
1148  const GLsizei kEmuOffset2 = kSize1;
1149  const GLsizei kTotalSize = kSize1 + kSize2;
1150
1151  ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1152  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1153  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1154
1155  Cmds expected;
1156  expected.enable1.Init(kAttribIndex1);
1157  expected.enable2.Init(kAttribIndex2);
1158  expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1159  expected.set_index_size.Init(
1160      GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1161  expected.copy_data0.Init(
1162      GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1163  expected.set_token0.Init(GetNextToken());
1164  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1165  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1166  expected.copy_data1.Init(
1167      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1168  expected.set_token1.Init(GetNextToken());
1169  expected.set_pointer1.Init(
1170      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1171  expected.copy_data2.Init(
1172      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1173  expected.set_token2.Init(GetNextToken());
1174  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1175                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1176  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0);
1177  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1178  expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1179  gl_->EnableVertexAttribArray(kAttribIndex1);
1180  gl_->EnableVertexAttribArray(kAttribIndex2);
1181  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1182                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1183  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1184                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1185  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices);
1186  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1187}
1188
1189TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersIndexUint) {
1190  static const float verts[][4] = {
1191    { 12.0f, 23.0f, 34.0f, 45.0f, },
1192    { 56.0f, 67.0f, 78.0f, 89.0f, },
1193    { 13.0f, 24.0f, 35.0f, 46.0f, },
1194  };
1195  static const uint32 indices[] = {
1196    1, 2,
1197  };
1198  struct Cmds {
1199    cmds::EnableVertexAttribArray enable1;
1200    cmds::EnableVertexAttribArray enable2;
1201    cmds::BindBuffer bind_to_index_emu;
1202    cmds::BufferData set_index_size;
1203    cmds::BufferSubData copy_data0;
1204    cmd::SetToken set_token0;
1205    cmds::BindBuffer bind_to_emu;
1206    cmds::BufferData set_size;
1207    cmds::BufferSubData copy_data1;
1208    cmd::SetToken set_token1;
1209    cmds::VertexAttribPointer set_pointer1;
1210    cmds::BufferSubData copy_data2;
1211    cmd::SetToken set_token2;
1212    cmds::VertexAttribPointer set_pointer2;
1213    cmds::DrawElements draw;
1214    cmds::BindBuffer restore;
1215    cmds::BindBuffer restore_element;
1216  };
1217  const GLsizei kIndexSize = sizeof(indices);
1218  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1219  const GLuint kEmuIndexBufferId =
1220      GLES2Implementation::kClientSideElementArrayId;
1221  const GLuint kAttribIndex1 = 1;
1222  const GLuint kAttribIndex2 = 3;
1223  const GLint kNumComponents1 = 3;
1224  const GLint kNumComponents2 = 2;
1225  const GLsizei kClientStride = sizeof(verts[0]);
1226  const GLsizei kCount = 2;
1227  const GLsizei kSize1 =
1228      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1229  const GLsizei kSize2 =
1230      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1231  const GLsizei kEmuOffset1 = 0;
1232  const GLsizei kEmuOffset2 = kSize1;
1233  const GLsizei kTotalSize = kSize1 + kSize2;
1234
1235  ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1236  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1237  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1238
1239  Cmds expected;
1240  expected.enable1.Init(kAttribIndex1);
1241  expected.enable2.Init(kAttribIndex2);
1242  expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1243  expected.set_index_size.Init(
1244      GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1245  expected.copy_data0.Init(
1246      GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1247  expected.set_token0.Init(GetNextToken());
1248  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1249  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1250  expected.copy_data1.Init(
1251      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1252  expected.set_token1.Init(GetNextToken());
1253  expected.set_pointer1.Init(
1254      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1255  expected.copy_data2.Init(
1256      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1257  expected.set_token2.Init(GetNextToken());
1258  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1259                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1260  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_INT, 0);
1261  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1262  expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1263  gl_->EnableVertexAttribArray(kAttribIndex1);
1264  gl_->EnableVertexAttribArray(kAttribIndex2);
1265  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1266                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1267  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1268                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1269  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices);
1270  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1271}
1272
1273TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersInvalidIndexUint) {
1274  static const float verts[][4] = {
1275    { 12.0f, 23.0f, 34.0f, 45.0f, },
1276    { 56.0f, 67.0f, 78.0f, 89.0f, },
1277    { 13.0f, 24.0f, 35.0f, 46.0f, },
1278  };
1279  static const uint32 indices[] = {
1280    1, 0x90000000
1281  };
1282
1283  const GLuint kAttribIndex1 = 1;
1284  const GLuint kAttribIndex2 = 3;
1285  const GLint kNumComponents1 = 3;
1286  const GLint kNumComponents2 = 2;
1287  const GLsizei kClientStride = sizeof(verts[0]);
1288  const GLsizei kCount = 2;
1289
1290  EXPECT_CALL(*command_buffer(), OnFlush())
1291      .Times(1)
1292      .RetiresOnSaturation();
1293
1294  gl_->EnableVertexAttribArray(kAttribIndex1);
1295  gl_->EnableVertexAttribArray(kAttribIndex2);
1296  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1297                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1298  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1299                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1300  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices);
1301
1302  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
1303}
1304
1305TEST_F(GLES2ImplementationTest,
1306       DrawElementsClientSideBuffersServiceSideIndices) {
1307  static const float verts[][4] = {
1308    { 12.0f, 23.0f, 34.0f, 45.0f, },
1309    { 56.0f, 67.0f, 78.0f, 89.0f, },
1310    { 13.0f, 24.0f, 35.0f, 46.0f, },
1311  };
1312  struct Cmds {
1313    cmds::EnableVertexAttribArray enable1;
1314    cmds::EnableVertexAttribArray enable2;
1315    cmds::BindBuffer bind_to_index;
1316    cmds::GetMaxValueInBufferCHROMIUM get_max;
1317    cmds::BindBuffer bind_to_emu;
1318    cmds::BufferData set_size;
1319    cmds::BufferSubData copy_data1;
1320    cmd::SetToken set_token1;
1321    cmds::VertexAttribPointer set_pointer1;
1322    cmds::BufferSubData copy_data2;
1323    cmd::SetToken set_token2;
1324    cmds::VertexAttribPointer set_pointer2;
1325    cmds::DrawElements draw;
1326    cmds::BindBuffer restore;
1327  };
1328  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1329  const GLuint kClientIndexBufferId = 0x789;
1330  const GLuint kIndexOffset = 0x40;
1331  const GLuint kMaxIndex = 2;
1332  const GLuint kAttribIndex1 = 1;
1333  const GLuint kAttribIndex2 = 3;
1334  const GLint kNumComponents1 = 3;
1335  const GLint kNumComponents2 = 2;
1336  const GLsizei kClientStride = sizeof(verts[0]);
1337  const GLsizei kCount = 2;
1338  const GLsizei kSize1 =
1339      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1340  const GLsizei kSize2 =
1341      arraysize(verts) * kNumComponents2 * sizeof(verts[0][0]);
1342  const GLsizei kEmuOffset1 = 0;
1343  const GLsizei kEmuOffset2 = kSize1;
1344  const GLsizei kTotalSize = kSize1 + kSize2;
1345
1346  ExpectedMemoryInfo mem1 = GetExpectedResultMemory(sizeof(uint32));
1347  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1348  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1349
1350
1351  Cmds expected;
1352  expected.enable1.Init(kAttribIndex1);
1353  expected.enable2.Init(kAttribIndex2);
1354  expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId);
1355  expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT,
1356                        kIndexOffset, mem1.id, mem1.offset);
1357  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1358  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1359  expected.copy_data1.Init(
1360      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1361  expected.set_token1.Init(GetNextToken());
1362  expected.set_pointer1.Init(kAttribIndex1, kNumComponents1,
1363                             GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1364  expected.copy_data2.Init(
1365      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1366  expected.set_token2.Init(GetNextToken());
1367  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1368                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1369  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, kIndexOffset);
1370  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1371
1372  EXPECT_CALL(*command_buffer(), OnFlush())
1373      .WillOnce(SetMemory(mem1.ptr,kMaxIndex))
1374      .RetiresOnSaturation();
1375
1376  gl_->EnableVertexAttribArray(kAttribIndex1);
1377  gl_->EnableVertexAttribArray(kAttribIndex2);
1378  gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId);
1379  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1380                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1381  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1382                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1383  gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT,
1384                    reinterpret_cast<const void*>(kIndexOffset));
1385  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1386}
1387
1388TEST_F(GLES2ImplementationTest, DrawElementsInstancedANGLEClientSideBuffers) {
1389  static const float verts[][4] = {
1390    { 12.0f, 23.0f, 34.0f, 45.0f, },
1391    { 56.0f, 67.0f, 78.0f, 89.0f, },
1392    { 13.0f, 24.0f, 35.0f, 46.0f, },
1393  };
1394  static const uint16 indices[] = {
1395    1, 2,
1396  };
1397  struct Cmds {
1398    cmds::EnableVertexAttribArray enable1;
1399    cmds::EnableVertexAttribArray enable2;
1400    cmds::VertexAttribDivisorANGLE divisor;
1401    cmds::BindBuffer bind_to_index_emu;
1402    cmds::BufferData set_index_size;
1403    cmds::BufferSubData copy_data0;
1404    cmd::SetToken set_token0;
1405    cmds::BindBuffer bind_to_emu;
1406    cmds::BufferData set_size;
1407    cmds::BufferSubData copy_data1;
1408    cmd::SetToken set_token1;
1409    cmds::VertexAttribPointer set_pointer1;
1410    cmds::BufferSubData copy_data2;
1411    cmd::SetToken set_token2;
1412    cmds::VertexAttribPointer set_pointer2;
1413    cmds::DrawElementsInstancedANGLE draw;
1414    cmds::BindBuffer restore;
1415    cmds::BindBuffer restore_element;
1416  };
1417  const GLsizei kIndexSize = sizeof(indices);
1418  const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1419  const GLuint kEmuIndexBufferId =
1420      GLES2Implementation::kClientSideElementArrayId;
1421  const GLuint kAttribIndex1 = 1;
1422  const GLuint kAttribIndex2 = 3;
1423  const GLint kNumComponents1 = 3;
1424  const GLint kNumComponents2 = 2;
1425  const GLsizei kClientStride = sizeof(verts[0]);
1426  const GLsizei kCount = 2;
1427  const GLsizei kSize1 =
1428      arraysize(verts) * kNumComponents1 * sizeof(verts[0][0]);
1429  const GLsizei kSize2 =
1430      1 * kNumComponents2 * sizeof(verts[0][0]);
1431  const GLuint kDivisor = 1;
1432  const GLsizei kEmuOffset1 = 0;
1433  const GLsizei kEmuOffset2 = kSize1;
1434  const GLsizei kTotalSize = kSize1 + kSize2;
1435
1436  ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1437  ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1438  ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1439
1440  Cmds expected;
1441  expected.enable1.Init(kAttribIndex1);
1442  expected.enable2.Init(kAttribIndex2);
1443  expected.divisor.Init(kAttribIndex2, kDivisor);
1444  expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1445  expected.set_index_size.Init(
1446      GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1447  expected.copy_data0.Init(
1448      GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1449  expected.set_token0.Init(GetNextToken());
1450  expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1451  expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1452  expected.copy_data1.Init(
1453      GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1454  expected.set_token1.Init(GetNextToken());
1455  expected.set_pointer1.Init(
1456      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1457  expected.copy_data2.Init(
1458      GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1459  expected.set_token2.Init(GetNextToken());
1460  expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1461                             GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1462  expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0, 1);
1463  expected.restore.Init(GL_ARRAY_BUFFER, 0);
1464  expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1465  gl_->EnableVertexAttribArray(kAttribIndex1);
1466  gl_->EnableVertexAttribArray(kAttribIndex2);
1467  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1468                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1469  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1470                           GL_FLOAT, GL_FALSE, kClientStride, verts);
1471  gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor);
1472  gl_->DrawElementsInstancedANGLE(
1473      GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices, 1);
1474  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1475}
1476
1477TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) {
1478  static const float verts[1] = { 0.0f, };
1479  const GLuint kAttribIndex1 = 1;
1480  const GLuint kAttribIndex2 = 3;
1481  const GLint kNumComponents1 = 3;
1482  const GLint kNumComponents2 = 2;
1483  const GLsizei kStride1 = 12;
1484  const GLsizei kStride2 = 0;
1485  const GLuint kBufferId = 0x123;
1486  const GLint kOffset2 = 0x456;
1487
1488  // It's all cached on the client side so no get commands are issued.
1489  struct Cmds {
1490    cmds::BindBuffer bind;
1491    cmds::VertexAttribPointer set_pointer;
1492  };
1493
1494  Cmds expected;
1495  expected.bind.Init(GL_ARRAY_BUFFER, kBufferId);
1496  expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE,
1497                            kStride2, kOffset2);
1498
1499  // Set one client side buffer.
1500  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1501                           GL_FLOAT, GL_FALSE, kStride1, verts);
1502  // Set one VBO
1503  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
1504  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1505                           GL_FLOAT, GL_FALSE, kStride2,
1506                           reinterpret_cast<const void*>(kOffset2));
1507  // now get them both.
1508  void* ptr1 = NULL;
1509  void* ptr2 = NULL;
1510
1511  gl_->GetVertexAttribPointerv(
1512      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr1);
1513  gl_->GetVertexAttribPointerv(
1514      kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr2);
1515
1516  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1517  EXPECT_TRUE(static_cast<const void*>(&verts) == ptr1);
1518  EXPECT_TRUE(ptr2 == reinterpret_cast<void*>(kOffset2));
1519}
1520
1521TEST_F(GLES2ImplementationTest, GetVertexAttrib) {
1522  static const float verts[1] = { 0.0f, };
1523  const GLuint kAttribIndex1 = 1;
1524  const GLuint kAttribIndex2 = 3;
1525  const GLint kNumComponents1 = 3;
1526  const GLint kNumComponents2 = 2;
1527  const GLsizei kStride1 = 12;
1528  const GLsizei kStride2 = 0;
1529  const GLuint kBufferId = 0x123;
1530  const GLint kOffset2 = 0x456;
1531
1532  // Only one set and one get because the client side buffer's info is stored
1533  // on the client side.
1534  struct Cmds {
1535    cmds::EnableVertexAttribArray enable;
1536    cmds::BindBuffer bind;
1537    cmds::VertexAttribPointer set_pointer;
1538    cmds::GetVertexAttribfv get2;  // for getting the value from attrib1
1539  };
1540
1541  ExpectedMemoryInfo mem2 = GetExpectedResultMemory(16);
1542
1543  Cmds expected;
1544  expected.enable.Init(kAttribIndex1);
1545  expected.bind.Init(GL_ARRAY_BUFFER, kBufferId);
1546  expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE,
1547                            kStride2, kOffset2);
1548  expected.get2.Init(kAttribIndex1,
1549                     GL_CURRENT_VERTEX_ATTRIB,
1550                     mem2.id, mem2.offset);
1551
1552  FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f);
1553
1554  // One call to flush to wait for last call to GetVertexAttribiv
1555  // as others are all cached.
1556  EXPECT_CALL(*command_buffer(), OnFlush())
1557      .WillOnce(SetMemory(
1558          mem2.ptr, SizedResultHelper<FourFloats>(current_attrib)))
1559      .RetiresOnSaturation();
1560
1561  gl_->EnableVertexAttribArray(kAttribIndex1);
1562  // Set one client side buffer.
1563  gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1564                           GL_FLOAT, GL_FALSE, kStride1, verts);
1565  // Set one VBO
1566  gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
1567  gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1568                           GL_FLOAT, GL_FALSE, kStride2,
1569                           reinterpret_cast<const void*>(kOffset2));
1570  // first get the service side once to see that we make a command
1571  GLint buffer_id = 0;
1572  GLint enabled = 0;
1573  GLint size = 0;
1574  GLint stride = 0;
1575  GLint type = 0;
1576  GLint normalized = 1;
1577  float current[4] = { 0.0f, };
1578
1579  gl_->GetVertexAttribiv(
1580      kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id);
1581  EXPECT_EQ(kBufferId, static_cast<GLuint>(buffer_id));
1582  gl_->GetVertexAttribiv(
1583      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id);
1584  gl_->GetVertexAttribiv(
1585      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1586  gl_->GetVertexAttribiv(
1587      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size);
1588  gl_->GetVertexAttribiv(
1589      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride);
1590  gl_->GetVertexAttribiv(
1591      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type);
1592  gl_->GetVertexAttribiv(
1593      kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized);
1594  gl_->GetVertexAttribfv(
1595      kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, &current[0]);
1596
1597  EXPECT_EQ(0, buffer_id);
1598  EXPECT_EQ(GL_TRUE, enabled);
1599  EXPECT_EQ(kNumComponents1, size);
1600  EXPECT_EQ(kStride1, stride);
1601  EXPECT_EQ(GL_FLOAT, type);
1602  EXPECT_EQ(GL_FALSE, normalized);
1603  EXPECT_EQ(0, memcmp(&current_attrib, &current, sizeof(current_attrib)));
1604
1605  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1606}
1607
1608TEST_F(GLES2ImplementationTest, ReservedIds) {
1609  // Only the get error command should be issued.
1610  struct Cmds {
1611    cmds::GetError get;
1612  };
1613  Cmds expected;
1614
1615  ExpectedMemoryInfo mem1 = GetExpectedResultMemory(
1616      sizeof(cmds::GetError::Result));
1617
1618  expected.get.Init(mem1.id, mem1.offset);
1619
1620  // One call to flush to wait for GetError
1621  EXPECT_CALL(*command_buffer(), OnFlush())
1622      .WillOnce(SetMemory(mem1.ptr, GLuint(GL_NO_ERROR)))
1623      .RetiresOnSaturation();
1624
1625  gl_->BindBuffer(
1626      GL_ARRAY_BUFFER,
1627      GLES2Implementation::kClientSideArrayId);
1628  gl_->BindBuffer(
1629      GL_ARRAY_BUFFER,
1630      GLES2Implementation::kClientSideElementArrayId);
1631  GLenum err = gl_->GetError();
1632  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), err);
1633  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1634}
1635
1636#endif  // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1637
1638TEST_F(GLES2ImplementationTest, ReadPixels2Reads) {
1639  struct Cmds {
1640    cmds::ReadPixels read1;
1641    cmd::SetToken set_token1;
1642    cmds::ReadPixels read2;
1643    cmd::SetToken set_token2;
1644  };
1645  const GLint kBytesPerPixel = 4;
1646  const GLint kWidth =
1647      (kTransferBufferSize - GLES2Implementation::kStartingOffset) /
1648      kBytesPerPixel;
1649  const GLint kHeight = 2;
1650  const GLenum kFormat = GL_RGBA;
1651  const GLenum kType = GL_UNSIGNED_BYTE;
1652
1653  ExpectedMemoryInfo mem1 =
1654      GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel);
1655  ExpectedMemoryInfo result1 =
1656      GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1657  ExpectedMemoryInfo mem2 =
1658      GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel);
1659  ExpectedMemoryInfo result2 =
1660      GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1661
1662  Cmds expected;
1663  expected.read1.Init(
1664      0, 0, kWidth, kHeight / 2, kFormat, kType,
1665      mem1.id, mem1.offset, result1.id, result1.offset,
1666      false);
1667  expected.set_token1.Init(GetNextToken());
1668  expected.read2.Init(
1669      0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
1670      mem2.id, mem2.offset, result2.id, result2.offset, false);
1671  expected.set_token2.Init(GetNextToken());
1672  scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]);
1673
1674  EXPECT_CALL(*command_buffer(), OnFlush())
1675      .WillOnce(SetMemory(result1.ptr, static_cast<uint32>(1)))
1676      .WillOnce(SetMemory(result2.ptr, static_cast<uint32>(1)))
1677      .RetiresOnSaturation();
1678
1679  gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get());
1680  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1681}
1682
1683TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) {
1684  struct Cmds {
1685    cmds::ReadPixels read;
1686    cmd::SetToken set_token;
1687  };
1688  const GLint kBytesPerPixel = 4;
1689  const GLint kWidth = 2;
1690  const GLint kHeight = 2;
1691  const GLenum kFormat = 0;
1692  const GLenum kType = 0;
1693
1694  ExpectedMemoryInfo mem1 =
1695      GetExpectedMemory(kWidth * kHeight * kBytesPerPixel);
1696  ExpectedMemoryInfo result1 =
1697      GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1698
1699  Cmds expected;
1700  expected.read.Init(
1701      0, 0, kWidth, kHeight, kFormat, kType,
1702      mem1.id, mem1.offset, result1.id, result1.offset, false);
1703  expected.set_token.Init(GetNextToken());
1704  scoped_ptr<int8[]> buffer(new int8[kWidth * kHeight * kBytesPerPixel]);
1705
1706  EXPECT_CALL(*command_buffer(), OnFlush())
1707      .Times(1)
1708      .RetiresOnSaturation();
1709
1710  gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get());
1711}
1712
1713TEST_F(GLES2ImplementationTest, FreeUnusedSharedMemory) {
1714  struct Cmds {
1715    cmds::BufferSubData buf;
1716    cmd::SetToken set_token;
1717  };
1718  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1719  const GLintptr kOffset = 15;
1720  const GLsizeiptr kSize = 16;
1721
1722  ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize);
1723
1724  Cmds expected;
1725  expected.buf.Init(
1726    kTarget, kOffset, kSize, mem1.id, mem1.offset);
1727  expected.set_token.Init(GetNextToken());
1728
1729  void* mem = gl_->MapBufferSubDataCHROMIUM(
1730      kTarget, kOffset, kSize, GL_WRITE_ONLY);
1731  ASSERT_TRUE(mem != NULL);
1732  gl_->UnmapBufferSubDataCHROMIUM(mem);
1733  EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
1734      .Times(1)
1735      .RetiresOnSaturation();
1736  gl_->FreeUnusedSharedMemory();
1737}
1738
1739TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUM) {
1740  struct Cmds {
1741    cmds::BufferSubData buf;
1742    cmd::SetToken set_token;
1743  };
1744  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1745  const GLintptr kOffset = 15;
1746  const GLsizeiptr kSize = 16;
1747
1748  uint32 offset = 0;
1749  Cmds expected;
1750  expected.buf.Init(
1751      kTarget, kOffset, kSize,
1752      command_buffer()->GetNextFreeTransferBufferId(), offset);
1753  expected.set_token.Init(GetNextToken());
1754
1755  void* mem = gl_->MapBufferSubDataCHROMIUM(
1756      kTarget, kOffset, kSize, GL_WRITE_ONLY);
1757  ASSERT_TRUE(mem != NULL);
1758  gl_->UnmapBufferSubDataCHROMIUM(mem);
1759  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1760}
1761
1762TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUMBadArgs) {
1763  const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1764  const GLintptr kOffset = 15;
1765  const GLsizeiptr kSize = 16;
1766
1767  ExpectedMemoryInfo result1 =
1768      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1769  ExpectedMemoryInfo result2 =
1770      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1771  ExpectedMemoryInfo result3 =
1772      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1773  ExpectedMemoryInfo result4 =
1774      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1775
1776  // Calls to flush to wait for GetError
1777  EXPECT_CALL(*command_buffer(), OnFlush())
1778      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1779      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1780      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1781      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1782      .RetiresOnSaturation();
1783
1784  void* mem;
1785  mem = gl_->MapBufferSubDataCHROMIUM(kTarget, -1, kSize, GL_WRITE_ONLY);
1786  ASSERT_TRUE(mem == NULL);
1787  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1788  mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, -1, GL_WRITE_ONLY);
1789  ASSERT_TRUE(mem == NULL);
1790  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1791  mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, kSize, GL_READ_ONLY);
1792  ASSERT_TRUE(mem == NULL);
1793  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
1794  const char* kPtr = "something";
1795  gl_->UnmapBufferSubDataCHROMIUM(kPtr);
1796  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1797}
1798
1799TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUM) {
1800  struct Cmds {
1801    cmds::TexSubImage2D tex;
1802    cmd::SetToken set_token;
1803  };
1804  const GLint kLevel = 1;
1805  const GLint kXOffset = 2;
1806  const GLint kYOffset = 3;
1807  const GLint kWidth = 4;
1808  const GLint kHeight = 5;
1809  const GLenum kFormat = GL_RGBA;
1810  const GLenum kType = GL_UNSIGNED_BYTE;
1811
1812  uint32 offset = 0;
1813  Cmds expected;
1814  expected.tex.Init(
1815      GL_TEXTURE_2D, kLevel, kXOffset, kYOffset, kWidth, kHeight, kFormat,
1816      kType,
1817      command_buffer()->GetNextFreeTransferBufferId(), offset, GL_FALSE);
1818  expected.set_token.Init(GetNextToken());
1819
1820  void* mem = gl_->MapTexSubImage2DCHROMIUM(
1821      GL_TEXTURE_2D,
1822      kLevel,
1823      kXOffset,
1824      kYOffset,
1825      kWidth,
1826      kHeight,
1827      kFormat,
1828      kType,
1829      GL_WRITE_ONLY);
1830  ASSERT_TRUE(mem != NULL);
1831  gl_->UnmapTexSubImage2DCHROMIUM(mem);
1832  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1833}
1834
1835TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUMBadArgs) {
1836  const GLint kLevel = 1;
1837  const GLint kXOffset = 2;
1838  const GLint kYOffset = 3;
1839  const GLint kWidth = 4;
1840  const GLint kHeight = 5;
1841  const GLenum kFormat = GL_RGBA;
1842  const GLenum kType = GL_UNSIGNED_BYTE;
1843
1844  ExpectedMemoryInfo result1 =
1845      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1846  ExpectedMemoryInfo result2 =
1847      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1848  ExpectedMemoryInfo result3 =
1849      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1850  ExpectedMemoryInfo result4 =
1851      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1852  ExpectedMemoryInfo result5 =
1853      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1854  ExpectedMemoryInfo result6 =
1855      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1856  ExpectedMemoryInfo result7 =
1857      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1858
1859  // Calls to flush to wait for GetError
1860  EXPECT_CALL(*command_buffer(), OnFlush())
1861      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1862      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1863      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1864      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1865      .WillOnce(SetMemory(result5.ptr, GLuint(GL_NO_ERROR)))
1866      .WillOnce(SetMemory(result6.ptr, GLuint(GL_NO_ERROR)))
1867      .WillOnce(SetMemory(result7.ptr, GLuint(GL_NO_ERROR)))
1868      .RetiresOnSaturation();
1869
1870  void* mem;
1871  mem = gl_->MapTexSubImage2DCHROMIUM(
1872    GL_TEXTURE_2D,
1873    -1,
1874    kXOffset,
1875    kYOffset,
1876    kWidth,
1877    kHeight,
1878    kFormat,
1879    kType,
1880    GL_WRITE_ONLY);
1881  EXPECT_TRUE(mem == NULL);
1882  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1883  mem = gl_->MapTexSubImage2DCHROMIUM(
1884    GL_TEXTURE_2D,
1885    kLevel,
1886    -1,
1887    kYOffset,
1888    kWidth,
1889    kHeight,
1890    kFormat,
1891    kType,
1892    GL_WRITE_ONLY);
1893  EXPECT_TRUE(mem == NULL);
1894  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1895  mem = gl_->MapTexSubImage2DCHROMIUM(
1896    GL_TEXTURE_2D,
1897    kLevel,
1898    kXOffset,
1899    -1,
1900    kWidth,
1901    kHeight,
1902    kFormat,
1903    kType,
1904    GL_WRITE_ONLY);
1905  EXPECT_TRUE(mem == NULL);
1906  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1907  mem = gl_->MapTexSubImage2DCHROMIUM(
1908    GL_TEXTURE_2D,
1909    kLevel,
1910    kXOffset,
1911    kYOffset,
1912    -1,
1913    kHeight,
1914    kFormat,
1915    kType,
1916    GL_WRITE_ONLY);
1917  EXPECT_TRUE(mem == NULL);
1918  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1919  mem = gl_->MapTexSubImage2DCHROMIUM(
1920    GL_TEXTURE_2D,
1921    kLevel,
1922    kXOffset,
1923    kYOffset,
1924    kWidth,
1925    -1,
1926    kFormat,
1927    kType,
1928    GL_WRITE_ONLY);
1929  EXPECT_TRUE(mem == NULL);
1930  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1931  mem = gl_->MapTexSubImage2DCHROMIUM(
1932    GL_TEXTURE_2D,
1933    kLevel,
1934    kXOffset,
1935    kYOffset,
1936    kWidth,
1937    kHeight,
1938    kFormat,
1939    kType,
1940    GL_READ_ONLY);
1941  EXPECT_TRUE(mem == NULL);
1942  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
1943  const char* kPtr = "something";
1944  gl_->UnmapTexSubImage2DCHROMIUM(kPtr);
1945  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1946}
1947
1948TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMValidArgs) {
1949  const GLenum pnames[] = {
1950    GL_DEPTH_WRITEMASK,
1951    GL_COLOR_WRITEMASK,
1952    GL_STENCIL_WRITEMASK,
1953  };
1954  const GLint num_results = 6;
1955  GLint results[num_results + 1];
1956  struct Cmds {
1957    cmds::GetMultipleIntegervCHROMIUM get_multiple;
1958    cmd::SetToken set_token;
1959  };
1960  const GLsizei kNumPnames = arraysize(pnames);
1961  const GLsizeiptr kResultsSize = num_results * sizeof(results[0]);
1962  const size_t kPNamesSize = kNumPnames * sizeof(pnames[0]);
1963
1964  ExpectedMemoryInfo mem1 = GetExpectedMemory(kPNamesSize + kResultsSize);
1965  ExpectedMemoryInfo result1 = GetExpectedResultMemory(
1966      sizeof(cmds::GetError::Result));
1967
1968  const uint32 kPnamesOffset = mem1.offset;
1969  const uint32 kResultsOffset = mem1.offset + kPNamesSize;
1970  Cmds expected;
1971  expected.get_multiple.Init(
1972      mem1.id, kPnamesOffset, kNumPnames,
1973      mem1.id, kResultsOffset, kResultsSize);
1974  expected.set_token.Init(GetNextToken());
1975
1976  const GLint kSentinel = 0x12345678;
1977  memset(results, 0, sizeof(results));
1978  results[num_results] = kSentinel;
1979  const GLint returned_results[] = {
1980    1, 0, 1, 0, 1, -1,
1981  };
1982  // One call to flush to wait for results
1983  EXPECT_CALL(*command_buffer(), OnFlush())
1984      .WillOnce(SetMemoryFromArray(mem1.ptr + kPNamesSize,
1985                                   returned_results, sizeof(returned_results)))
1986      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1987      .RetiresOnSaturation();
1988
1989  gl_->GetMultipleIntegervCHROMIUM(
1990      &pnames[0], kNumPnames, &results[0], kResultsSize);
1991  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1992  EXPECT_EQ(0, memcmp(&returned_results, results, sizeof(returned_results)));
1993  EXPECT_EQ(kSentinel, results[num_results]);
1994  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
1995}
1996
1997TEST_F(GLES2ImplementationTest, GetMultipleIntegervCHROMIUMBadArgs) {
1998  GLenum pnames[] = {
1999    GL_DEPTH_WRITEMASK,
2000    GL_COLOR_WRITEMASK,
2001    GL_STENCIL_WRITEMASK,
2002  };
2003  const GLint num_results = 6;
2004  GLint results[num_results + 1];
2005  const GLsizei kNumPnames = arraysize(pnames);
2006  const GLsizeiptr kResultsSize = num_results * sizeof(results[0]);
2007
2008  ExpectedMemoryInfo result1 =
2009      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2010  ExpectedMemoryInfo result2 =
2011      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2012  ExpectedMemoryInfo result3 =
2013      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2014  ExpectedMemoryInfo result4 =
2015      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2016
2017  // Calls to flush to wait for GetError
2018  EXPECT_CALL(*command_buffer(), OnFlush())
2019      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2020      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
2021      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
2022      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
2023      .RetiresOnSaturation();
2024
2025  const GLint kSentinel = 0x12345678;
2026  memset(results, 0, sizeof(results));
2027  results[num_results] = kSentinel;
2028  // try bad size.
2029  gl_->GetMultipleIntegervCHROMIUM(
2030      &pnames[0], kNumPnames, &results[0], kResultsSize + 1);
2031  EXPECT_TRUE(NoCommandsWritten());
2032  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2033  EXPECT_EQ(0, results[0]);
2034  EXPECT_EQ(kSentinel, results[num_results]);
2035  // try bad size.
2036  ClearCommands();
2037  gl_->GetMultipleIntegervCHROMIUM(
2038      &pnames[0], kNumPnames, &results[0], kResultsSize - 1);
2039  EXPECT_TRUE(NoCommandsWritten());
2040  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2041  EXPECT_EQ(0, results[0]);
2042  EXPECT_EQ(kSentinel, results[num_results]);
2043  // try uncleared results.
2044  ClearCommands();
2045  results[2] = 1;
2046  gl_->GetMultipleIntegervCHROMIUM(
2047      &pnames[0], kNumPnames, &results[0], kResultsSize);
2048  EXPECT_TRUE(NoCommandsWritten());
2049  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2050  EXPECT_EQ(0, results[0]);
2051  EXPECT_EQ(kSentinel, results[num_results]);
2052  // try bad enum results.
2053  ClearCommands();
2054  results[2] = 0;
2055  pnames[1] = GL_TRUE;
2056  gl_->GetMultipleIntegervCHROMIUM(
2057      &pnames[0], kNumPnames, &results[0], kResultsSize);
2058  EXPECT_TRUE(NoCommandsWritten());
2059  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
2060  EXPECT_EQ(0, results[0]);
2061  EXPECT_EQ(kSentinel, results[num_results]);
2062}
2063
2064TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMGoodArgs) {
2065  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2066  const GLuint kProgramId = 123;
2067  const char kBad = 0x12;
2068  GLsizei size = 0;
2069  const Str7 kString = {"foobar"};
2070  char buf[20];
2071
2072  ExpectedMemoryInfo mem1 =
2073      GetExpectedMemory(MaxTransferBufferSize());
2074  ExpectedMemoryInfo result1 =
2075      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2076  ExpectedMemoryInfo result2 =
2077      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2078
2079  memset(buf, kBad, sizeof(buf));
2080  EXPECT_CALL(*command_buffer(), OnFlush())
2081      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2082                      SetMemory(mem1.ptr, kString)))
2083      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
2084      .RetiresOnSaturation();
2085
2086  struct Cmds {
2087    cmd::SetBucketSize set_bucket_size1;
2088    cmds::GetProgramInfoCHROMIUM get_program_info;
2089    cmd::GetBucketStart get_bucket_start;
2090    cmd::SetToken set_token1;
2091    cmd::SetBucketSize set_bucket_size2;
2092  };
2093  Cmds expected;
2094  expected.set_bucket_size1.Init(kBucketId, 0);
2095  expected.get_program_info.Init(kProgramId, kBucketId);
2096  expected.get_bucket_start.Init(
2097      kBucketId, result1.id, result1.offset,
2098      MaxTransferBufferSize(), mem1.id, mem1.offset);
2099  expected.set_token1.Init(GetNextToken());
2100  expected.set_bucket_size2.Init(kBucketId, 0);
2101  gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), &size, &buf);
2102  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2103  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2104  EXPECT_EQ(sizeof(kString), static_cast<size_t>(size));
2105  EXPECT_STREQ(kString.str, buf);
2106  EXPECT_EQ(buf[sizeof(kString)], kBad);
2107}
2108
2109TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) {
2110  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2111  const GLuint kProgramId = 123;
2112  GLsizei size = 0;
2113  const Str7 kString = {"foobar"};
2114  char buf[20];
2115
2116  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
2117  ExpectedMemoryInfo result1 =
2118      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2119  ExpectedMemoryInfo result2 =
2120      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2121  ExpectedMemoryInfo result3 =
2122      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2123  ExpectedMemoryInfo result4 =
2124      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2125
2126  EXPECT_CALL(*command_buffer(), OnFlush())
2127      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2128                      SetMemory(mem1.ptr,  kString)))
2129      .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
2130      .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
2131      .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
2132      .RetiresOnSaturation();
2133
2134  // try bufsize not big enough.
2135  struct Cmds {
2136    cmd::SetBucketSize set_bucket_size1;
2137    cmds::GetProgramInfoCHROMIUM get_program_info;
2138    cmd::GetBucketStart get_bucket_start;
2139    cmd::SetToken set_token1;
2140    cmd::SetBucketSize set_bucket_size2;
2141  };
2142  Cmds expected;
2143  expected.set_bucket_size1.Init(kBucketId, 0);
2144  expected.get_program_info.Init(kProgramId, kBucketId);
2145  expected.get_bucket_start.Init(
2146      kBucketId, result1.id, result1.offset,
2147      MaxTransferBufferSize(), mem1.id, mem1.offset);
2148  expected.set_token1.Init(GetNextToken());
2149  expected.set_bucket_size2.Init(kBucketId, 0);
2150  gl_->GetProgramInfoCHROMIUM(kProgramId, 6, &size, &buf);
2151  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2152  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
2153  ClearCommands();
2154
2155  // try bad bufsize
2156  gl_->GetProgramInfoCHROMIUM(kProgramId, -1, &size, &buf);
2157  EXPECT_TRUE(NoCommandsWritten());
2158  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2159  ClearCommands();
2160  // try no size ptr.
2161  gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), NULL, &buf);
2162  EXPECT_TRUE(NoCommandsWritten());
2163  EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2164}
2165
2166// Test that things are cached
2167TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) {
2168  struct PNameValue {
2169    GLenum pname;
2170    GLint expected;
2171  };
2172  const PNameValue pairs[] = {
2173      {GL_ACTIVE_TEXTURE, GL_TEXTURE0, },
2174      {GL_TEXTURE_BINDING_2D, 0, },
2175      {GL_TEXTURE_BINDING_CUBE_MAP, 0, },
2176      {GL_TEXTURE_BINDING_EXTERNAL_OES, 0, },
2177      {GL_FRAMEBUFFER_BINDING, 0, },
2178      {GL_RENDERBUFFER_BINDING, 0, },
2179      {GL_ARRAY_BUFFER_BINDING, 0, },
2180      {GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, },
2181      {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kMaxCombinedTextureImageUnits, },
2182      {GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMaxCubeMapTextureSize, },
2183      {GL_MAX_FRAGMENT_UNIFORM_VECTORS, kMaxFragmentUniformVectors, },
2184      {GL_MAX_RENDERBUFFER_SIZE, kMaxRenderbufferSize, },
2185      {GL_MAX_TEXTURE_IMAGE_UNITS, kMaxTextureImageUnits, },
2186      {GL_MAX_TEXTURE_SIZE, kMaxTextureSize, },
2187      {GL_MAX_VARYING_VECTORS, kMaxVaryingVectors, },
2188      {GL_MAX_VERTEX_ATTRIBS, kMaxVertexAttribs, },
2189      {GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMaxVertexTextureImageUnits, },
2190      {GL_MAX_VERTEX_UNIFORM_VECTORS, kMaxVertexUniformVectors, },
2191      {GL_NUM_COMPRESSED_TEXTURE_FORMATS, kNumCompressedTextureFormats, },
2192      {GL_NUM_SHADER_BINARY_FORMATS, kNumShaderBinaryFormats, }, };
2193  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2194  for (size_t ii = 0; ii < num_pairs; ++ii) {
2195    const PNameValue& pv = pairs[ii];
2196    GLint v = -1;
2197    gl_->GetIntegerv(pv.pname, &v);
2198    EXPECT_TRUE(NoCommandsWritten());
2199    EXPECT_EQ(pv.expected, v);
2200  }
2201
2202  ExpectedMemoryInfo result1 =
2203      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2204
2205  EXPECT_CALL(*command_buffer(), OnFlush())
2206      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2207      .RetiresOnSaturation();
2208  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2209}
2210
2211TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) {
2212  struct PNameValue {
2213    GLenum pname;
2214    GLint expected;
2215  };
2216  gl_->ActiveTexture(GL_TEXTURE4);
2217  gl_->BindBuffer(GL_ARRAY_BUFFER, 2);
2218  gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 3);
2219  gl_->BindFramebuffer(GL_FRAMEBUFFER, 4);
2220  gl_->BindRenderbuffer(GL_RENDERBUFFER, 5);
2221  gl_->BindTexture(GL_TEXTURE_2D, 6);
2222  gl_->BindTexture(GL_TEXTURE_CUBE_MAP, 7);
2223  gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, 8);
2224
2225  const PNameValue pairs[] = {{GL_ACTIVE_TEXTURE, GL_TEXTURE4, },
2226                              {GL_ARRAY_BUFFER_BINDING, 2, },
2227                              {GL_ELEMENT_ARRAY_BUFFER_BINDING, 3, },
2228                              {GL_FRAMEBUFFER_BINDING, 4, },
2229                              {GL_RENDERBUFFER_BINDING, 5, },
2230                              {GL_TEXTURE_BINDING_2D, 6, },
2231                              {GL_TEXTURE_BINDING_CUBE_MAP, 7, },
2232                              {GL_TEXTURE_BINDING_EXTERNAL_OES, 8, }, };
2233  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2234  for (size_t ii = 0; ii < num_pairs; ++ii) {
2235    const PNameValue& pv = pairs[ii];
2236    GLint v = -1;
2237    gl_->GetIntegerv(pv.pname, &v);
2238    EXPECT_EQ(pv.expected, v);
2239  }
2240
2241  ExpectedMemoryInfo result1 =
2242      GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2243
2244  EXPECT_CALL(*command_buffer(), OnFlush())
2245      .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2246      .RetiresOnSaturation();
2247  EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2248}
2249
2250static bool CheckRect(
2251    int width, int height, GLenum format, GLenum type, int alignment,
2252    bool flip_y, const uint8* r1, const uint8* r2) {
2253  uint32 size = 0;
2254  uint32 unpadded_row_size = 0;
2255  uint32 padded_row_size = 0;
2256  if (!GLES2Util::ComputeImageDataSizes(
2257      width, height, format, type, alignment, &size, &unpadded_row_size,
2258      &padded_row_size)) {
2259    return false;
2260  }
2261
2262  int r2_stride = flip_y ?
2263      -static_cast<int>(padded_row_size) :
2264      static_cast<int>(padded_row_size);
2265  r2 = flip_y ? (r2 + (height - 1) * padded_row_size) : r2;
2266
2267  for (int y = 0; y < height; ++y) {
2268    if (memcmp(r1, r2, unpadded_row_size) != 0) {
2269      return false;
2270    }
2271    r1 += padded_row_size;
2272    r2 += r2_stride;
2273  }
2274  return true;
2275}
2276
2277ACTION_P8(CheckRectAction, width, height, format, type, alignment, flip_y,
2278          r1, r2) {
2279  EXPECT_TRUE(CheckRect(
2280      width, height, format, type, alignment, flip_y, r1, r2));
2281}
2282
2283// Test TexImage2D with and without flip_y
2284TEST_F(GLES2ImplementationTest, TexImage2D) {
2285  struct Cmds {
2286    cmds::TexImage2D tex_image_2d;
2287    cmd::SetToken set_token;
2288  };
2289  struct Cmds2 {
2290    cmds::TexImage2D tex_image_2d;
2291    cmd::SetToken set_token;
2292  };
2293  const GLenum kTarget = GL_TEXTURE_2D;
2294  const GLint kLevel = 0;
2295  const GLenum kFormat = GL_RGB;
2296  const GLsizei kWidth = 3;
2297  const GLsizei kHeight = 4;
2298  const GLint kBorder = 0;
2299  const GLenum kType = GL_UNSIGNED_BYTE;
2300  const GLint kPixelStoreUnpackAlignment = 4;
2301  static uint8 pixels[] = {
2302    11, 12, 13, 13, 14, 15, 15, 16, 17, 101, 102, 103,
2303    21, 22, 23, 23, 24, 25, 25, 26, 27, 201, 202, 203,
2304    31, 32, 33, 33, 34, 35, 35, 36, 37, 123, 124, 125,
2305    41, 42, 43, 43, 44, 45, 45, 46, 47,
2306  };
2307
2308  ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels));
2309
2310  Cmds expected;
2311  expected.tex_image_2d.Init(
2312      kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2313      mem1.id, mem1.offset);
2314  expected.set_token.Init(GetNextToken());
2315  gl_->TexImage2D(
2316      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2317      pixels);
2318  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2319  EXPECT_TRUE(CheckRect(
2320      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false,
2321      pixels, mem1.ptr));
2322
2323  ClearCommands();
2324  gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2325
2326  ExpectedMemoryInfo mem2 = GetExpectedMemory(sizeof(pixels));
2327  Cmds2 expected2;
2328  expected2.tex_image_2d.Init(
2329      kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2330      mem2.id, mem2.offset);
2331  expected2.set_token.Init(GetNextToken());
2332  const void* commands2 = GetPut();
2333  gl_->TexImage2D(
2334      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2335      pixels);
2336  EXPECT_EQ(0, memcmp(&expected2, commands2, sizeof(expected2)));
2337  EXPECT_TRUE(CheckRect(
2338      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, true,
2339      pixels, mem2.ptr));
2340}
2341
2342// Test TexImage2D with 2 writes
2343TEST_F(GLES2ImplementationTest, TexImage2D2Writes) {
2344  struct Cmds {
2345    cmds::TexImage2D tex_image_2d;
2346    cmds::TexSubImage2D tex_sub_image_2d1;
2347    cmd::SetToken set_token1;
2348    cmds::TexSubImage2D tex_sub_image_2d2;
2349    cmd::SetToken set_token2;
2350  };
2351  const GLenum kTarget = GL_TEXTURE_2D;
2352  const GLint kLevel = 0;
2353  const GLenum kFormat = GL_RGB;
2354  const GLint kBorder = 0;
2355  const GLenum kType = GL_UNSIGNED_BYTE;
2356  const GLint kPixelStoreUnpackAlignment = 4;
2357  const GLsizei kWidth = 3;
2358
2359  uint32 size = 0;
2360  uint32 unpadded_row_size = 0;
2361  uint32 padded_row_size = 0;
2362  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2363      kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment,
2364      &size, &unpadded_row_size, &padded_row_size));
2365  const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2;
2366  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2367      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment,
2368      &size, NULL, NULL));
2369  uint32 half_size = 0;
2370  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2371      kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2372      &half_size, NULL, NULL));
2373
2374  scoped_ptr<uint8[]> pixels(new uint8[size]);
2375  for (uint32 ii = 0; ii < size; ++ii) {
2376    pixels[ii] = static_cast<uint8>(ii);
2377  }
2378
2379  ExpectedMemoryInfo mem1 = GetExpectedMemory(half_size);
2380  ExpectedMemoryInfo mem2 = GetExpectedMemory(half_size);
2381
2382  Cmds expected;
2383  expected.tex_image_2d.Init(
2384      kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2385      0, 0);
2386  expected.tex_sub_image_2d1.Init(
2387      kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType,
2388      mem1.id, mem1.offset, true);
2389  expected.set_token1.Init(GetNextToken());
2390  expected.tex_sub_image_2d2.Init(
2391      kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
2392      mem2.id, mem2.offset, true);
2393  expected.set_token2.Init(GetNextToken());
2394
2395  // TODO(gman): Make it possible to run this test
2396  // EXPECT_CALL(*command_buffer(), OnFlush())
2397  //     .WillOnce(CheckRectAction(
2398  //         kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2399  //         false, pixels.get(),
2400  //         GetExpectedTransferAddressFromOffsetAs<uint8>(offset1, half_size)))
2401  //     .RetiresOnSaturation();
2402
2403  gl_->TexImage2D(
2404      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2405      pixels.get());
2406  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2407  EXPECT_TRUE(CheckRect(
2408      kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, false,
2409      pixels.get() + kHeight / 2 * padded_row_size, mem2.ptr));
2410
2411  ClearCommands();
2412  gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2413  const void* commands2 = GetPut();
2414  ExpectedMemoryInfo mem3 = GetExpectedMemory(half_size);
2415  ExpectedMemoryInfo mem4 = GetExpectedMemory(half_size);
2416  expected.tex_image_2d.Init(
2417      kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2418      0, 0);
2419  expected.tex_sub_image_2d1.Init(
2420      kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
2421      mem3.id, mem3.offset, true);
2422  expected.set_token1.Init(GetNextToken());
2423  expected.tex_sub_image_2d2.Init(
2424      kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType,
2425      mem4.id, mem4.offset, true);
2426  expected.set_token2.Init(GetNextToken());
2427
2428  // TODO(gman): Make it possible to run this test
2429  // EXPECT_CALL(*command_buffer(), OnFlush())
2430  //     .WillOnce(CheckRectAction(
2431  //         kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2432  //         true, pixels.get(),
2433  //         GetExpectedTransferAddressFromOffsetAs<uint8>(offset3, half_size)))
2434  //     .RetiresOnSaturation();
2435
2436  gl_->TexImage2D(
2437      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2438      pixels.get());
2439  EXPECT_EQ(0, memcmp(&expected, commands2, sizeof(expected)));
2440  EXPECT_TRUE(CheckRect(
2441      kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment, true,
2442      pixels.get() + kHeight / 2 * padded_row_size, mem4.ptr));
2443}
2444
2445// Test TexSubImage2D with GL_PACK_FLIP_Y set and partial multirow transfers
2446TEST_F(GLES2ImplementationTest, TexSubImage2DFlipY) {
2447  const GLsizei kTextureWidth = MaxTransferBufferSize() / 4;
2448  const GLsizei kTextureHeight = 7;
2449  const GLsizei kSubImageWidth = MaxTransferBufferSize() / 8;
2450  const GLsizei kSubImageHeight = 4;
2451  const GLint kSubImageXOffset = 1;
2452  const GLint kSubImageYOffset = 2;
2453  const GLenum kFormat = GL_RGBA;
2454  const GLenum kType = GL_UNSIGNED_BYTE;
2455  const GLenum kTarget = GL_TEXTURE_2D;
2456  const GLint kLevel = 0;
2457  const GLint kBorder = 0;
2458  const GLint kPixelStoreUnpackAlignment = 4;
2459
2460  struct Cmds {
2461    cmds::PixelStorei pixel_store_i1;
2462    cmds::TexImage2D tex_image_2d;
2463    cmds::PixelStorei pixel_store_i2;
2464    cmds::TexSubImage2D tex_sub_image_2d1;
2465    cmd::SetToken set_token1;
2466    cmds::TexSubImage2D tex_sub_image_2d2;
2467    cmd::SetToken set_token2;
2468  };
2469
2470  uint32 sub_2_high_size = 0;
2471  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2472      kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment,
2473      &sub_2_high_size, NULL, NULL));
2474
2475  ExpectedMemoryInfo mem1 = GetExpectedMemory(sub_2_high_size);
2476  ExpectedMemoryInfo mem2 = GetExpectedMemory(sub_2_high_size);
2477
2478  Cmds expected;
2479  expected.pixel_store_i1.Init(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment);
2480  expected.tex_image_2d.Init(
2481      kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kFormat,
2482      kType, 0, 0);
2483  expected.pixel_store_i2.Init(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2484  expected.tex_sub_image_2d1.Init(kTarget, kLevel, kSubImageXOffset,
2485      kSubImageYOffset + 2, kSubImageWidth, 2, kFormat, kType,
2486      mem1.id, mem1.offset, false);
2487  expected.set_token1.Init(GetNextToken());
2488  expected.tex_sub_image_2d2.Init(kTarget, kLevel, kSubImageXOffset,
2489      kSubImageYOffset, kSubImageWidth , 2, kFormat, kType,
2490      mem2.id, mem2.offset, false);
2491  expected.set_token2.Init(GetNextToken());
2492
2493  gl_->PixelStorei(GL_UNPACK_ALIGNMENT, kPixelStoreUnpackAlignment);
2494  gl_->TexImage2D(
2495      kTarget, kLevel, kFormat, kTextureWidth, kTextureHeight, kBorder, kFormat,
2496      kType, NULL);
2497  gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, GL_TRUE);
2498  scoped_ptr<uint32[]> pixels(new uint32[kSubImageWidth * kSubImageHeight]);
2499  for (int y = 0; y < kSubImageHeight; ++y) {
2500    for (int x = 0; x < kSubImageWidth; ++x) {
2501      pixels.get()[kSubImageWidth * y + x] = x | (y << 16);
2502    }
2503  }
2504  gl_->TexSubImage2D(
2505      GL_TEXTURE_2D, 0, kSubImageXOffset, kSubImageYOffset, kSubImageWidth,
2506      kSubImageHeight, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
2507
2508  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2509  EXPECT_TRUE(CheckRect(
2510      kSubImageWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment, true,
2511      reinterpret_cast<uint8*>(pixels.get() + 2 * kSubImageWidth),
2512      mem2.ptr));
2513}
2514
2515TEST_F(GLES2ImplementationTest, SubImageUnpack) {
2516  static const GLint unpack_alignments[] = { 1, 2, 4, 8 };
2517
2518  static const GLenum kFormat = GL_RGB;
2519  static const GLenum kType = GL_UNSIGNED_BYTE;
2520  static const GLint kLevel = 0;
2521  static const GLint kBorder = 0;
2522  // We're testing using the unpack params to pull a subimage out of a larger
2523  // source of pixels. Here we specify the subimage by its border rows /
2524  // columns.
2525  static const GLint kSrcWidth = 33;
2526  static const GLint kSrcSubImageX0 = 11;
2527  static const GLint kSrcSubImageX1 = 20;
2528  static const GLint kSrcSubImageY0 = 18;
2529  static const GLint kSrcSubImageY1 = 23;
2530  static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0;
2531  static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0;
2532
2533  // these are only used in the texsubimage tests
2534  static const GLint kTexWidth = 1023;
2535  static const GLint kTexHeight = 511;
2536  static const GLint kTexSubXOffset = 419;
2537  static const GLint kTexSubYOffset = 103;
2538
2539  struct {
2540    cmds::PixelStorei pixel_store_i;
2541    cmds::PixelStorei pixel_store_i2;
2542    cmds::TexImage2D tex_image_2d;
2543  } texImageExpected;
2544
2545  struct  {
2546    cmds::PixelStorei pixel_store_i;
2547    cmds::PixelStorei pixel_store_i2;
2548    cmds::TexImage2D tex_image_2d;
2549    cmds::TexSubImage2D tex_sub_image_2d;
2550  } texSubImageExpected;
2551
2552  uint32 src_size;
2553  ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2554      kSrcWidth, kSrcSubImageY1, kFormat, kType, 8, &src_size, NULL, NULL));
2555  scoped_ptr<uint8[]> src_pixels;
2556  src_pixels.reset(new uint8[src_size]);
2557  for (size_t i = 0; i < src_size; ++i) {
2558    src_pixels[i] = static_cast<int8>(i);
2559  }
2560
2561  for (int sub = 0; sub < 2; ++sub) {
2562    for (int flip_y = 0; flip_y < 2; ++flip_y) {
2563      for (size_t a = 0; a < arraysize(unpack_alignments); ++a) {
2564        GLint alignment = unpack_alignments[a];
2565        uint32 size;
2566        uint32 unpadded_row_size;
2567        uint32 padded_row_size;
2568        ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2569            kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, alignment,
2570            &size, &unpadded_row_size, &padded_row_size));
2571        ASSERT_TRUE(size <= MaxTransferBufferSize());
2572        ExpectedMemoryInfo mem = GetExpectedMemory(size);
2573
2574        const void* commands = GetPut();
2575        gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment);
2576        gl_->PixelStorei(GL_UNPACK_ROW_LENGTH_EXT, kSrcWidth);
2577        gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, kSrcSubImageX0);
2578        gl_->PixelStorei(GL_UNPACK_SKIP_ROWS_EXT, kSrcSubImageY0);
2579        gl_->PixelStorei(GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
2580        if (sub) {
2581          gl_->TexImage2D(
2582              GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder,
2583              kFormat, kType, NULL);
2584          gl_->TexSubImage2D(
2585              GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset,
2586              kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType,
2587              src_pixels.get());
2588          texSubImageExpected.pixel_store_i.Init(
2589              GL_UNPACK_ALIGNMENT, alignment);
2590          texSubImageExpected.pixel_store_i2.Init(
2591              GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
2592          texSubImageExpected.tex_image_2d.Init(
2593              GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight,
2594              kFormat, kType, 0, 0);
2595          texSubImageExpected.tex_sub_image_2d.Init(
2596              GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset,
2597              kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id,
2598              mem.offset, GL_FALSE);
2599          EXPECT_EQ(0, memcmp(
2600              &texSubImageExpected, commands, sizeof(texSubImageExpected)));
2601        } else {
2602          gl_->TexImage2D(
2603              GL_TEXTURE_2D, kLevel, kFormat,
2604              kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType,
2605              src_pixels.get());
2606          texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment);
2607          texImageExpected.pixel_store_i2.Init(
2608              GL_UNPACK_FLIP_Y_CHROMIUM, flip_y);
2609          texImageExpected.tex_image_2d.Init(
2610              GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth,
2611              kSrcSubImageHeight, kFormat, kType, mem.id, mem.offset);
2612          EXPECT_EQ(0, memcmp(
2613              &texImageExpected, commands, sizeof(texImageExpected)));
2614        }
2615        uint32 src_padded_row_size;
2616        ASSERT_TRUE(GLES2Util::ComputeImagePaddedRowSize(
2617            kSrcWidth, kFormat, kType, alignment, &src_padded_row_size));
2618        uint32 bytes_per_group = GLES2Util::ComputeImageGroupSize(
2619            kFormat, kType);
2620        for (int y = 0; y < kSrcSubImageHeight; ++y) {
2621          GLint src_sub_y = flip_y ? kSrcSubImageHeight - y - 1 : y;
2622          const uint8* src_row = src_pixels.get() +
2623              (kSrcSubImageY0 + src_sub_y) * src_padded_row_size +
2624              bytes_per_group * kSrcSubImageX0;
2625          const uint8* dst_row = mem.ptr + y * padded_row_size;
2626          EXPECT_EQ(0, memcmp(src_row, dst_row, unpadded_row_size));
2627        }
2628        ClearCommands();
2629      }
2630    }
2631  }
2632}
2633
2634// Test texture related calls with invalid arguments.
2635TEST_F(GLES2ImplementationTest, TextureInvalidArguments) {
2636  struct Cmds {
2637    cmds::TexImage2D tex_image_2d;
2638    cmd::SetToken set_token;
2639  };
2640  const GLenum kTarget = GL_TEXTURE_2D;
2641  const GLint kLevel = 0;
2642  const GLenum kFormat = GL_RGB;
2643  const GLsizei kWidth = 3;
2644  const GLsizei kHeight = 4;
2645  const GLint kBorder = 0;
2646  const GLint kInvalidBorder = 1;
2647  const GLenum kType = GL_UNSIGNED_BYTE;
2648  const GLint kPixelStoreUnpackAlignment = 4;
2649  static uint8 pixels[] = {
2650    11, 12, 13, 13, 14, 15, 15, 16, 17, 101, 102, 103,
2651    21, 22, 23, 23, 24, 25, 25, 26, 27, 201, 202, 203,
2652    31, 32, 33, 33, 34, 35, 35, 36, 37, 123, 124, 125,
2653    41, 42, 43, 43, 44, 45, 45, 46, 47,
2654  };
2655
2656  // Verify that something works.
2657
2658  ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels));
2659
2660  Cmds expected;
2661  expected.tex_image_2d.Init(
2662      kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2663      mem1.id, mem1.offset);
2664  expected.set_token.Init(GetNextToken());
2665  gl_->TexImage2D(
2666      kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2667      pixels);
2668  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2669  EXPECT_TRUE(CheckRect(
2670      kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment, false,
2671      pixels, mem1.ptr));
2672
2673  ClearCommands();
2674
2675  // Use invalid border.
2676  gl_->TexImage2D(
2677      kTarget, kLevel, kFormat, kWidth, kHeight, kInvalidBorder, kFormat, kType,
2678      pixels);
2679
2680  EXPECT_TRUE(NoCommandsWritten());
2681  EXPECT_EQ(GL_INVALID_VALUE, CheckError());
2682
2683  ClearCommands();
2684
2685  gl_->AsyncTexImage2DCHROMIUM(
2686      kTarget, kLevel, kFormat, kWidth, kHeight, kInvalidBorder, kFormat, kType,
2687      NULL);
2688
2689  EXPECT_TRUE(NoCommandsWritten());
2690  EXPECT_EQ(GL_INVALID_VALUE, CheckError());
2691
2692  ClearCommands();
2693
2694  // Checking for CompressedTexImage2D argument validation is a bit tricky due
2695  // to (runtime-detected) compression formats. Try to infer the error with an
2696  // aux check.
2697  const GLenum kCompressedFormat = GL_ETC1_RGB8_OES;
2698  gl_->CompressedTexImage2D(
2699      kTarget, kLevel, kCompressedFormat, kWidth, kHeight, kBorder,
2700      arraysize(pixels), pixels);
2701
2702  // In the above, kCompressedFormat and arraysize(pixels) are possibly wrong
2703  // values. First ensure that these do not cause failures at the client. If
2704  // this check ever fails, it probably means that client checks more than at
2705  // the time of writing of this test. In this case, more code needs to be
2706  // written for this test.
2707  EXPECT_FALSE(NoCommandsWritten());
2708
2709  ClearCommands();
2710
2711  // Changing border to invalid border should make the call fail at the client
2712  // checks.
2713  gl_->CompressedTexImage2D(
2714      kTarget, kLevel, kCompressedFormat, kWidth, kHeight, kInvalidBorder,
2715      arraysize(pixels), pixels);
2716  EXPECT_TRUE(NoCommandsWritten());
2717  EXPECT_EQ(GL_INVALID_VALUE, CheckError());
2718}
2719
2720
2721// Binds can not be cached with bind_generates_resource = false because
2722// our id might not be valid. More specifically if you bind on contextA then
2723// delete on contextB the resource is still bound on contextA but GetInterger
2724// won't return an id.
2725TEST_F(GLES2ImplementationStrictSharedTest, BindsNotCached) {
2726  struct PNameValue {
2727    GLenum pname;
2728    GLint expected;
2729  };
2730  const PNameValue pairs[] = {{GL_TEXTURE_BINDING_2D, 1, },
2731                              {GL_TEXTURE_BINDING_CUBE_MAP, 2, },
2732                              {GL_TEXTURE_BINDING_EXTERNAL_OES, 3, },
2733                              {GL_FRAMEBUFFER_BINDING, 4, },
2734                              {GL_RENDERBUFFER_BINDING, 5, },
2735                              {GL_ARRAY_BUFFER_BINDING, 6, },
2736                              {GL_ELEMENT_ARRAY_BUFFER_BINDING, 7, }, };
2737  size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2738  for (size_t ii = 0; ii < num_pairs; ++ii) {
2739    const PNameValue& pv = pairs[ii];
2740    GLint v = -1;
2741    ExpectedMemoryInfo result1 =
2742        GetExpectedResultMemory(sizeof(cmds::GetIntegerv::Result));
2743    EXPECT_CALL(*command_buffer(), OnFlush())
2744        .WillOnce(SetMemory(result1.ptr,
2745                            SizedResultHelper<GLuint>(pv.expected)))
2746        .RetiresOnSaturation();
2747    gl_->GetIntegerv(pv.pname, &v);
2748    EXPECT_EQ(pv.expected, v);
2749  }
2750}
2751
2752// glGen* Ids must not be reused until glDelete* commands have been
2753// flushed by glFlush.
2754TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestBuffers) {
2755  FlushGenerationTest<GenBuffersAPI>();
2756}
2757TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestFramebuffers) {
2758  FlushGenerationTest<GenFramebuffersAPI>();
2759}
2760TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestRenderbuffers) {
2761  FlushGenerationTest<GenRenderbuffersAPI>();
2762}
2763TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestTextures) {
2764  FlushGenerationTest<GenTexturesAPI>();
2765}
2766
2767// glGen* Ids must not be reused cross-context until glDelete* commands are
2768// flushed by glFlush, and the Ids are lazily freed after.
2769TEST_F(GLES2ImplementationStrictSharedTest, CrossContextGenerationTestBuffers) {
2770  CrossContextGenerationTest<GenBuffersAPI>();
2771}
2772TEST_F(GLES2ImplementationStrictSharedTest,
2773       CrossContextGenerationTestFramebuffers) {
2774  CrossContextGenerationTest<GenFramebuffersAPI>();
2775}
2776TEST_F(GLES2ImplementationStrictSharedTest,
2777       CrossContextGenerationTestRenderbuffers) {
2778  CrossContextGenerationTest<GenRenderbuffersAPI>();
2779}
2780TEST_F(GLES2ImplementationStrictSharedTest,
2781       CrossContextGenerationTestTextures) {
2782  CrossContextGenerationTest<GenTexturesAPI>();
2783}
2784
2785// Test Delete which causes auto flush.  Tests a regression case that occurred
2786// in testing.
2787TEST_F(GLES2ImplementationStrictSharedTest,
2788       CrossContextGenerationAutoFlushTestBuffers) {
2789  CrossContextGenerationAutoFlushTest<GenBuffersAPI>();
2790}
2791TEST_F(GLES2ImplementationStrictSharedTest,
2792       CrossContextGenerationAutoFlushTestFramebuffers) {
2793  CrossContextGenerationAutoFlushTest<GenFramebuffersAPI>();
2794}
2795TEST_F(GLES2ImplementationStrictSharedTest,
2796       CrossContextGenerationAutoFlushTestRenderbuffers) {
2797  CrossContextGenerationAutoFlushTest<GenRenderbuffersAPI>();
2798}
2799TEST_F(GLES2ImplementationStrictSharedTest,
2800       CrossContextGenerationAutoFlushTestTextures) {
2801  CrossContextGenerationAutoFlushTest<GenTexturesAPI>();
2802}
2803
2804TEST_F(GLES2ImplementationTest, GetString) {
2805  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2806  const Str7 kString = {"foobar"};
2807  // GL_CHROMIUM_map_sub GL_CHROMIUM_flipy are hard coded into
2808  // GLES2Implementation.
2809  const char* expected_str =
2810      "foobar "
2811      "GL_CHROMIUM_flipy "
2812      "GL_EXT_unpack_subimage "
2813      "GL_CHROMIUM_map_sub";
2814  const char kBad = 0x12;
2815  struct Cmds {
2816    cmd::SetBucketSize set_bucket_size1;
2817    cmds::GetString get_string;
2818    cmd::GetBucketStart get_bucket_start;
2819    cmd::SetToken set_token1;
2820    cmd::SetBucketSize set_bucket_size2;
2821  };
2822  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
2823  ExpectedMemoryInfo result1 =
2824      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2825  Cmds expected;
2826  expected.set_bucket_size1.Init(kBucketId, 0);
2827  expected.get_string.Init(GL_EXTENSIONS, kBucketId);
2828  expected.get_bucket_start.Init(
2829      kBucketId, result1.id, result1.offset,
2830      MaxTransferBufferSize(), mem1.id, mem1.offset);
2831  expected.set_token1.Init(GetNextToken());
2832  expected.set_bucket_size2.Init(kBucketId, 0);
2833  char buf[sizeof(kString) + 1];
2834  memset(buf, kBad, sizeof(buf));
2835
2836  EXPECT_CALL(*command_buffer(), OnFlush())
2837      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2838                      SetMemory(mem1.ptr, kString)))
2839      .RetiresOnSaturation();
2840
2841  const GLubyte* result = gl_->GetString(GL_EXTENSIONS);
2842  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2843  EXPECT_STREQ(expected_str, reinterpret_cast<const char*>(result));
2844}
2845
2846TEST_F(GLES2ImplementationTest, PixelStoreiGLPackReverseRowOrderANGLE) {
2847  const uint32 kBucketId = GLES2Implementation::kResultBucketId;
2848  const Str7 kString = {"foobar"};
2849  struct Cmds {
2850    cmd::SetBucketSize set_bucket_size1;
2851    cmds::GetString get_string;
2852    cmd::GetBucketStart get_bucket_start;
2853    cmd::SetToken set_token1;
2854    cmd::SetBucketSize set_bucket_size2;
2855    cmds::PixelStorei pixel_store;
2856  };
2857
2858  ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
2859  ExpectedMemoryInfo result1 =
2860      GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
2861
2862  Cmds expected;
2863  expected.set_bucket_size1.Init(kBucketId, 0);
2864  expected.get_string.Init(GL_EXTENSIONS, kBucketId);
2865  expected.get_bucket_start.Init(
2866      kBucketId, result1.id, result1.offset,
2867      MaxTransferBufferSize(), mem1.id, mem1.offset);
2868  expected.set_token1.Init(GetNextToken());
2869  expected.set_bucket_size2.Init(kBucketId, 0);
2870  expected.pixel_store.Init(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1);
2871
2872  EXPECT_CALL(*command_buffer(), OnFlush())
2873      .WillOnce(DoAll(SetMemory(result1.ptr, uint32(sizeof(kString))),
2874                      SetMemory(mem1.ptr, kString)))
2875      .RetiresOnSaturation();
2876
2877  gl_->PixelStorei(GL_PACK_REVERSE_ROW_ORDER_ANGLE, 1);
2878  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2879}
2880
2881TEST_F(GLES2ImplementationTest, CreateProgram) {
2882  struct Cmds {
2883    cmds::CreateProgram cmd;
2884  };
2885
2886  Cmds expected;
2887  expected.cmd.Init(kProgramsAndShadersStartId);
2888  GLuint id = gl_->CreateProgram();
2889  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2890  EXPECT_EQ(kProgramsAndShadersStartId, id);
2891}
2892
2893TEST_F(GLES2ImplementationTest, BufferDataLargerThanTransferBuffer) {
2894  struct Cmds {
2895    cmds::BufferData set_size;
2896    cmds::BufferSubData copy_data1;
2897    cmd::SetToken set_token1;
2898    cmds::BufferSubData copy_data2;
2899    cmd::SetToken set_token2;
2900  };
2901  const unsigned kUsableSize =
2902      kTransferBufferSize - GLES2Implementation::kStartingOffset;
2903  uint8 buf[kUsableSize * 2] = { 0, };
2904
2905  ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize);
2906  ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize);
2907
2908  Cmds expected;
2909  expected.set_size.Init(
2910      GL_ARRAY_BUFFER, arraysize(buf), 0, 0, GL_DYNAMIC_DRAW);
2911  expected.copy_data1.Init(
2912      GL_ARRAY_BUFFER, 0, kUsableSize, mem1.id, mem1.offset);
2913  expected.set_token1.Init(GetNextToken());
2914  expected.copy_data2.Init(
2915      GL_ARRAY_BUFFER, kUsableSize, kUsableSize, mem2.id, mem2.offset);
2916  expected.set_token2.Init(GetNextToken());
2917  gl_->BufferData(GL_ARRAY_BUFFER, arraysize(buf), buf, GL_DYNAMIC_DRAW);
2918  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2919}
2920
2921TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) {
2922  static const GLenum kStates[] = {
2923    GL_DITHER,
2924    GL_BLEND,
2925    GL_CULL_FACE,
2926    GL_DEPTH_TEST,
2927    GL_POLYGON_OFFSET_FILL,
2928    GL_SAMPLE_ALPHA_TO_COVERAGE,
2929    GL_SAMPLE_COVERAGE,
2930    GL_SCISSOR_TEST,
2931    GL_STENCIL_TEST,
2932  };
2933  struct Cmds {
2934    cmds::Enable enable_cmd;
2935  };
2936  Cmds expected;
2937
2938  for (size_t ii = 0; ii < arraysize(kStates); ++ii) {
2939    GLenum state = kStates[ii];
2940    expected.enable_cmd.Init(state);
2941    GLboolean result = gl_->IsEnabled(state);
2942    EXPECT_EQ(static_cast<GLboolean>(ii == 0), result);
2943    EXPECT_TRUE(NoCommandsWritten());
2944    const void* commands = GetPut();
2945    if (!result) {
2946      gl_->Enable(state);
2947      EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
2948    }
2949    ClearCommands();
2950    result = gl_->IsEnabled(state);
2951    EXPECT_TRUE(result);
2952    EXPECT_TRUE(NoCommandsWritten());
2953  }
2954}
2955
2956TEST_F(GLES2ImplementationTest, BindVertexArrayOES) {
2957  GLuint id = 0;
2958  gl_->GenVertexArraysOES(1, &id);
2959  ClearCommands();
2960
2961  struct Cmds {
2962    cmds::BindVertexArrayOES cmd;
2963  };
2964  Cmds expected;
2965  expected.cmd.Init(id);
2966
2967  const void* commands = GetPut();
2968  gl_->BindVertexArrayOES(id);
2969  EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
2970  ClearCommands();
2971  gl_->BindVertexArrayOES(id);
2972  EXPECT_TRUE(NoCommandsWritten());
2973}
2974
2975TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) {
2976  // Test GetQueryivEXT returns 0 if no current query.
2977  GLint param = -1;
2978  gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, &param);
2979  EXPECT_EQ(0, param);
2980
2981  GLuint expected_ids[2] = { 1, 2 }; // These must match what's actually genned.
2982  struct GenCmds {
2983    cmds::GenQueriesEXTImmediate gen;
2984    GLuint data[2];
2985  };
2986  GenCmds expected_gen_cmds;
2987  expected_gen_cmds.gen.Init(arraysize(expected_ids), &expected_ids[0]);
2988  GLuint ids[arraysize(expected_ids)] = { 0, };
2989  gl_->GenQueriesEXT(arraysize(expected_ids), &ids[0]);
2990  EXPECT_EQ(0, memcmp(
2991      &expected_gen_cmds, commands_, sizeof(expected_gen_cmds)));
2992  GLuint id1 = ids[0];
2993  GLuint id2 = ids[1];
2994  ClearCommands();
2995
2996  // Test BeginQueryEXT fails if id = 0.
2997  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0);
2998  EXPECT_TRUE(NoCommandsWritten());
2999  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3000
3001  // Test BeginQueryEXT inserts command.
3002  struct BeginCmds {
3003    cmds::BeginQueryEXT begin_query;
3004  };
3005  BeginCmds expected_begin_cmds;
3006  const void* commands = GetPut();
3007  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1);
3008  QueryTracker::Query* query = GetQuery(id1);
3009  ASSERT_TRUE(query != NULL);
3010  expected_begin_cmds.begin_query.Init(
3011      GL_ANY_SAMPLES_PASSED_EXT, id1, query->shm_id(), query->shm_offset());
3012  EXPECT_EQ(0, memcmp(
3013      &expected_begin_cmds, commands, sizeof(expected_begin_cmds)));
3014  ClearCommands();
3015
3016  // Test GetQueryivEXT returns id.
3017  param = -1;
3018  gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, &param);
3019  EXPECT_EQ(id1, static_cast<GLuint>(param));
3020  gl_->GetQueryivEXT(
3021      GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_CURRENT_QUERY_EXT, &param);
3022  EXPECT_EQ(0, param);
3023
3024  // Test BeginQueryEXT fails if between Begin/End.
3025  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id2);
3026  EXPECT_TRUE(NoCommandsWritten());
3027  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3028
3029  // Test EndQueryEXT fails if target not same as current query.
3030  ClearCommands();
3031  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
3032  EXPECT_TRUE(NoCommandsWritten());
3033  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3034
3035  // Test EndQueryEXT sends command
3036  struct EndCmds {
3037    cmds::EndQueryEXT end_query;
3038  };
3039  EndCmds expected_end_cmds;
3040  expected_end_cmds.end_query.Init(
3041      GL_ANY_SAMPLES_PASSED_EXT, query->submit_count());
3042  commands = GetPut();
3043  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3044  EXPECT_EQ(0, memcmp(
3045      &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3046
3047  // Test EndQueryEXT fails if no current query.
3048  ClearCommands();
3049  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3050  EXPECT_TRUE(NoCommandsWritten());
3051  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3052
3053  // Test 2nd Begin/End increments count.
3054  base::subtle::Atomic32 old_submit_count = query->submit_count();
3055  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1);
3056  EXPECT_NE(old_submit_count, query->submit_count());
3057  expected_end_cmds.end_query.Init(
3058      GL_ANY_SAMPLES_PASSED_EXT, query->submit_count());
3059  commands = GetPut();
3060  gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3061  EXPECT_EQ(0, memcmp(
3062      &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3063
3064  // Test BeginQueryEXT fails if target changed.
3065  ClearCommands();
3066  gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, id1);
3067  EXPECT_TRUE(NoCommandsWritten());
3068  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3069
3070  // Test GetQueryObjectuivEXT fails if unused id
3071  GLuint available = 0xBDu;
3072  ClearCommands();
3073  gl_->GetQueryObjectuivEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3074  EXPECT_TRUE(NoCommandsWritten());
3075  EXPECT_EQ(0xBDu, available);
3076  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3077
3078  // Test GetQueryObjectuivEXT fails if bad id
3079  ClearCommands();
3080  gl_->GetQueryObjectuivEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3081  EXPECT_TRUE(NoCommandsWritten());
3082  EXPECT_EQ(0xBDu, available);
3083  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3084
3085  // Test GetQueryObjectuivEXT CheckResultsAvailable
3086  ClearCommands();
3087  gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3088  EXPECT_EQ(0u, available);
3089}
3090
3091TEST_F(GLES2ImplementationTest, ErrorQuery) {
3092  GLuint id = 0;
3093  gl_->GenQueriesEXT(1, &id);
3094  ClearCommands();
3095
3096  // Test BeginQueryEXT does NOT insert commands.
3097  gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id);
3098  EXPECT_TRUE(NoCommandsWritten());
3099  QueryTracker::Query* query = GetQuery(id);
3100  ASSERT_TRUE(query != NULL);
3101
3102  // Test EndQueryEXT sends both begin and end command
3103  struct EndCmds {
3104    cmds::BeginQueryEXT begin_query;
3105    cmds::EndQueryEXT end_query;
3106  };
3107  EndCmds expected_end_cmds;
3108  expected_end_cmds.begin_query.Init(
3109      GL_GET_ERROR_QUERY_CHROMIUM, id, query->shm_id(), query->shm_offset());
3110  expected_end_cmds.end_query.Init(
3111      GL_GET_ERROR_QUERY_CHROMIUM, query->submit_count());
3112  const void* commands = GetPut();
3113  gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM);
3114  EXPECT_EQ(0, memcmp(
3115      &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3116  ClearCommands();
3117
3118  // Check result is not yet available.
3119  GLuint available = 0xBDu;
3120  gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3121  EXPECT_TRUE(NoCommandsWritten());
3122  EXPECT_EQ(0u, available);
3123
3124  // Test no commands are sent if there is a client side error.
3125
3126  // Generate a client side error
3127  gl_->ActiveTexture(GL_TEXTURE0 - 1);
3128
3129  gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id);
3130  gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM);
3131  EXPECT_TRUE(NoCommandsWritten());
3132
3133  // Check result is available.
3134  gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3135  EXPECT_TRUE(NoCommandsWritten());
3136  EXPECT_NE(0u, available);
3137
3138  // Check result.
3139  GLuint result = 0xBDu;
3140  gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_EXT, &result);
3141  EXPECT_TRUE(NoCommandsWritten());
3142  EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), result);
3143}
3144
3145#if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
3146TEST_F(GLES2ImplementationTest, VertexArrays) {
3147  const GLuint kAttribIndex1 = 1;
3148  const GLint kNumComponents1 = 3;
3149  const GLsizei kClientStride = 12;
3150
3151  GLuint id = 0;
3152  gl_->GenVertexArraysOES(1, &id);
3153  ClearCommands();
3154
3155  gl_->BindVertexArrayOES(id);
3156
3157  // Test that VertexAttribPointer cannot be called with a bound buffer of 0
3158  // unless the offset is NULL
3159  gl_->BindBuffer(GL_ARRAY_BUFFER, 0);
3160
3161  gl_->VertexAttribPointer(
3162      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride,
3163      reinterpret_cast<const void*>(4));
3164  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3165
3166  gl_->VertexAttribPointer(
3167      kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, NULL);
3168  EXPECT_EQ(GL_NO_ERROR, CheckError());
3169}
3170#endif
3171
3172TEST_F(GLES2ImplementationTest, Disable) {
3173  struct Cmds {
3174    cmds::Disable cmd;
3175  };
3176  Cmds expected;
3177  expected.cmd.Init(GL_DITHER);  // Note: DITHER defaults to enabled.
3178
3179  gl_->Disable(GL_DITHER);
3180  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3181  // Check it's cached and not called again.
3182  ClearCommands();
3183  gl_->Disable(GL_DITHER);
3184  EXPECT_TRUE(NoCommandsWritten());
3185}
3186
3187TEST_F(GLES2ImplementationTest, Enable) {
3188  struct Cmds {
3189    cmds::Enable cmd;
3190  };
3191  Cmds expected;
3192  expected.cmd.Init(GL_BLEND);  // Note: BLEND defaults to disabled.
3193
3194  gl_->Enable(GL_BLEND);
3195  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3196  // Check it's cached and not called again.
3197  ClearCommands();
3198  gl_->Enable(GL_BLEND);
3199  EXPECT_TRUE(NoCommandsWritten());
3200}
3201
3202TEST_F(GLES2ImplementationTest, ConsumeTextureCHROMIUM) {
3203  struct Cmds {
3204    cmds::ConsumeTextureCHROMIUMImmediate cmd;
3205    GLbyte data[64];
3206  };
3207
3208  Mailbox mailbox = Mailbox::Generate();
3209  Cmds expected;
3210  expected.cmd.Init(GL_TEXTURE_2D, mailbox.name);
3211  gl_->ConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
3212  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3213}
3214
3215TEST_F(GLES2ImplementationTest, CreateAndConsumeTextureCHROMIUM) {
3216  struct Cmds {
3217    cmds::CreateAndConsumeTextureCHROMIUMImmediate cmd;
3218    GLbyte data[64];
3219  };
3220
3221  Mailbox mailbox = Mailbox::Generate();
3222  Cmds expected;
3223  expected.cmd.Init(GL_TEXTURE_2D, kTexturesStartId, mailbox.name);
3224  GLuint id = gl_->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
3225  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3226  EXPECT_EQ(kTexturesStartId, id);
3227}
3228
3229TEST_F(GLES2ImplementationTest, ProduceTextureCHROMIUM) {
3230  struct Cmds {
3231    cmds::ProduceTextureCHROMIUMImmediate cmd;
3232    GLbyte data[64];
3233  };
3234
3235  Mailbox mailbox = Mailbox::Generate();
3236  Cmds expected;
3237  expected.cmd.Init(GL_TEXTURE_2D, mailbox.name);
3238  gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
3239  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3240}
3241
3242TEST_F(GLES2ImplementationTest, ProduceTextureDirectCHROMIUM) {
3243  struct Cmds {
3244    cmds::ProduceTextureDirectCHROMIUMImmediate cmd;
3245    GLbyte data[64];
3246  };
3247
3248  Mailbox mailbox = Mailbox::Generate();
3249  Cmds expected;
3250  expected.cmd.Init(kTexturesStartId, GL_TEXTURE_2D, mailbox.name);
3251  gl_->ProduceTextureDirectCHROMIUM(
3252      kTexturesStartId, GL_TEXTURE_2D, mailbox.name);
3253  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3254}
3255
3256TEST_F(GLES2ImplementationTest, LimitSizeAndOffsetTo32Bit) {
3257  GLsizeiptr size;
3258  GLintptr offset;
3259  if (sizeof(size) <= 4 || sizeof(offset) <= 4)
3260    return;
3261  // The below two casts should be no-op, as we return early if
3262  // it's 32-bit system.
3263  int64 value64 = 0x100000000;
3264  size = static_cast<GLsizeiptr>(value64);
3265  offset = static_cast<GLintptr>(value64);
3266
3267  const char kSizeOverflowMessage[] = "size more than 32-bit";
3268  const char kOffsetOverflowMessage[] = "offset more than 32-bit";
3269
3270  const GLfloat buf[] = { 1.0, 1.0, 1.0, 1.0 };
3271  const GLubyte indices[] = { 0 };
3272
3273  const GLuint kClientArrayBufferId = 0x789;
3274  const GLuint kClientElementArrayBufferId = 0x790;
3275  gl_->BindBuffer(GL_ARRAY_BUFFER, kClientArrayBufferId);
3276  gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientElementArrayBufferId);
3277  EXPECT_EQ(GL_NO_ERROR, CheckError());
3278
3279  // Call BufferData() should succeed with legal paramaters.
3280  gl_->BufferData(GL_ARRAY_BUFFER, sizeof(buf), buf, GL_DYNAMIC_DRAW);
3281  gl_->BufferData(
3282      GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
3283  EXPECT_EQ(GL_NO_ERROR, CheckError());
3284
3285  // BufferData: size
3286  gl_->BufferData(GL_ARRAY_BUFFER, size, buf, GL_DYNAMIC_DRAW);
3287  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3288  EXPECT_STREQ(kSizeOverflowMessage, GetLastError().c_str());
3289
3290  // Call BufferSubData() should succeed with legal paramaters.
3291  gl_->BufferSubData(GL_ARRAY_BUFFER, 0, sizeof(buf[0]), buf);
3292  EXPECT_EQ(GL_NO_ERROR, CheckError());
3293
3294  // BufferSubData: offset
3295  gl_->BufferSubData(GL_ARRAY_BUFFER, offset, 1, buf);
3296  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3297  EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3298
3299  // BufferSubData: size
3300  EXPECT_EQ(GL_NO_ERROR, CheckError());
3301  gl_->BufferSubData(GL_ARRAY_BUFFER, 0, size, buf);
3302  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3303  EXPECT_STREQ(kSizeOverflowMessage, GetLastError().c_str());
3304
3305  // Call MapBufferSubDataCHROMIUM() should succeed with legal paramaters.
3306  void* mem =
3307      gl_->MapBufferSubDataCHROMIUM(GL_ARRAY_BUFFER, 0, 1, GL_WRITE_ONLY);
3308  EXPECT_TRUE(NULL != mem);
3309  EXPECT_EQ(GL_NO_ERROR, CheckError());
3310  gl_->UnmapBufferSubDataCHROMIUM(mem);
3311
3312  // MapBufferSubDataCHROMIUM: offset
3313  EXPECT_TRUE(NULL == gl_->MapBufferSubDataCHROMIUM(
3314      GL_ARRAY_BUFFER, offset, 1, GL_WRITE_ONLY));
3315  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3316  EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3317
3318  // MapBufferSubDataCHROMIUM: size
3319  EXPECT_EQ(GL_NO_ERROR, CheckError());
3320  EXPECT_TRUE(NULL == gl_->MapBufferSubDataCHROMIUM(
3321      GL_ARRAY_BUFFER, 0, size, GL_WRITE_ONLY));
3322  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3323  EXPECT_STREQ(kSizeOverflowMessage, GetLastError().c_str());
3324
3325  // Call DrawElements() should succeed with legal paramaters.
3326  gl_->DrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, NULL);
3327  EXPECT_EQ(GL_NO_ERROR, CheckError());
3328
3329  // DrawElements: offset
3330  gl_->DrawElements(
3331      GL_POINTS, 1, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
3332  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3333  EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3334
3335  // Call DrawElementsInstancedANGLE() should succeed with legal paramaters.
3336  gl_->DrawElementsInstancedANGLE(GL_POINTS, 1, GL_UNSIGNED_BYTE, NULL, 1);
3337  EXPECT_EQ(GL_NO_ERROR, CheckError());
3338
3339  // DrawElementsInstancedANGLE: offset
3340  gl_->DrawElementsInstancedANGLE(
3341      GL_POINTS, 1, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset), 1);
3342  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3343  EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3344
3345  // Call VertexAttribPointer() should succeed with legal paramaters.
3346  const GLuint kAttribIndex = 1;
3347  const GLsizei kStride = 4;
3348  gl_->VertexAttribPointer(
3349      kAttribIndex, 1, GL_FLOAT, GL_FALSE, kStride, NULL);
3350  EXPECT_EQ(GL_NO_ERROR, CheckError());
3351
3352  // VertexAttribPointer: offset
3353  gl_->VertexAttribPointer(
3354      kAttribIndex, 1, GL_FLOAT, GL_FALSE, kStride,
3355      reinterpret_cast<void*>(offset));
3356  EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3357  EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3358}
3359
3360TEST_F(GLES2ImplementationManualInitTest, LoseContextOnOOM) {
3361  ContextInitOptions init_options;
3362  init_options.lose_context_when_out_of_memory = true;
3363  ASSERT_TRUE(Initialize(init_options));
3364
3365  struct Cmds {
3366    cmds::LoseContextCHROMIUM cmd;
3367  };
3368
3369  GLsizei max = std::numeric_limits<GLsizei>::max();
3370  EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _, _))
3371      .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL)));
3372  gl_->CreateImageCHROMIUM(max, max, 0, GL_IMAGE_MAP_CHROMIUM);
3373  // The context should be lost.
3374  Cmds expected;
3375  expected.cmd.Init(GL_GUILTY_CONTEXT_RESET_ARB, GL_UNKNOWN_CONTEXT_RESET_ARB);
3376  EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3377}
3378
3379TEST_F(GLES2ImplementationManualInitTest, NoLoseContextOnOOM) {
3380  ContextInitOptions init_options;
3381  ASSERT_TRUE(Initialize(init_options));
3382
3383  struct Cmds {
3384    cmds::LoseContextCHROMIUM cmd;
3385  };
3386
3387  GLsizei max = std::numeric_limits<GLsizei>::max();
3388  EXPECT_CALL(*gpu_control_, CreateGpuMemoryBuffer(max, max, _, _, _))
3389      .WillOnce(Return(static_cast<gfx::GpuMemoryBuffer*>(NULL)));
3390  gl_->CreateImageCHROMIUM(max, max, 0, GL_IMAGE_MAP_CHROMIUM);
3391  // The context should not be lost.
3392  EXPECT_TRUE(NoCommandsWritten());
3393}
3394
3395TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch1) {
3396  ContextInitOptions init_options;
3397  init_options.bind_generates_resource_client = false;
3398  init_options.bind_generates_resource_service = true;
3399  EXPECT_FALSE(Initialize(init_options));
3400}
3401
3402TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch2) {
3403  ContextInitOptions init_options;
3404  init_options.bind_generates_resource_client = true;
3405  init_options.bind_generates_resource_service = false;
3406  EXPECT_FALSE(Initialize(init_options));
3407}
3408
3409#include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h"
3410
3411}  // namespace gles2
3412}  // namespace gpu
3413