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