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