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