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