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