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