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