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