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