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/gl2.h>
10 #include <GLES2/gl2ext.h>
11 #include <GLES2/gl2extchromium.h>
12 #include <GLES3/gl3.h>
13 
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <memory>
18 
19 #include "base/bind.h"
20 #include "base/compiler_specific.h"
21 #include "base/stl_util.h"
22 #include "gpu/command_buffer/client/client_test_helper.h"
23 #include "gpu/command_buffer/client/gles2_cmd_helper.h"
24 #include "gpu/command_buffer/client/mock_transfer_buffer.h"
25 #include "gpu/command_buffer/client/program_info_manager.h"
26 #include "gpu/command_buffer/client/query_tracker.h"
27 #include "gpu/command_buffer/client/ring_buffer.h"
28 #include "gpu/command_buffer/client/shared_memory_limits.h"
29 #include "gpu/command_buffer/common/command_buffer.h"
30 #include "gpu/command_buffer/common/sync_token.h"
31 #include "testing/gmock/include/gmock/gmock.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33 
34 #if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
35 #define GLES2_SUPPORT_CLIENT_SIDE_ARRAYS
36 #endif
37 
38 using testing::_;
39 using testing::AtLeast;
40 using testing::AnyNumber;
41 using testing::DoAll;
42 using testing::InSequence;
43 using testing::Invoke;
44 using testing::Mock;
45 using testing::Pointee;
46 using testing::SaveArg;
47 using testing::Sequence;
48 using testing::StrictMock;
49 using testing::Truly;
50 using testing::Return;
51 using testing::ReturnRef;
52 
53 namespace gpu {
54 namespace gles2 {
55 
ACTION_P2(SetMemory,dst,obj)56 ACTION_P2(SetMemory, dst, obj) {
57   memcpy(dst, &obj, sizeof(obj));
58 }
59 
ACTION_P3(SetMemoryFromArray,dst,array,size)60 ACTION_P3(SetMemoryFromArray, dst, array, size) {
61   memcpy(dst, array, size);
62 }
63 
64 // Used to help set the transfer buffer result to SizedResult of a single value.
65 template <typename T>
66 class SizedResultHelper {
67  public:
SizedResultHelper(T result)68   explicit SizedResultHelper(T result)
69       : size_(sizeof(result)) {
70     memcpy(result_, &result, sizeof(T));
71   }
72 
73  private:
74   uint32_t size_;
75   char result_[sizeof(T)];
76 };
77 
78 // Struct to make it easy to pass a vec4 worth of floats.
79 struct FourFloats {
FourFloatsgpu::gles2::FourFloats80   FourFloats(float _x, float _y, float _z, float _w)
81       : x(_x),
82         y(_y),
83         z(_z),
84         w(_w) {
85   }
86 
87   float x;
88   float y;
89   float z;
90   float w;
91 };
92 
93 #pragma pack(push, 1)
94 // Struct that holds 7 characters.
95 struct Str7 {
96   char str[7];
97 };
98 #pragma pack(pop)
99 
100 // API wrapper for Buffers.
101 class GenBuffersAPI {
102  public:
Gen(GLES2Implementation * gl_impl,GLsizei n,GLuint * ids)103   static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
104     gl_impl->GenBuffers(n, ids);
105   }
106 
Delete(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids)107   static void Delete(GLES2Implementation* gl_impl,
108                      GLsizei n,
109                      const GLuint* ids) {
110     gl_impl->DeleteBuffers(n, ids);
111   }
112 };
113 
114 // API wrapper for Renderbuffers.
115 class GenRenderbuffersAPI {
116  public:
Gen(GLES2Implementation * gl_impl,GLsizei n,GLuint * ids)117   static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
118     gl_impl->GenRenderbuffers(n, ids);
119   }
120 
Delete(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids)121   static void Delete(GLES2Implementation* gl_impl,
122                      GLsizei n,
123                      const GLuint* ids) {
124     gl_impl->DeleteRenderbuffers(n, ids);
125   }
126 };
127 
128 // API wrapper for Textures.
129 class GenTexturesAPI {
130  public:
Gen(GLES2Implementation * gl_impl,GLsizei n,GLuint * ids)131   static void Gen(GLES2Implementation* gl_impl, GLsizei n, GLuint* ids) {
132     gl_impl->GenTextures(n, ids);
133   }
134 
Delete(GLES2Implementation * gl_impl,GLsizei n,const GLuint * ids)135   static void Delete(GLES2Implementation* gl_impl,
136                      GLsizei n,
137                      const GLuint* ids) {
138     gl_impl->DeleteTextures(n, ids);
139   }
140 };
141 
142 class GLES2ImplementationTest : public testing::Test {
143  protected:
144   static const int kNumTestContexts = 2;
145   static const uint8_t kInitialValue = 0xBD;
146   static const int32_t kNumCommandEntries = 500;
147   static const int32_t kCommandBufferSizeBytes =
148       kNumCommandEntries * sizeof(CommandBufferEntry);
149   static const size_t kTransferBufferSize = 512;
150 
151   static const GLint kMaxCombinedTextureImageUnits = 8;
152   static const GLint kMaxCubeMapTextureSize = 64;
153   static const GLint kMaxFragmentUniformVectors = 16;
154   static const GLint kMaxRenderbufferSize = 64;
155   static const GLint kMaxTextureImageUnits = 8;
156   static const GLint kMaxTextureSize = 128;
157   static const GLint kMaxVaryingVectors = 8;
158   static const GLint kMaxVertexAttribs = 8;
159   static const GLint kMaxVertexTextureImageUnits = 0;
160   static const GLint kMaxVertexUniformVectors = 128;
161   static const GLint kMaxViewportWidth = 8192;
162   static const GLint kMaxViewportHeight = 6144;
163   static const GLint kNumCompressedTextureFormats = 0;
164   static const GLint kNumShaderBinaryFormats = 0;
165   static const GLuint kMaxTransformFeedbackSeparateAttribs = 4;
166   static const GLuint kMaxUniformBufferBindings = 36;
167   static const GLuint kStartId = 1024;
168   static const GLuint kBuffersStartId = 1;
169   static const GLuint kFramebuffersStartId = 1;
170   static const GLuint kProgramsAndShadersStartId = 1;
171   static const GLuint kRenderbuffersStartId = 1;
172   static const GLuint kSamplersStartId = 1;
173   static const GLuint kTexturesStartId = 1;
174   static const GLuint kTransformFeedbacksStartId = 1;
175   static const GLuint kQueriesStartId = 1;
176   static const GLuint kVertexArraysStartId = 1;
177 
178   typedef MockTransferBuffer::ExpectedMemoryInfo ExpectedMemoryInfo;
179 
180   class TestContext {
181    public:
TestContext()182     TestContext() : commands_(nullptr), token_(0) {}
183 
Initialize(ShareGroup * share_group,bool bind_generates_resource_client,bool bind_generates_resource_service,bool lose_context_when_out_of_memory,bool transfer_buffer_initialize_fail,bool sync_query,bool occlusion_query_boolean,bool timer_queries,int major_version,int minor_version)184     bool Initialize(ShareGroup* share_group,
185                     bool bind_generates_resource_client,
186                     bool bind_generates_resource_service,
187                     bool lose_context_when_out_of_memory,
188                     bool transfer_buffer_initialize_fail,
189                     bool sync_query,
190                     bool occlusion_query_boolean,
191                     bool timer_queries,
192                     int major_version,
193                     int minor_version) {
194       SharedMemoryLimits limits = SharedMemoryLimitsForTesting();
195       command_buffer_.reset(new StrictMock<MockClientCommandBuffer>());
196 
197       transfer_buffer_.reset(
198           new MockTransferBuffer(command_buffer_.get(),
199                                  kTransferBufferSize,
200                                  GLES2Implementation::kStartingOffset,
201                                  GLES2Implementation::kAlignment,
202                                  transfer_buffer_initialize_fail));
203 
204       helper_.reset(new GLES2CmdHelper(command_buffer()));
205       helper_->Initialize(limits.command_buffer_size);
206 
207       gpu_control_.reset(new StrictMock<MockClientGpuControl>());
208       capabilities_.VisitPrecisions(
209           [](GLenum shader, GLenum type,
210              Capabilities::ShaderPrecision* precision) {
211             precision->min_range = 3;
212             precision->max_range = 5;
213             precision->precision = 7;
214           });
215       capabilities_.max_combined_texture_image_units =
216           kMaxCombinedTextureImageUnits;
217       capabilities_.max_cube_map_texture_size = kMaxCubeMapTextureSize;
218       capabilities_.max_fragment_uniform_vectors = kMaxFragmentUniformVectors;
219       capabilities_.max_renderbuffer_size = kMaxRenderbufferSize;
220       capabilities_.max_texture_image_units = kMaxTextureImageUnits;
221       capabilities_.max_texture_size = kMaxTextureSize;
222       capabilities_.max_varying_vectors = kMaxVaryingVectors;
223       capabilities_.max_vertex_attribs = kMaxVertexAttribs;
224       capabilities_.max_vertex_texture_image_units =
225           kMaxVertexTextureImageUnits;
226       capabilities_.max_vertex_uniform_vectors = kMaxVertexUniformVectors;
227       capabilities_.max_viewport_width = kMaxViewportWidth;
228       capabilities_.max_viewport_height = kMaxViewportHeight;
229       capabilities_.num_compressed_texture_formats =
230           kNumCompressedTextureFormats;
231       capabilities_.num_shader_binary_formats = kNumShaderBinaryFormats;
232       capabilities_.max_transform_feedback_separate_attribs =
233           kMaxTransformFeedbackSeparateAttribs;
234       capabilities_.max_uniform_buffer_bindings = kMaxUniformBufferBindings;
235       capabilities_.bind_generates_resource_chromium =
236           bind_generates_resource_service ? 1 : 0;
237       capabilities_.sync_query = sync_query;
238       capabilities_.occlusion_query_boolean = occlusion_query_boolean;
239       capabilities_.timer_queries = timer_queries;
240       capabilities_.major_version = major_version;
241       capabilities_.minor_version = minor_version;
242       EXPECT_CALL(*gpu_control_, GetCapabilities())
243           .WillOnce(ReturnRef(capabilities_));
244 
245       {
246         InSequence sequence;
247 
248         const bool support_client_side_arrays = true;
249         gl_.reset(new GLES2Implementation(helper_.get(),
250                                           share_group,
251                                           transfer_buffer_.get(),
252                                           bind_generates_resource_client,
253                                           lose_context_when_out_of_memory,
254                                           support_client_side_arrays,
255                                           gpu_control_.get()));
256       }
257 
258       // The client should be set to something non-null.
259       EXPECT_CALL(*gpu_control_, SetGpuControlClient(gl_.get())).Times(1);
260 
261       if (gl_->Initialize(limits) != gpu::ContextResult::kSuccess)
262         return false;
263 
264       helper_->CommandBufferHelper::Finish();
265       Mock::VerifyAndClearExpectations(gl_.get());
266 
267       scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
268       commands_ = static_cast<CommandBufferEntry*>(ring_buffer->memory()) +
269                   command_buffer()->GetServicePutOffset();
270       ClearCommands();
271       EXPECT_TRUE(transfer_buffer_->InSync());
272 
273       Mock::VerifyAndClearExpectations(command_buffer());
274       return true;
275     }
276 
TearDown()277     void TearDown() {
278       Mock::VerifyAndClear(gl_.get());
279       EXPECT_CALL(*command_buffer(), OnFlush()).Times(AnyNumber());
280       // For command buffer.
281       EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
282           .Times(AtLeast(1));
283       // The client should be unset.
284       EXPECT_CALL(*gpu_control_, SetGpuControlClient(nullptr)).Times(1);
285       gl_.reset();
286     }
287 
command_buffer() const288     MockClientCommandBuffer* command_buffer() const {
289       return command_buffer_.get();
290     }
291 
GetNextToken()292     int GetNextToken() { return ++token_; }
293 
ClearCommands()294     void ClearCommands() {
295       scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
296       memset(ring_buffer->memory(), kInitialValue, ring_buffer->size());
297     }
298 
299     std::unique_ptr<MockClientCommandBuffer> command_buffer_;
300     std::unique_ptr<MockClientGpuControl> gpu_control_;
301     std::unique_ptr<GLES2CmdHelper> helper_;
302     std::unique_ptr<MockTransferBuffer> transfer_buffer_;
303     std::unique_ptr<GLES2Implementation> gl_;
304     CommandBufferEntry* commands_;
305     int token_;
306     Capabilities capabilities_;
307   };
308 
GLES2ImplementationTest()309   GLES2ImplementationTest() : commands_(nullptr) {}
310 
311   void SetUp() override;
312   void TearDown() override;
313 
NoCommandsWritten()314   bool NoCommandsWritten() {
315     scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
316     const uint8_t* cmds = static_cast<const uint8_t*>(ring_buffer->memory());
317     const uint8_t* end = cmds + ring_buffer->size();
318     for (; cmds < end; ++cmds) {
319       if (*cmds != kInitialValue) {
320         return false;
321       }
322     }
323     return true;
324   }
325 
GetQuery(GLuint id)326   QueryTracker::Query* GetQuery(GLuint id) {
327     return gl_->query_tracker_->GetQuery(id);
328   }
329 
GetQueryTracker()330   QueryTracker* GetQueryTracker() {
331     return gl_->query_tracker_.get();
332   }
333 
334   struct ContextInitOptions {
ContextInitOptionsgpu::gles2::GLES2ImplementationTest::ContextInitOptions335     ContextInitOptions()
336         : bind_generates_resource_client(true),
337           bind_generates_resource_service(true),
338           lose_context_when_out_of_memory(false),
339           transfer_buffer_initialize_fail(false),
340           sync_query(true),
341           occlusion_query_boolean(true),
342           timer_queries(true),
343           major_version(2),
344           minor_version(0) {}
345 
346     bool bind_generates_resource_client;
347     bool bind_generates_resource_service;
348     bool lose_context_when_out_of_memory;
349     bool transfer_buffer_initialize_fail;
350     bool sync_query;
351     bool occlusion_query_boolean;
352     bool timer_queries;
353     int major_version;
354     int minor_version;
355   };
356 
Initialize(const ContextInitOptions & init_options)357   bool Initialize(const ContextInitOptions& init_options) {
358     bool success = true;
359     share_group_ = new ShareGroup(init_options.bind_generates_resource_client,
360                                   0 /* tracing_id */);
361 
362     for (int i = 0; i < kNumTestContexts; i++) {
363       if (!test_contexts_[i].Initialize(
364               share_group_.get(),
365               init_options.bind_generates_resource_client,
366               init_options.bind_generates_resource_service,
367               init_options.lose_context_when_out_of_memory,
368               init_options.transfer_buffer_initialize_fail,
369               init_options.sync_query,
370               init_options.occlusion_query_boolean,
371               init_options.timer_queries,
372               init_options.major_version,
373               init_options.minor_version))
374         success = false;
375     }
376 
377     // Default to test context 0.
378     gpu_control_ = test_contexts_[0].gpu_control_.get();
379     helper_ = test_contexts_[0].helper_.get();
380     transfer_buffer_ = test_contexts_[0].transfer_buffer_.get();
381     gl_ = test_contexts_[0].gl_.get();
382     commands_ = test_contexts_[0].commands_;
383     return success;
384   }
385 
command_buffer() const386   MockClientCommandBuffer* command_buffer() const {
387     return test_contexts_[0].command_buffer_.get();
388   }
389 
GetNextToken()390   int GetNextToken() { return test_contexts_[0].GetNextToken(); }
391 
GetPut()392   const void* GetPut() {
393     return helper_->GetSpace(0);
394   }
395 
ClearCommands()396   void ClearCommands() {
397     scoped_refptr<Buffer> ring_buffer = helper_->get_ring_buffer();
398     memset(ring_buffer->memory(), kInitialValue, ring_buffer->size());
399   }
400 
MaxTransferBufferSize()401   size_t MaxTransferBufferSize() {
402     return transfer_buffer_->MaxTransferBufferSize();
403   }
404 
SetMappedMemoryLimit(size_t limit)405   void SetMappedMemoryLimit(size_t limit) {
406     gl_->mapped_memory_->set_max_allocated_bytes(limit);
407   }
408 
GetExpectedMemory(size_t size)409   ExpectedMemoryInfo GetExpectedMemory(size_t size) {
410     return transfer_buffer_->GetExpectedMemory(size);
411   }
412 
GetExpectedResultMemory(size_t size)413   ExpectedMemoryInfo GetExpectedResultMemory(size_t size) {
414     return transfer_buffer_->GetExpectedResultMemory(size);
415   }
416 
GetExpectedMappedMemory(size_t size)417   ExpectedMemoryInfo GetExpectedMappedMemory(size_t size) {
418     ExpectedMemoryInfo mem;
419 
420     // Temporarily allocate memory and expect that memory block to be reused.
421     mem.ptr = static_cast<uint8_t*>(
422         gl_->mapped_memory_->Alloc(size, &mem.id, &mem.offset));
423     gl_->mapped_memory_->Free(mem.ptr);
424 
425     return mem;
426   }
427 
428   // Sets the ProgramInfoManager. The manager will be owned
429   // by the ShareGroup.
SetProgramInfoManager(ProgramInfoManager * manager)430   void SetProgramInfoManager(ProgramInfoManager* manager) {
431     gl_->share_group()->SetProgramInfoManagerForTesting(manager);
432   }
433 
CheckError()434   int CheckError() {
435     ExpectedMemoryInfo result =
436         GetExpectedResultMemory(sizeof(cmds::GetError::Result));
437     EXPECT_CALL(*command_buffer(), OnFlush())
438         .WillOnce(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
439         .RetiresOnSaturation();
440     return gl_->GetError();
441   }
442 
GetLastError()443   const std::string& GetLastError() {
444     return gl_->GetLastError();
445   }
446 
GetBucketContents(uint32_t bucket_id,std::vector<int8_t> * data)447   bool GetBucketContents(uint32_t bucket_id, std::vector<int8_t>* data) {
448     return gl_->GetBucketContents(bucket_id, data);
449   }
450 
AllowExtraTransferBufferSize()451   bool AllowExtraTransferBufferSize() {
452     return gl_->max_extra_transfer_buffer_size_ > 0;
453   }
454 
SharedMemoryLimitsForTesting()455   static SharedMemoryLimits SharedMemoryLimitsForTesting() {
456     SharedMemoryLimits limits;
457     limits.command_buffer_size = kCommandBufferSizeBytes;
458     limits.start_transfer_buffer_size = kTransferBufferSize;
459     limits.min_transfer_buffer_size = kTransferBufferSize;
460     limits.max_transfer_buffer_size = kTransferBufferSize;
461     limits.mapped_memory_reclaim_limit = SharedMemoryLimits::kNoLimit;
462     return limits;
463   }
464 
ResetErrorMessageCallback()465   void ResetErrorMessageCallback() { gl_->error_message_callback_.Reset(); }
466 
467   TestContext test_contexts_[kNumTestContexts];
468 
469   scoped_refptr<ShareGroup> share_group_;
470   MockClientGpuControl* gpu_control_;
471   GLES2CmdHelper* helper_;
472   MockTransferBuffer* transfer_buffer_;
473   GLES2Implementation* gl_;
474   CommandBufferEntry* commands_;
475 };
476 
SetUp()477 void GLES2ImplementationTest::SetUp() {
478   ContextInitOptions init_options;
479   ASSERT_TRUE(Initialize(init_options));
480 }
481 
TearDown()482 void GLES2ImplementationTest::TearDown() {
483   for (int i = 0; i < kNumTestContexts; i++)
484     test_contexts_[i].TearDown();
485 }
486 
487 class GLES2ImplementationManualInitTest : public GLES2ImplementationTest {
488  protected:
SetUp()489   void SetUp() override {}
490 };
491 
492 class GLES2ImplementationStrictSharedTest : public GLES2ImplementationTest {
493  protected:
494   void SetUp() override;
495 
496   template <class ResApi>
FlushGenerationTest()497   void FlushGenerationTest() {
498     GLuint id1, id2, id3;
499 
500     // Generate valid id.
501     ResApi::Gen(gl_, 1, &id1);
502     EXPECT_NE(id1, 0u);
503 
504     // Delete id1 and generate id2.  id1 should not be reused.
505     ResApi::Delete(gl_, 1, &id1);
506     ResApi::Gen(gl_, 1, &id2);
507     EXPECT_NE(id2, 0u);
508     EXPECT_NE(id2, id1);
509 
510     // Expect id1 reuse after Flush.
511     gl_->Flush();
512     ResApi::Gen(gl_, 1, &id3);
513     EXPECT_EQ(id3, id1);
514   }
515 
516   // Ids should not be reused unless the |Deleting| context does a Flush()
517   // AND triggers a lazy release after that.
518   template <class ResApi>
CrossContextGenerationTest()519   void CrossContextGenerationTest() {
520     GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
521     GLES2Implementation* gl2 = test_contexts_[1].gl_.get();
522     GLuint id1, id2, id3;
523 
524     // Delete, no flush on context 1.  No reuse.
525     ResApi::Gen(gl1, 1, &id1);
526     ResApi::Delete(gl1, 1, &id1);
527     ResApi::Gen(gl1, 1, &id2);
528     EXPECT_NE(id1, id2);
529 
530     // Flush context 2.  Still no reuse.
531     gl2->Flush();
532     ResApi::Gen(gl2, 1, &id3);
533     EXPECT_NE(id1, id3);
534     EXPECT_NE(id2, id3);
535 
536     // Flush on context 1, but no lazy release.  Still no reuse.
537     gl1->Flush();
538     ResApi::Gen(gl2, 1, &id3);
539     EXPECT_NE(id1, id3);
540 
541     // Lazy release triggered by another Delete.  Should reuse id1.
542     ResApi::Delete(gl1, 1, &id2);
543     ResApi::Gen(gl2, 1, &id3);
544     EXPECT_EQ(id1, id3);
545   }
546 
547   // Same as CrossContextGenerationTest(), but triggers an Auto Flush on
548   // the Delete().  Tests an edge case regression.
549   template <class ResApi>
CrossContextGenerationAutoFlushTest()550   void CrossContextGenerationAutoFlushTest() {
551     GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
552     GLES2Implementation* gl2 = test_contexts_[1].gl_.get();
553     GLuint id1, id2, id3;
554 
555     // Delete, no flush on context 1.  No reuse.
556     // By half filling the buffer, an internal flush is forced on the Delete().
557     ResApi::Gen(gl1, 1, &id1);
558     gl1->helper()->Noop(kNumCommandEntries / 2);
559     ResApi::Delete(gl1, 1, &id1);
560     ResApi::Gen(gl1, 1, &id2);
561     EXPECT_NE(id1, id2);
562 
563     // Flush context 2.  Still no reuse.
564     gl2->Flush();
565     ResApi::Gen(gl2, 1, &id3);
566     EXPECT_NE(id1, id3);
567     EXPECT_NE(id2, id3);
568 
569     // Flush on context 1, but no lazy release.  Still no reuse.
570     gl1->Flush();
571     ResApi::Gen(gl2, 1, &id3);
572     EXPECT_NE(id1, id3);
573 
574     // Lazy release triggered by another Delete.  Should reuse id1.
575     ResApi::Delete(gl1, 1, &id2);
576     ResApi::Gen(gl2, 1, &id3);
577     EXPECT_EQ(id1, id3);
578   }
579 
580   // Require that deleting definitely-invalid IDs produces an error.
581   template <class ResApi>
DeletingInvalidIdGeneratesError()582   void DeletingInvalidIdGeneratesError() {
583     GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
584     GLuint id1;
585     ResApi::Gen(gl1, 1, &id1);
586     const GLuint kDefinitelyInvalidId = 0xBEEF;
587     EXPECT_EQ(GL_NO_ERROR, CheckError());
588     ResApi::Delete(gl1, 1, &kDefinitelyInvalidId);
589     EXPECT_EQ(GL_INVALID_VALUE, CheckError());
590   }
591 
592   // Require that double-deleting IDs produces an error.
593   template <class ResApi>
DoubleDeletingIdGeneratesError()594   void DoubleDeletingIdGeneratesError() {
595     GLES2Implementation* gl1 = test_contexts_[0].gl_.get();
596     GLuint id1;
597     ResApi::Gen(gl1, 1, &id1);
598     ResApi::Delete(gl1, 1, &id1);
599     EXPECT_EQ(GL_NO_ERROR, CheckError());
600     ResApi::Delete(gl1, 1, &id1);
601     EXPECT_EQ(GL_INVALID_VALUE, CheckError());
602   }
603 };
604 
SetUp()605 void GLES2ImplementationStrictSharedTest::SetUp() {
606   ContextInitOptions init_options;
607   init_options.bind_generates_resource_client = false;
608   init_options.bind_generates_resource_service = false;
609   ASSERT_TRUE(Initialize(init_options));
610 }
611 
612 class GLES3ImplementationTest : public GLES2ImplementationTest {
613  protected:
614   void SetUp() override;
615 };
616 
SetUp()617 void GLES3ImplementationTest::SetUp() {
618   ContextInitOptions init_options;
619   init_options.major_version = 3;
620   init_options.minor_version = 0;
621   ASSERT_TRUE(Initialize(init_options));
622 }
623 
624 // GCC requires these declarations, but MSVC requires they not be present
625 #ifndef _MSC_VER
626 const uint8_t GLES2ImplementationTest::kInitialValue;
627 const int32_t GLES2ImplementationTest::kNumCommandEntries;
628 const int32_t GLES2ImplementationTest::kCommandBufferSizeBytes;
629 const size_t GLES2ImplementationTest::kTransferBufferSize;
630 const GLint GLES2ImplementationTest::kMaxCombinedTextureImageUnits;
631 const GLint GLES2ImplementationTest::kMaxCubeMapTextureSize;
632 const GLint GLES2ImplementationTest::kMaxFragmentUniformVectors;
633 const GLint GLES2ImplementationTest::kMaxRenderbufferSize;
634 const GLint GLES2ImplementationTest::kMaxTextureImageUnits;
635 const GLint GLES2ImplementationTest::kMaxTextureSize;
636 const GLint GLES2ImplementationTest::kMaxVaryingVectors;
637 const GLint GLES2ImplementationTest::kMaxVertexAttribs;
638 const GLint GLES2ImplementationTest::kMaxVertexTextureImageUnits;
639 const GLint GLES2ImplementationTest::kMaxVertexUniformVectors;
640 const GLint GLES2ImplementationTest::kNumCompressedTextureFormats;
641 const GLint GLES2ImplementationTest::kNumShaderBinaryFormats;
642 const GLuint GLES2ImplementationTest::kStartId;
643 const GLuint GLES2ImplementationTest::kBuffersStartId;
644 const GLuint GLES2ImplementationTest::kFramebuffersStartId;
645 const GLuint GLES2ImplementationTest::kProgramsAndShadersStartId;
646 const GLuint GLES2ImplementationTest::kRenderbuffersStartId;
647 const GLuint GLES2ImplementationTest::kSamplersStartId;
648 const GLuint GLES2ImplementationTest::kTexturesStartId;
649 const GLuint GLES2ImplementationTest::kTransformFeedbacksStartId;
650 const GLuint GLES2ImplementationTest::kQueriesStartId;
651 const GLuint GLES2ImplementationTest::kVertexArraysStartId;
652 #endif
653 
TEST_F(GLES2ImplementationTest,Basic)654 TEST_F(GLES2ImplementationTest, Basic) {
655   EXPECT_TRUE(gl_->share_group());
656 }
657 
TEST_F(GLES2ImplementationTest,GetBucketContents)658 TEST_F(GLES2ImplementationTest, GetBucketContents) {
659   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
660   const uint32_t kTestSize = MaxTransferBufferSize() + 32;
661 
662   std::unique_ptr<uint8_t[]> buf(new uint8_t[kTestSize]);
663   uint8_t* expected_data = buf.get();
664   for (uint32_t ii = 0; ii < kTestSize; ++ii) {
665     expected_data[ii] = ii * 3;
666   }
667 
668   struct Cmds {
669     cmd::GetBucketStart get_bucket_start;
670     cmd::SetToken set_token1;
671     cmd::GetBucketData get_bucket_data;
672     cmd::SetToken set_token2;
673     cmd::SetBucketSize set_bucket_size2;
674   };
675 
676   ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
677   ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32_t));
678   ExpectedMemoryInfo mem2 = GetExpectedMemory(
679       kTestSize - MaxTransferBufferSize());
680 
681   Cmds expected;
682   expected.get_bucket_start.Init(
683       kBucketId, result1.id, result1.offset,
684       MaxTransferBufferSize(), mem1.id, mem1.offset);
685   expected.set_token1.Init(GetNextToken());
686   expected.get_bucket_data.Init(
687       kBucketId, MaxTransferBufferSize(),
688       kTestSize - MaxTransferBufferSize(), mem2.id, mem2.offset);
689   expected.set_bucket_size2.Init(kBucketId, 0);
690   expected.set_token2.Init(GetNextToken());
691 
692   EXPECT_CALL(*command_buffer(), OnFlush())
693       .WillOnce(DoAll(
694           SetMemory(result1.ptr, kTestSize),
695           SetMemoryFromArray(
696               mem1.ptr, expected_data, MaxTransferBufferSize())))
697       .WillOnce(SetMemoryFromArray(
698           mem2.ptr, expected_data + MaxTransferBufferSize(),
699           kTestSize - MaxTransferBufferSize()))
700       .RetiresOnSaturation();
701 
702   std::vector<int8_t> data;
703   GetBucketContents(kBucketId, &data);
704   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
705   ASSERT_EQ(kTestSize, data.size());
706   EXPECT_EQ(0, memcmp(expected_data, &data[0], data.size()));
707 }
708 
TEST_F(GLES2ImplementationTest,GetShaderPrecisionFormat)709 TEST_F(GLES2ImplementationTest, GetShaderPrecisionFormat) {
710   struct Cmds {
711     cmds::GetShaderPrecisionFormat cmd;
712   };
713   typedef cmds::GetShaderPrecisionFormat::Result Result;
714   const unsigned kDummyType1 = 3;
715   const unsigned kDummyType2 = 4;
716 
717   // The first call for dummy type 1 should trigger a command buffer request.
718   GLint range1[2] = {0, 0};
719   GLint precision1 = 0;
720   Cmds expected1;
721   ExpectedMemoryInfo client_result1 = GetExpectedResultMemory(4);
722   expected1.cmd.Init(GL_FRAGMENT_SHADER, kDummyType1, client_result1.id,
723                      client_result1.offset);
724   Result server_result1 = {true, 14, 14, 10};
725   EXPECT_CALL(*command_buffer(), OnFlush())
726       .WillOnce(SetMemory(client_result1.ptr, server_result1))
727       .RetiresOnSaturation();
728   gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, kDummyType1, range1,
729                                 &precision1);
730   const void* commands2 = GetPut();
731   EXPECT_NE(commands_, commands2);
732   EXPECT_EQ(0, memcmp(&expected1, commands_, sizeof(expected1)));
733   EXPECT_EQ(range1[0], 14);
734   EXPECT_EQ(range1[1], 14);
735   EXPECT_EQ(precision1, 10);
736 
737   // The second call for dummy type 1 should use the cached value and avoid
738   // triggering a command buffer request, so we do not expect a call to
739   // OnFlush() here. We do expect the results to be correct though.
740   GLint range2[2] = {0, 0};
741   GLint precision2 = 0;
742   gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, kDummyType1, range2,
743                                 &precision2);
744   const void* commands3 = GetPut();
745   EXPECT_EQ(commands2, commands3);
746   EXPECT_EQ(range2[0], 14);
747   EXPECT_EQ(range2[1], 14);
748   EXPECT_EQ(precision2, 10);
749 
750   // If we then make a request for dummy type 2, we should get another command
751   // buffer request since it hasn't been cached yet.
752   GLint range3[2] = {0, 0};
753   GLint precision3 = 0;
754   Cmds expected3;
755   ExpectedMemoryInfo result3 = GetExpectedResultMemory(4);
756   expected3.cmd.Init(GL_FRAGMENT_SHADER, kDummyType2, result3.id,
757                      result3.offset);
758   Result result3_source = {true, 62, 62, 16};
759   EXPECT_CALL(*command_buffer(), OnFlush())
760       .WillOnce(SetMemory(result3.ptr, result3_source))
761       .RetiresOnSaturation();
762   gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, kDummyType2, range3,
763                                 &precision3);
764   const void* commands4 = GetPut();
765   EXPECT_NE(commands3, commands4);
766   EXPECT_EQ(0, memcmp(&expected3, commands3, sizeof(expected3)));
767   EXPECT_EQ(range3[0], 62);
768   EXPECT_EQ(range3[1], 62);
769   EXPECT_EQ(precision3, 16);
770 
771   // Any call for predefined types should use the cached value from the
772   // Capabilities  and avoid triggering a command buffer request, so we do not
773   // expect a call to OnFlush() here. We do expect the results to be correct
774   // though.
775   GLint range4[2] = {0, 0};
776   GLint precision4 = 0;
777   gl_->GetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT, range4,
778                                 &precision4);
779   const void* commands5 = GetPut();
780   EXPECT_EQ(commands4, commands5);
781   EXPECT_EQ(range4[0], 3);
782   EXPECT_EQ(range4[1], 5);
783   EXPECT_EQ(precision4, 7);
784 }
785 
TEST_F(GLES2ImplementationTest,GetShaderSource)786 TEST_F(GLES2ImplementationTest, GetShaderSource) {
787   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
788   const GLuint kShaderId = 456;
789   const Str7 kString = {"foobar"};
790   const char kBad = 0x12;
791   struct Cmds {
792     cmd::SetBucketSize set_bucket_size1;
793     cmds::GetShaderSource get_shader_source;
794     cmd::GetBucketStart get_bucket_start;
795     cmd::SetToken set_token1;
796     cmd::SetBucketSize set_bucket_size2;
797   };
798 
799   ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
800   ExpectedMemoryInfo result1 = GetExpectedResultMemory(sizeof(uint32_t));
801 
802   Cmds expected;
803   expected.set_bucket_size1.Init(kBucketId, 0);
804   expected.get_shader_source.Init(kShaderId, kBucketId);
805   expected.get_bucket_start.Init(
806       kBucketId, result1.id, result1.offset,
807       MaxTransferBufferSize(), mem1.id, mem1.offset);
808   expected.set_token1.Init(GetNextToken());
809   expected.set_bucket_size2.Init(kBucketId, 0);
810   char buf[sizeof(kString) + 1];
811   memset(buf, kBad, sizeof(buf));
812 
813   EXPECT_CALL(*command_buffer(), OnFlush())
814       .WillOnce(DoAll(SetMemory(result1.ptr, uint32_t(sizeof(kString))),
815                       SetMemory(mem1.ptr, kString)))
816       .RetiresOnSaturation();
817 
818   GLsizei length = 0;
819   gl_->GetShaderSource(kShaderId, sizeof(buf), &length, buf);
820   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
821   EXPECT_EQ(sizeof(kString) - 1, static_cast<size_t>(length));
822   EXPECT_STREQ(kString.str, buf);
823   EXPECT_EQ(buf[sizeof(kString)], kBad);
824 }
825 
826 #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
827 
TEST_F(GLES2ImplementationTest,DrawArraysClientSideBuffers)828 TEST_F(GLES2ImplementationTest, DrawArraysClientSideBuffers) {
829   static const float verts[][4] = {
830     { 12.0f, 23.0f, 34.0f, 45.0f, },
831     { 56.0f, 67.0f, 78.0f, 89.0f, },
832     { 13.0f, 24.0f, 35.0f, 46.0f, },
833   };
834   struct Cmds {
835     cmds::EnableVertexAttribArray enable1;
836     cmds::EnableVertexAttribArray enable2;
837     cmds::BindBuffer bind_to_emu;
838     cmds::BufferData set_size;
839     cmds::BufferSubData copy_data1;
840     cmd::SetToken set_token1;
841     cmds::VertexAttribPointer set_pointer1;
842     cmds::BufferSubData copy_data2;
843     cmd::SetToken set_token2;
844     cmds::VertexAttribPointer set_pointer2;
845     cmds::DrawArrays draw;
846     cmds::BindBuffer restore;
847   };
848   const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
849   const GLuint kAttribIndex1 = 1;
850   const GLuint kAttribIndex2 = 3;
851   const GLint kNumComponents1 = 3;
852   const GLint kNumComponents2 = 2;
853   const GLsizei kClientStride = sizeof(verts[0]);
854   const GLint kFirst = 1;
855   const GLsizei kCount = 2;
856   const GLsizei kSize1 =
857       base::size(verts) * kNumComponents1 * sizeof(verts[0][0]);
858   const GLsizei kSize2 =
859       base::size(verts) * kNumComponents2 * sizeof(verts[0][0]);
860   const GLsizei kEmuOffset1 = 0;
861   const GLsizei kEmuOffset2 = kSize1;
862   const GLsizei kTotalSize = kSize1 + kSize2;
863 
864   ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1);
865   ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2);
866 
867   Cmds expected;
868   expected.enable1.Init(kAttribIndex1);
869   expected.enable2.Init(kAttribIndex2);
870   expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
871   expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
872   expected.copy_data1.Init(
873       GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset);
874   expected.set_token1.Init(GetNextToken());
875   expected.set_pointer1.Init(
876       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
877   expected.copy_data2.Init(
878       GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset);
879   expected.set_token2.Init(GetNextToken());
880   expected.set_pointer2.Init(
881       kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
882   expected.draw.Init(GL_POINTS, kFirst, kCount);
883   expected.restore.Init(GL_ARRAY_BUFFER, 0);
884   gl_->EnableVertexAttribArray(kAttribIndex1);
885   gl_->EnableVertexAttribArray(kAttribIndex2);
886   gl_->VertexAttribPointer(
887       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts);
888   gl_->VertexAttribPointer(
889       kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts);
890   gl_->DrawArrays(GL_POINTS, kFirst, kCount);
891   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
892 }
893 
TEST_F(GLES2ImplementationTest,DrawArraysInstancedANGLEClientSideBuffers)894 TEST_F(GLES2ImplementationTest, DrawArraysInstancedANGLEClientSideBuffers) {
895   static const float verts[][4] = {
896     { 12.0f, 23.0f, 34.0f, 45.0f, },
897     { 56.0f, 67.0f, 78.0f, 89.0f, },
898     { 13.0f, 24.0f, 35.0f, 46.0f, },
899   };
900   struct Cmds {
901     cmds::EnableVertexAttribArray enable1;
902     cmds::EnableVertexAttribArray enable2;
903     cmds::VertexAttribDivisorANGLE divisor;
904     cmds::BindBuffer bind_to_emu;
905     cmds::BufferData set_size;
906     cmds::BufferSubData copy_data1;
907     cmd::SetToken set_token1;
908     cmds::VertexAttribPointer set_pointer1;
909     cmds::BufferSubData copy_data2;
910     cmd::SetToken set_token2;
911     cmds::VertexAttribPointer set_pointer2;
912     cmds::DrawArraysInstancedANGLE draw;
913     cmds::BindBuffer restore;
914   };
915   const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
916   const GLuint kAttribIndex1 = 1;
917   const GLuint kAttribIndex2 = 3;
918   const GLint kNumComponents1 = 3;
919   const GLint kNumComponents2 = 2;
920   const GLsizei kClientStride = sizeof(verts[0]);
921   const GLint kFirst = 1;
922   const GLsizei kCount = 2;
923   const GLuint kDivisor = 1;
924   const GLsizei kSize1 =
925       base::size(verts) * kNumComponents1 * sizeof(verts[0][0]);
926   const GLsizei kSize2 =
927       1 * kNumComponents2 * sizeof(verts[0][0]);
928   const GLsizei kEmuOffset1 = 0;
929   const GLsizei kEmuOffset2 = kSize1;
930   const GLsizei kTotalSize = kSize1 + kSize2;
931 
932   ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize1);
933   ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize2);
934 
935   Cmds expected;
936   expected.enable1.Init(kAttribIndex1);
937   expected.enable2.Init(kAttribIndex2);
938   expected.divisor.Init(kAttribIndex2, kDivisor);
939   expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
940   expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
941   expected.copy_data1.Init(
942       GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem1.id, mem1.offset);
943   expected.set_token1.Init(GetNextToken());
944   expected.set_pointer1.Init(
945       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
946   expected.copy_data2.Init(
947       GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem2.id, mem2.offset);
948   expected.set_token2.Init(GetNextToken());
949   expected.set_pointer2.Init(
950       kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
951   expected.draw.Init(GL_POINTS, kFirst, kCount, 1);
952   expected.restore.Init(GL_ARRAY_BUFFER, 0);
953   gl_->EnableVertexAttribArray(kAttribIndex1);
954   gl_->EnableVertexAttribArray(kAttribIndex2);
955   gl_->VertexAttribPointer(
956       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride, verts);
957   gl_->VertexAttribPointer(
958       kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE, kClientStride, verts);
959   gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor);
960   gl_->DrawArraysInstancedANGLE(GL_POINTS, kFirst, kCount, 1);
961   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
962 }
963 
TEST_F(GLES2ImplementationTest,DrawElementsClientSideBuffers)964 TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffers) {
965   static const float verts[][4] = {
966     { 12.0f, 23.0f, 34.0f, 45.0f, },
967     { 56.0f, 67.0f, 78.0f, 89.0f, },
968     { 13.0f, 24.0f, 35.0f, 46.0f, },
969   };
970   static const uint16_t indices[] = {
971       1, 2,
972   };
973   struct Cmds {
974     cmds::EnableVertexAttribArray enable1;
975     cmds::EnableVertexAttribArray enable2;
976     cmds::BindBuffer bind_to_index_emu;
977     cmds::BufferData set_index_size;
978     cmds::BufferSubData copy_data0;
979     cmd::SetToken set_token0;
980     cmds::BindBuffer bind_to_emu;
981     cmds::BufferData set_size;
982     cmds::BufferSubData copy_data1;
983     cmd::SetToken set_token1;
984     cmds::VertexAttribPointer set_pointer1;
985     cmds::BufferSubData copy_data2;
986     cmd::SetToken set_token2;
987     cmds::VertexAttribPointer set_pointer2;
988     cmds::DrawElements draw;
989     cmds::BindBuffer restore;
990     cmds::BindBuffer restore_element;
991   };
992   const GLsizei kIndexSize = sizeof(indices);
993   const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
994   const GLuint kEmuIndexBufferId =
995       GLES2Implementation::kClientSideElementArrayId;
996   const GLuint kAttribIndex1 = 1;
997   const GLuint kAttribIndex2 = 3;
998   const GLint kNumComponents1 = 3;
999   const GLint kNumComponents2 = 2;
1000   const GLsizei kClientStride = sizeof(verts[0]);
1001   const GLsizei kCount = 2;
1002   const GLsizei kSize1 =
1003       base::size(verts) * kNumComponents1 * sizeof(verts[0][0]);
1004   const GLsizei kSize2 =
1005       base::size(verts) * kNumComponents2 * sizeof(verts[0][0]);
1006   const GLsizei kEmuOffset1 = 0;
1007   const GLsizei kEmuOffset2 = kSize1;
1008   const GLsizei kTotalSize = kSize1 + kSize2;
1009 
1010   ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1011   ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1012   ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1013 
1014   Cmds expected;
1015   expected.enable1.Init(kAttribIndex1);
1016   expected.enable2.Init(kAttribIndex2);
1017   expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1018   expected.set_index_size.Init(
1019       GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1020   expected.copy_data0.Init(
1021       GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1022   expected.set_token0.Init(GetNextToken());
1023   expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1024   expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1025   expected.copy_data1.Init(
1026       GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1027   expected.set_token1.Init(GetNextToken());
1028   expected.set_pointer1.Init(
1029       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1030   expected.copy_data2.Init(
1031       GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1032   expected.set_token2.Init(GetNextToken());
1033   expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1034                              GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1035   expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0);
1036   expected.restore.Init(GL_ARRAY_BUFFER, 0);
1037   expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1038   gl_->EnableVertexAttribArray(kAttribIndex1);
1039   gl_->EnableVertexAttribArray(kAttribIndex2);
1040   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1041                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1042   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1043                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1044   gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices);
1045   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1046 }
1047 
TEST_F(GLES2ImplementationTest,DrawElementsClientSideBuffersIndexUint)1048 TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersIndexUint) {
1049   static const float verts[][4] = {
1050     { 12.0f, 23.0f, 34.0f, 45.0f, },
1051     { 56.0f, 67.0f, 78.0f, 89.0f, },
1052     { 13.0f, 24.0f, 35.0f, 46.0f, },
1053   };
1054   static const uint32_t indices[] = {
1055       1, 2,
1056   };
1057   struct Cmds {
1058     cmds::EnableVertexAttribArray enable1;
1059     cmds::EnableVertexAttribArray enable2;
1060     cmds::BindBuffer bind_to_index_emu;
1061     cmds::BufferData set_index_size;
1062     cmds::BufferSubData copy_data0;
1063     cmd::SetToken set_token0;
1064     cmds::BindBuffer bind_to_emu;
1065     cmds::BufferData set_size;
1066     cmds::BufferSubData copy_data1;
1067     cmd::SetToken set_token1;
1068     cmds::VertexAttribPointer set_pointer1;
1069     cmds::BufferSubData copy_data2;
1070     cmd::SetToken set_token2;
1071     cmds::VertexAttribPointer set_pointer2;
1072     cmds::DrawElements draw;
1073     cmds::BindBuffer restore;
1074     cmds::BindBuffer restore_element;
1075   };
1076   const GLsizei kIndexSize = sizeof(indices);
1077   const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1078   const GLuint kEmuIndexBufferId =
1079       GLES2Implementation::kClientSideElementArrayId;
1080   const GLuint kAttribIndex1 = 1;
1081   const GLuint kAttribIndex2 = 3;
1082   const GLint kNumComponents1 = 3;
1083   const GLint kNumComponents2 = 2;
1084   const GLsizei kClientStride = sizeof(verts[0]);
1085   const GLsizei kCount = 2;
1086   const GLsizei kSize1 =
1087       base::size(verts) * kNumComponents1 * sizeof(verts[0][0]);
1088   const GLsizei kSize2 =
1089       base::size(verts) * kNumComponents2 * sizeof(verts[0][0]);
1090   const GLsizei kEmuOffset1 = 0;
1091   const GLsizei kEmuOffset2 = kSize1;
1092   const GLsizei kTotalSize = kSize1 + kSize2;
1093 
1094   ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1095   ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1096   ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1097 
1098   Cmds expected;
1099   expected.enable1.Init(kAttribIndex1);
1100   expected.enable2.Init(kAttribIndex2);
1101   expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1102   expected.set_index_size.Init(
1103       GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1104   expected.copy_data0.Init(
1105       GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1106   expected.set_token0.Init(GetNextToken());
1107   expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1108   expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1109   expected.copy_data1.Init(
1110       GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1111   expected.set_token1.Init(GetNextToken());
1112   expected.set_pointer1.Init(
1113       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1114   expected.copy_data2.Init(
1115       GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1116   expected.set_token2.Init(GetNextToken());
1117   expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1118                              GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1119   expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_INT, 0);
1120   expected.restore.Init(GL_ARRAY_BUFFER, 0);
1121   expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1122   gl_->EnableVertexAttribArray(kAttribIndex1);
1123   gl_->EnableVertexAttribArray(kAttribIndex2);
1124   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1125                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1126   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1127                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1128   gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices);
1129   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1130 }
1131 
TEST_F(GLES2ImplementationTest,DrawElementsClientSideBuffersInvalidIndexUint)1132 TEST_F(GLES2ImplementationTest, DrawElementsClientSideBuffersInvalidIndexUint) {
1133   static const float verts[][4] = {
1134     { 12.0f, 23.0f, 34.0f, 45.0f, },
1135     { 56.0f, 67.0f, 78.0f, 89.0f, },
1136     { 13.0f, 24.0f, 35.0f, 46.0f, },
1137   };
1138   static const uint32_t indices[] = {1, 0x90000000};
1139 
1140   const GLuint kAttribIndex1 = 1;
1141   const GLuint kAttribIndex2 = 3;
1142   const GLint kNumComponents1 = 3;
1143   const GLint kNumComponents2 = 2;
1144   const GLsizei kClientStride = sizeof(verts[0]);
1145   const GLsizei kCount = 2;
1146 
1147   EXPECT_CALL(*command_buffer(), OnFlush())
1148       .Times(1)
1149       .RetiresOnSaturation();
1150 
1151   gl_->EnableVertexAttribArray(kAttribIndex1);
1152   gl_->EnableVertexAttribArray(kAttribIndex2);
1153   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1154                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1155   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1156                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1157   gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_INT, indices);
1158 
1159   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
1160 }
1161 
TEST_F(GLES2ImplementationTest,DrawElementsClientSideBuffersServiceSideIndices)1162 TEST_F(GLES2ImplementationTest,
1163        DrawElementsClientSideBuffersServiceSideIndices) {
1164   static const float verts[][4] = {
1165     { 12.0f, 23.0f, 34.0f, 45.0f, },
1166     { 56.0f, 67.0f, 78.0f, 89.0f, },
1167     { 13.0f, 24.0f, 35.0f, 46.0f, },
1168   };
1169   struct Cmds {
1170     cmds::EnableVertexAttribArray enable1;
1171     cmds::EnableVertexAttribArray enable2;
1172     cmds::BindBuffer bind_to_index;
1173     cmds::GetMaxValueInBufferCHROMIUM get_max;
1174     cmds::BindBuffer bind_to_emu;
1175     cmds::BufferData set_size;
1176     cmds::BufferSubData copy_data1;
1177     cmd::SetToken set_token1;
1178     cmds::VertexAttribPointer set_pointer1;
1179     cmds::BufferSubData copy_data2;
1180     cmd::SetToken set_token2;
1181     cmds::VertexAttribPointer set_pointer2;
1182     cmds::DrawElements draw;
1183     cmds::BindBuffer restore;
1184   };
1185   const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1186   const GLuint kClientIndexBufferId = 0x789;
1187   const GLuint kIndexOffset = 0x40;
1188   const GLuint kMaxIndex = 2;
1189   const GLuint kAttribIndex1 = 1;
1190   const GLuint kAttribIndex2 = 3;
1191   const GLint kNumComponents1 = 3;
1192   const GLint kNumComponents2 = 2;
1193   const GLsizei kClientStride = sizeof(verts[0]);
1194   const GLsizei kCount = 2;
1195   const GLsizei kSize1 =
1196       base::size(verts) * kNumComponents1 * sizeof(verts[0][0]);
1197   const GLsizei kSize2 =
1198       base::size(verts) * kNumComponents2 * sizeof(verts[0][0]);
1199   const GLsizei kEmuOffset1 = 0;
1200   const GLsizei kEmuOffset2 = kSize1;
1201   const GLsizei kTotalSize = kSize1 + kSize2;
1202 
1203   ExpectedMemoryInfo mem1 = GetExpectedResultMemory(sizeof(uint32_t));
1204   ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1205   ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1206 
1207 
1208   Cmds expected;
1209   expected.enable1.Init(kAttribIndex1);
1210   expected.enable2.Init(kAttribIndex2);
1211   expected.bind_to_index.Init(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId);
1212   expected.get_max.Init(kClientIndexBufferId, kCount, GL_UNSIGNED_SHORT,
1213                         kIndexOffset, mem1.id, mem1.offset);
1214   expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1215   expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1216   expected.copy_data1.Init(
1217       GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1218   expected.set_token1.Init(GetNextToken());
1219   expected.set_pointer1.Init(kAttribIndex1, kNumComponents1,
1220                              GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1221   expected.copy_data2.Init(
1222       GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1223   expected.set_token2.Init(GetNextToken());
1224   expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1225                              GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1226   expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, kIndexOffset);
1227   expected.restore.Init(GL_ARRAY_BUFFER, 0);
1228 
1229   EXPECT_CALL(*command_buffer(), OnFlush())
1230       .WillOnce(SetMemory(mem1.ptr,kMaxIndex))
1231       .RetiresOnSaturation();
1232 
1233   gl_->EnableVertexAttribArray(kAttribIndex1);
1234   gl_->EnableVertexAttribArray(kAttribIndex2);
1235   gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientIndexBufferId);
1236   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1237                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1238   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1239                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1240   gl_->DrawElements(GL_POINTS, kCount, GL_UNSIGNED_SHORT,
1241                     reinterpret_cast<const void*>(kIndexOffset));
1242   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1243 }
1244 
TEST_F(GLES2ImplementationTest,DrawElementsInstancedANGLEClientSideBuffers)1245 TEST_F(GLES2ImplementationTest, DrawElementsInstancedANGLEClientSideBuffers) {
1246   static const float verts[][4] = {
1247     { 12.0f, 23.0f, 34.0f, 45.0f, },
1248     { 56.0f, 67.0f, 78.0f, 89.0f, },
1249     { 13.0f, 24.0f, 35.0f, 46.0f, },
1250   };
1251   static const uint16_t indices[] = {
1252       1, 2,
1253   };
1254   struct Cmds {
1255     cmds::EnableVertexAttribArray enable1;
1256     cmds::EnableVertexAttribArray enable2;
1257     cmds::VertexAttribDivisorANGLE divisor;
1258     cmds::BindBuffer bind_to_index_emu;
1259     cmds::BufferData set_index_size;
1260     cmds::BufferSubData copy_data0;
1261     cmd::SetToken set_token0;
1262     cmds::BindBuffer bind_to_emu;
1263     cmds::BufferData set_size;
1264     cmds::BufferSubData copy_data1;
1265     cmd::SetToken set_token1;
1266     cmds::VertexAttribPointer set_pointer1;
1267     cmds::BufferSubData copy_data2;
1268     cmd::SetToken set_token2;
1269     cmds::VertexAttribPointer set_pointer2;
1270     cmds::DrawElementsInstancedANGLE draw;
1271     cmds::BindBuffer restore;
1272     cmds::BindBuffer restore_element;
1273   };
1274   const GLsizei kIndexSize = sizeof(indices);
1275   const GLuint kEmuBufferId = GLES2Implementation::kClientSideArrayId;
1276   const GLuint kEmuIndexBufferId =
1277       GLES2Implementation::kClientSideElementArrayId;
1278   const GLuint kAttribIndex1 = 1;
1279   const GLuint kAttribIndex2 = 3;
1280   const GLint kNumComponents1 = 3;
1281   const GLint kNumComponents2 = 2;
1282   const GLsizei kClientStride = sizeof(verts[0]);
1283   const GLsizei kCount = 2;
1284   const GLsizei kSize1 =
1285       base::size(verts) * kNumComponents1 * sizeof(verts[0][0]);
1286   const GLsizei kSize2 =
1287       1 * kNumComponents2 * sizeof(verts[0][0]);
1288   const GLuint kDivisor = 1;
1289   const GLsizei kEmuOffset1 = 0;
1290   const GLsizei kEmuOffset2 = kSize1;
1291   const GLsizei kTotalSize = kSize1 + kSize2;
1292 
1293   ExpectedMemoryInfo mem1 = GetExpectedMemory(kIndexSize);
1294   ExpectedMemoryInfo mem2 = GetExpectedMemory(kSize1);
1295   ExpectedMemoryInfo mem3 = GetExpectedMemory(kSize2);
1296 
1297   Cmds expected;
1298   expected.enable1.Init(kAttribIndex1);
1299   expected.enable2.Init(kAttribIndex2);
1300   expected.divisor.Init(kAttribIndex2, kDivisor);
1301   expected.bind_to_index_emu.Init(GL_ELEMENT_ARRAY_BUFFER, kEmuIndexBufferId);
1302   expected.set_index_size.Init(
1303       GL_ELEMENT_ARRAY_BUFFER, kIndexSize, 0, 0, GL_DYNAMIC_DRAW);
1304   expected.copy_data0.Init(
1305       GL_ELEMENT_ARRAY_BUFFER, 0, kIndexSize, mem1.id, mem1.offset);
1306   expected.set_token0.Init(GetNextToken());
1307   expected.bind_to_emu.Init(GL_ARRAY_BUFFER, kEmuBufferId);
1308   expected.set_size.Init(GL_ARRAY_BUFFER, kTotalSize, 0, 0, GL_DYNAMIC_DRAW);
1309   expected.copy_data1.Init(
1310       GL_ARRAY_BUFFER, kEmuOffset1, kSize1, mem2.id, mem2.offset);
1311   expected.set_token1.Init(GetNextToken());
1312   expected.set_pointer1.Init(
1313       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, 0, kEmuOffset1);
1314   expected.copy_data2.Init(
1315       GL_ARRAY_BUFFER, kEmuOffset2, kSize2, mem3.id, mem3.offset);
1316   expected.set_token2.Init(GetNextToken());
1317   expected.set_pointer2.Init(kAttribIndex2, kNumComponents2,
1318                              GL_FLOAT, GL_FALSE, 0, kEmuOffset2);
1319   expected.draw.Init(GL_POINTS, kCount, GL_UNSIGNED_SHORT, 0, 1);
1320   expected.restore.Init(GL_ARRAY_BUFFER, 0);
1321   expected.restore_element.Init(GL_ELEMENT_ARRAY_BUFFER, 0);
1322   gl_->EnableVertexAttribArray(kAttribIndex1);
1323   gl_->EnableVertexAttribArray(kAttribIndex2);
1324   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1325                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1326   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1327                            GL_FLOAT, GL_FALSE, kClientStride, verts);
1328   gl_->VertexAttribDivisorANGLE(kAttribIndex2, kDivisor);
1329   gl_->DrawElementsInstancedANGLE(
1330       GL_POINTS, kCount, GL_UNSIGNED_SHORT, indices, 1);
1331   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1332 }
1333 
TEST_F(GLES2ImplementationTest,GetVertexBufferPointerv)1334 TEST_F(GLES2ImplementationTest, GetVertexBufferPointerv) {
1335   static const float verts[1] = { 0.0f, };
1336   const GLuint kAttribIndex1 = 1;
1337   const GLuint kAttribIndex2 = 3;
1338   const GLint kNumComponents1 = 3;
1339   const GLint kNumComponents2 = 2;
1340   const GLsizei kStride1 = 12;
1341   const GLsizei kStride2 = 0;
1342   const GLuint kBufferId = 0x123;
1343   const GLint kOffset2 = 0x456;
1344 
1345   // It's all cached on the client side so no get commands are issued.
1346   struct Cmds {
1347     cmds::BindBuffer bind;
1348     cmds::VertexAttribPointer set_pointer;
1349   };
1350 
1351   Cmds expected;
1352   expected.bind.Init(GL_ARRAY_BUFFER, kBufferId);
1353   expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE,
1354                             kStride2, kOffset2);
1355 
1356   // Set one client side buffer.
1357   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1358                            GL_FLOAT, GL_FALSE, kStride1, verts);
1359   // Set one VBO
1360   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
1361   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1362                            GL_FLOAT, GL_FALSE, kStride2,
1363                            reinterpret_cast<const void*>(kOffset2));
1364   // now get them both.
1365   void* ptr1 = nullptr;
1366   void* ptr2 = nullptr;
1367 
1368   gl_->GetVertexAttribPointerv(
1369       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr1);
1370   gl_->GetVertexAttribPointerv(
1371       kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_POINTER, &ptr2);
1372 
1373   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1374   EXPECT_TRUE(static_cast<const void*>(&verts) == ptr1);
1375   EXPECT_TRUE(ptr2 == reinterpret_cast<void*>(kOffset2));
1376 }
1377 
TEST_F(GLES2ImplementationTest,GetVertexAttrib)1378 TEST_F(GLES2ImplementationTest, GetVertexAttrib) {
1379   static const float verts[1] = { 0.0f, };
1380   const GLuint kAttribIndex1 = 1;
1381   const GLuint kAttribIndex2 = 3;
1382   const GLint kNumComponents1 = 3;
1383   const GLint kNumComponents2 = 2;
1384   const GLsizei kStride1 = 12;
1385   const GLsizei kStride2 = 0;
1386   const GLuint kBufferId = 0x123;
1387   const GLint kOffset2 = 0x456;
1388 
1389   // Only one set and one get because the client side buffer's info is stored
1390   // on the client side.
1391   struct Cmds {
1392     cmds::EnableVertexAttribArray enable;
1393     cmds::BindBuffer bind;
1394     cmds::VertexAttribPointer set_pointer;
1395     cmds::GetVertexAttribfv get2;  // for getting the value from attrib1
1396   };
1397 
1398   ExpectedMemoryInfo mem2 = GetExpectedResultMemory(16);
1399 
1400   Cmds expected;
1401   expected.enable.Init(kAttribIndex1);
1402   expected.bind.Init(GL_ARRAY_BUFFER, kBufferId);
1403   expected.set_pointer.Init(kAttribIndex2, kNumComponents2, GL_FLOAT, GL_FALSE,
1404                             kStride2, kOffset2);
1405   expected.get2.Init(kAttribIndex1,
1406                      GL_CURRENT_VERTEX_ATTRIB,
1407                      mem2.id, mem2.offset);
1408 
1409   FourFloats current_attrib(1.2f, 3.4f, 5.6f, 7.8f);
1410 
1411   // One call to flush to wait for last call to GetVertexAttribiv
1412   // as others are all cached.
1413   EXPECT_CALL(*command_buffer(), OnFlush())
1414       .WillOnce(SetMemory(
1415           mem2.ptr, SizedResultHelper<FourFloats>(current_attrib)))
1416       .RetiresOnSaturation();
1417 
1418   gl_->EnableVertexAttribArray(kAttribIndex1);
1419   // Set one client side buffer.
1420   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1,
1421                            GL_FLOAT, GL_FALSE, kStride1, verts);
1422   // Set one VBO
1423   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
1424   gl_->VertexAttribPointer(kAttribIndex2, kNumComponents2,
1425                            GL_FLOAT, GL_FALSE, kStride2,
1426                            reinterpret_cast<const void*>(kOffset2));
1427   // first get the service side once to see that we make a command
1428   GLint buffer_id = 0;
1429   GLint enabled = 0;
1430   GLint size = 0;
1431   GLint stride = 0;
1432   GLint type = 0;
1433   GLint normalized = 1;
1434   float current[4] = { 0.0f, };
1435 
1436   gl_->GetVertexAttribiv(
1437       kAttribIndex2, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id);
1438   EXPECT_EQ(kBufferId, static_cast<GLuint>(buffer_id));
1439   gl_->GetVertexAttribiv(
1440       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_id);
1441   gl_->GetVertexAttribiv(
1442       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
1443   gl_->GetVertexAttribiv(
1444       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_SIZE, &size);
1445   gl_->GetVertexAttribiv(
1446       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &stride);
1447   gl_->GetVertexAttribiv(
1448       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_TYPE, &type);
1449   gl_->GetVertexAttribiv(
1450       kAttribIndex1, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &normalized);
1451   gl_->GetVertexAttribfv(
1452       kAttribIndex1, GL_CURRENT_VERTEX_ATTRIB, &current[0]);
1453 
1454   EXPECT_EQ(0, buffer_id);
1455   EXPECT_EQ(GL_TRUE, enabled);
1456   EXPECT_EQ(kNumComponents1, size);
1457   EXPECT_EQ(kStride1, stride);
1458   EXPECT_EQ(GL_FLOAT, type);
1459   EXPECT_EQ(GL_FALSE, normalized);
1460   EXPECT_EQ(0, memcmp(&current_attrib, &current, sizeof(current_attrib)));
1461 
1462   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1463 }
1464 
TEST_F(GLES2ImplementationTest,ReservedIds)1465 TEST_F(GLES2ImplementationTest, ReservedIds) {
1466   // Only the get error command should be issued.
1467   struct Cmds {
1468     cmds::GetError get;
1469   };
1470   Cmds expected;
1471 
1472   ExpectedMemoryInfo mem1 = GetExpectedResultMemory(
1473       sizeof(cmds::GetError::Result));
1474 
1475   expected.get.Init(mem1.id, mem1.offset);
1476 
1477   // One call to flush to wait for GetError
1478   EXPECT_CALL(*command_buffer(), OnFlush())
1479       .WillOnce(SetMemory(mem1.ptr, GLuint(GL_NO_ERROR)))
1480       .RetiresOnSaturation();
1481 
1482   gl_->BindBuffer(
1483       GL_ARRAY_BUFFER,
1484       GLES2Implementation::kClientSideArrayId);
1485   gl_->BindBuffer(
1486       GL_ARRAY_BUFFER,
1487       GLES2Implementation::kClientSideElementArrayId);
1488   GLenum err = gl_->GetError();
1489   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), err);
1490   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1491 }
1492 
1493 #endif  // defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
1494 
TEST_F(GLES2ImplementationTest,ReadPixels2Reads)1495 TEST_F(GLES2ImplementationTest, ReadPixels2Reads) {
1496   struct Cmds {
1497     cmds::ReadPixels read1;
1498     cmd::SetToken set_token1;
1499     cmds::ReadPixels read2;
1500     cmd::SetToken set_token2;
1501   };
1502   const GLint kBytesPerPixel = 4;
1503   const GLint kWidth =
1504       (kTransferBufferSize - GLES2Implementation::kStartingOffset) /
1505       kBytesPerPixel;
1506   const GLint kHeight = 2;
1507   const GLenum kFormat = GL_RGBA;
1508   const GLenum kType = GL_UNSIGNED_BYTE;
1509 
1510   ExpectedMemoryInfo mem1 =
1511       GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel);
1512   ExpectedMemoryInfo result1 =
1513       GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1514   ExpectedMemoryInfo mem2 =
1515       GetExpectedMemory(kWidth * kHeight / 2 * kBytesPerPixel);
1516   ExpectedMemoryInfo result2 =
1517       GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1518 
1519   Cmds expected;
1520   expected.read1.Init(
1521       0, 0, kWidth, kHeight / 2, kFormat, kType,
1522       mem1.id, mem1.offset, result1.id, result1.offset,
1523       false);
1524   expected.set_token1.Init(GetNextToken());
1525   expected.read2.Init(
1526       0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
1527       mem2.id, mem2.offset, result2.id, result2.offset, false);
1528   expected.set_token2.Init(GetNextToken());
1529   std::unique_ptr<int8_t[]> buffer(
1530       new int8_t[kWidth * kHeight * kBytesPerPixel]);
1531 
1532   EXPECT_CALL(*command_buffer(), OnFlush())
1533       .WillOnce(SetMemory(result1.ptr, static_cast<uint32_t>(1)))
1534       .WillOnce(SetMemory(result2.ptr, static_cast<uint32_t>(1)))
1535       .RetiresOnSaturation();
1536 
1537   gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get());
1538   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1539 }
1540 
TEST_F(GLES2ImplementationTest,ReadPixelsBadFormatType)1541 TEST_F(GLES2ImplementationTest, ReadPixelsBadFormatType) {
1542   struct Cmds {
1543     cmds::ReadPixels read;
1544     cmd::SetToken set_token;
1545   };
1546   const GLint kBytesPerPixel = 4;
1547   const GLint kWidth = 2;
1548   const GLint kHeight = 2;
1549   const GLenum kFormat = 0;
1550   const GLenum kType = 0;
1551 
1552   ExpectedMemoryInfo mem1 =
1553       GetExpectedMemory(kWidth * kHeight * kBytesPerPixel);
1554   ExpectedMemoryInfo result1 =
1555       GetExpectedResultMemory(sizeof(cmds::ReadPixels::Result));
1556 
1557   Cmds expected;
1558   expected.read.Init(
1559       0, 0, kWidth, kHeight, kFormat, kType,
1560       mem1.id, mem1.offset, result1.id, result1.offset, false);
1561   expected.set_token.Init(GetNextToken());
1562   std::unique_ptr<int8_t[]> buffer(
1563       new int8_t[kWidth * kHeight * kBytesPerPixel]);
1564 
1565   EXPECT_CALL(*command_buffer(), OnFlush())
1566       .Times(1)
1567       .RetiresOnSaturation();
1568 
1569   gl_->ReadPixels(0, 0, kWidth, kHeight, kFormat, kType, buffer.get());
1570 }
1571 
TEST_F(GLES2ImplementationTest,FreeUnusedSharedMemory)1572 TEST_F(GLES2ImplementationTest, FreeUnusedSharedMemory) {
1573   struct Cmds {
1574     cmds::BufferSubData buf;
1575     cmd::SetToken set_token;
1576   };
1577   const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1578   const GLintptr kOffset = 15;
1579   const GLsizeiptr kSize = 16;
1580 
1581   ExpectedMemoryInfo mem1 = GetExpectedMemory(kSize);
1582 
1583   Cmds expected;
1584   expected.buf.Init(
1585     kTarget, kOffset, kSize, mem1.id, mem1.offset);
1586   expected.set_token.Init(GetNextToken());
1587 
1588   void* mem = gl_->MapBufferSubDataCHROMIUM(
1589       kTarget, kOffset, kSize, GL_WRITE_ONLY);
1590   ASSERT_TRUE(mem != nullptr);
1591   gl_->UnmapBufferSubDataCHROMIUM(mem);
1592   EXPECT_CALL(*command_buffer(), DestroyTransferBuffer(_))
1593       .Times(1)
1594       .RetiresOnSaturation();
1595   gl_->FreeUnusedSharedMemory();
1596 }
1597 
TEST_F(GLES2ImplementationTest,MapUnmapBufferSubDataCHROMIUM)1598 TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUM) {
1599   struct Cmds {
1600     cmds::BufferSubData buf;
1601     cmd::SetToken set_token;
1602   };
1603   const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1604   const GLintptr kOffset = 15;
1605   const GLsizeiptr kSize = 16;
1606 
1607   uint32_t offset = 0;
1608   Cmds expected;
1609   expected.buf.Init(
1610       kTarget, kOffset, kSize,
1611       command_buffer()->GetNextFreeTransferBufferId(), offset);
1612   expected.set_token.Init(GetNextToken());
1613 
1614   void* mem = gl_->MapBufferSubDataCHROMIUM(
1615       kTarget, kOffset, kSize, GL_WRITE_ONLY);
1616   ASSERT_TRUE(mem != nullptr);
1617   gl_->UnmapBufferSubDataCHROMIUM(mem);
1618   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1619 }
1620 
TEST_F(GLES2ImplementationTest,MapUnmapBufferSubDataCHROMIUMBadArgs)1621 TEST_F(GLES2ImplementationTest, MapUnmapBufferSubDataCHROMIUMBadArgs) {
1622   const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
1623   const GLintptr kOffset = 15;
1624   const GLsizeiptr kSize = 16;
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 
1635   // Calls to flush to wait for GetError
1636   EXPECT_CALL(*command_buffer(), OnFlush())
1637       .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1638       .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1639       .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1640       .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1641       .RetiresOnSaturation();
1642 
1643   void* mem;
1644   mem = gl_->MapBufferSubDataCHROMIUM(kTarget, -1, kSize, GL_WRITE_ONLY);
1645   ASSERT_TRUE(mem == nullptr);
1646   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1647   mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, -1, GL_WRITE_ONLY);
1648   ASSERT_TRUE(mem == nullptr);
1649   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1650   mem = gl_->MapBufferSubDataCHROMIUM(kTarget, kOffset, kSize, GL_READ_ONLY);
1651   ASSERT_TRUE(mem == nullptr);
1652   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
1653   const char* kPtr = "something";
1654   gl_->UnmapBufferSubDataCHROMIUM(kPtr);
1655   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1656 }
1657 
TEST_F(GLES2ImplementationTest,MapUnmapTexSubImage2DCHROMIUM)1658 TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUM) {
1659   struct Cmds {
1660     cmds::TexSubImage2D tex;
1661     cmd::SetToken set_token;
1662   };
1663   const GLint kLevel = 1;
1664   const GLint kXOffset = 2;
1665   const GLint kYOffset = 3;
1666   const GLint kWidth = 4;
1667   const GLint kHeight = 5;
1668   const GLenum kFormat = GL_RGBA;
1669   const GLenum kType = GL_UNSIGNED_BYTE;
1670 
1671   uint32_t offset = 0;
1672   Cmds expected;
1673   expected.tex.Init(
1674       GL_TEXTURE_2D, kLevel, kXOffset, kYOffset, kWidth, kHeight, kFormat,
1675       kType,
1676       command_buffer()->GetNextFreeTransferBufferId(), offset, GL_FALSE);
1677   expected.set_token.Init(GetNextToken());
1678 
1679   void* mem = gl_->MapTexSubImage2DCHROMIUM(
1680       GL_TEXTURE_2D,
1681       kLevel,
1682       kXOffset,
1683       kYOffset,
1684       kWidth,
1685       kHeight,
1686       kFormat,
1687       kType,
1688       GL_WRITE_ONLY);
1689   ASSERT_TRUE(mem != nullptr);
1690   gl_->UnmapTexSubImage2DCHROMIUM(mem);
1691   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1692 }
1693 
TEST_F(GLES2ImplementationTest,MapUnmapTexSubImage2DCHROMIUMBadArgs)1694 TEST_F(GLES2ImplementationTest, MapUnmapTexSubImage2DCHROMIUMBadArgs) {
1695   const GLint kLevel = 1;
1696   const GLint kXOffset = 2;
1697   const GLint kYOffset = 3;
1698   const GLint kWidth = 4;
1699   const GLint kHeight = 5;
1700   const GLenum kFormat = GL_RGBA;
1701   const GLenum kType = GL_UNSIGNED_BYTE;
1702 
1703   ExpectedMemoryInfo result1 =
1704       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1705   ExpectedMemoryInfo result2 =
1706       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1707   ExpectedMemoryInfo result3 =
1708       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1709   ExpectedMemoryInfo result4 =
1710       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1711   ExpectedMemoryInfo result5 =
1712       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1713   ExpectedMemoryInfo result6 =
1714       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1715   ExpectedMemoryInfo result7 =
1716       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1717 
1718   // Calls to flush to wait for GetError
1719   EXPECT_CALL(*command_buffer(), OnFlush())
1720       .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
1721       .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1722       .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1723       .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1724       .WillOnce(SetMemory(result5.ptr, GLuint(GL_NO_ERROR)))
1725       .WillOnce(SetMemory(result6.ptr, GLuint(GL_NO_ERROR)))
1726       .WillOnce(SetMemory(result7.ptr, GLuint(GL_NO_ERROR)))
1727       .RetiresOnSaturation();
1728 
1729   void* mem;
1730   mem = gl_->MapTexSubImage2DCHROMIUM(
1731     GL_TEXTURE_2D,
1732     -1,
1733     kXOffset,
1734     kYOffset,
1735     kWidth,
1736     kHeight,
1737     kFormat,
1738     kType,
1739     GL_WRITE_ONLY);
1740   EXPECT_TRUE(mem == nullptr);
1741   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1742   mem = gl_->MapTexSubImage2DCHROMIUM(
1743     GL_TEXTURE_2D,
1744     kLevel,
1745     -1,
1746     kYOffset,
1747     kWidth,
1748     kHeight,
1749     kFormat,
1750     kType,
1751     GL_WRITE_ONLY);
1752   EXPECT_TRUE(mem == nullptr);
1753   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1754   mem = gl_->MapTexSubImage2DCHROMIUM(
1755     GL_TEXTURE_2D,
1756     kLevel,
1757     kXOffset,
1758     -1,
1759     kWidth,
1760     kHeight,
1761     kFormat,
1762     kType,
1763     GL_WRITE_ONLY);
1764   EXPECT_TRUE(mem == nullptr);
1765   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1766   mem = gl_->MapTexSubImage2DCHROMIUM(
1767     GL_TEXTURE_2D,
1768     kLevel,
1769     kXOffset,
1770     kYOffset,
1771     -1,
1772     kHeight,
1773     kFormat,
1774     kType,
1775     GL_WRITE_ONLY);
1776   EXPECT_TRUE(mem == nullptr);
1777   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1778   mem = gl_->MapTexSubImage2DCHROMIUM(
1779     GL_TEXTURE_2D,
1780     kLevel,
1781     kXOffset,
1782     kYOffset,
1783     kWidth,
1784     -1,
1785     kFormat,
1786     kType,
1787     GL_WRITE_ONLY);
1788   EXPECT_TRUE(mem == nullptr);
1789   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1790   mem = gl_->MapTexSubImage2DCHROMIUM(
1791     GL_TEXTURE_2D,
1792     kLevel,
1793     kXOffset,
1794     kYOffset,
1795     kWidth,
1796     kHeight,
1797     kFormat,
1798     kType,
1799     GL_READ_ONLY);
1800   EXPECT_TRUE(mem == nullptr);
1801   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_ENUM), gl_->GetError());
1802   const char* kPtr = "something";
1803   gl_->UnmapTexSubImage2DCHROMIUM(kPtr);
1804   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1805 }
1806 
TEST_F(GLES2ImplementationTest,GetProgramInfoCHROMIUMGoodArgs)1807 TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMGoodArgs) {
1808   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
1809   const GLuint kProgramId = 123;
1810   const char kBad = 0x12;
1811   GLsizei size = 0;
1812   const Str7 kString = {"foobar"};
1813   char buf[20];
1814 
1815   ExpectedMemoryInfo mem1 =
1816       GetExpectedMemory(MaxTransferBufferSize());
1817   ExpectedMemoryInfo result1 =
1818       GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
1819   ExpectedMemoryInfo result2 =
1820       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1821 
1822   memset(buf, kBad, sizeof(buf));
1823   EXPECT_CALL(*command_buffer(), OnFlush())
1824       .WillOnce(DoAll(SetMemory(result1.ptr, uint32_t(sizeof(kString))),
1825                       SetMemory(mem1.ptr, kString)))
1826       .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1827       .RetiresOnSaturation();
1828 
1829   struct Cmds {
1830     cmd::SetBucketSize set_bucket_size1;
1831     cmds::GetProgramInfoCHROMIUM get_program_info;
1832     cmd::GetBucketStart get_bucket_start;
1833     cmd::SetToken set_token1;
1834     cmd::SetBucketSize set_bucket_size2;
1835   };
1836   Cmds expected;
1837   expected.set_bucket_size1.Init(kBucketId, 0);
1838   expected.get_program_info.Init(kProgramId, kBucketId);
1839   expected.get_bucket_start.Init(
1840       kBucketId, result1.id, result1.offset,
1841       MaxTransferBufferSize(), mem1.id, mem1.offset);
1842   expected.set_token1.Init(GetNextToken());
1843   expected.set_bucket_size2.Init(kBucketId, 0);
1844   gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), &size, &buf);
1845   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1846   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
1847   EXPECT_EQ(sizeof(kString), static_cast<size_t>(size));
1848   EXPECT_STREQ(kString.str, buf);
1849   EXPECT_EQ(buf[sizeof(kString)], kBad);
1850 }
1851 
TEST_F(GLES2ImplementationTest,GetProgramInfoCHROMIUMBadArgs)1852 TEST_F(GLES2ImplementationTest, GetProgramInfoCHROMIUMBadArgs) {
1853   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
1854   const GLuint kProgramId = 123;
1855   GLsizei size = 0;
1856   const Str7 kString = {"foobar"};
1857   char buf[20];
1858 
1859   ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
1860   ExpectedMemoryInfo result1 =
1861       GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
1862   ExpectedMemoryInfo result2 =
1863       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1864   ExpectedMemoryInfo result3 =
1865       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1866   ExpectedMemoryInfo result4 =
1867       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1868 
1869   EXPECT_CALL(*command_buffer(), OnFlush())
1870       .WillOnce(DoAll(SetMemory(result1.ptr, uint32_t(sizeof(kString))),
1871                       SetMemory(mem1.ptr, kString)))
1872       .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1873       .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1874       .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1875       .RetiresOnSaturation();
1876 
1877   // try bufsize not big enough.
1878   struct Cmds {
1879     cmd::SetBucketSize set_bucket_size1;
1880     cmds::GetProgramInfoCHROMIUM get_program_info;
1881     cmd::GetBucketStart get_bucket_start;
1882     cmd::SetToken set_token1;
1883     cmd::SetBucketSize set_bucket_size2;
1884   };
1885   Cmds expected;
1886   expected.set_bucket_size1.Init(kBucketId, 0);
1887   expected.get_program_info.Init(kProgramId, kBucketId);
1888   expected.get_bucket_start.Init(
1889       kBucketId, result1.id, result1.offset,
1890       MaxTransferBufferSize(), mem1.id, mem1.offset);
1891   expected.set_token1.Init(GetNextToken());
1892   expected.set_bucket_size2.Init(kBucketId, 0);
1893   gl_->GetProgramInfoCHROMIUM(kProgramId, 6, &size, &buf);
1894   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1895   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
1896   ClearCommands();
1897 
1898   // try bad bufsize
1899   gl_->GetProgramInfoCHROMIUM(kProgramId, -1, &size, &buf);
1900   EXPECT_TRUE(NoCommandsWritten());
1901   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1902   ClearCommands();
1903   // try no size ptr.
1904   gl_->GetProgramInfoCHROMIUM(kProgramId, sizeof(buf), nullptr, &buf);
1905   EXPECT_TRUE(NoCommandsWritten());
1906   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
1907 }
1908 
TEST_F(GLES2ImplementationTest,GetUniformBlocksCHROMIUMGoodArgs)1909 TEST_F(GLES2ImplementationTest, GetUniformBlocksCHROMIUMGoodArgs) {
1910   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
1911   const GLuint kProgramId = 123;
1912   const char kBad = 0x12;
1913   GLsizei size = 0;
1914   const Str7 kString = {"foobar"};
1915   char buf[20];
1916 
1917   ExpectedMemoryInfo mem1 =
1918       GetExpectedMemory(MaxTransferBufferSize());
1919   ExpectedMemoryInfo result1 =
1920       GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
1921   ExpectedMemoryInfo result2 =
1922       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1923 
1924   memset(buf, kBad, sizeof(buf));
1925   EXPECT_CALL(*command_buffer(), OnFlush())
1926       .WillOnce(DoAll(SetMemory(result1.ptr, uint32_t(sizeof(kString))),
1927                       SetMemory(mem1.ptr, kString)))
1928       .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1929       .RetiresOnSaturation();
1930 
1931   struct Cmds {
1932     cmd::SetBucketSize set_bucket_size1;
1933     cmds::GetUniformBlocksCHROMIUM get_uniform_blocks;
1934     cmd::GetBucketStart get_bucket_start;
1935     cmd::SetToken set_token1;
1936     cmd::SetBucketSize set_bucket_size2;
1937   };
1938   Cmds expected;
1939   expected.set_bucket_size1.Init(kBucketId, 0);
1940   expected.get_uniform_blocks.Init(kProgramId, kBucketId);
1941   expected.get_bucket_start.Init(
1942       kBucketId, result1.id, result1.offset,
1943       MaxTransferBufferSize(), mem1.id, mem1.offset);
1944   expected.set_token1.Init(GetNextToken());
1945   expected.set_bucket_size2.Init(kBucketId, 0);
1946   gl_->GetUniformBlocksCHROMIUM(kProgramId, sizeof(buf), &size, &buf);
1947   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1948   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
1949   EXPECT_EQ(sizeof(kString), static_cast<size_t>(size));
1950   EXPECT_STREQ(kString.str, buf);
1951   EXPECT_EQ(buf[sizeof(kString)], kBad);
1952 }
1953 
TEST_F(GLES2ImplementationTest,GetUniformBlocksCHROMIUMBadArgs)1954 TEST_F(GLES2ImplementationTest, GetUniformBlocksCHROMIUMBadArgs) {
1955   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
1956   const GLuint kProgramId = 123;
1957   GLsizei size = 0;
1958   const Str7 kString = {"foobar"};
1959   char buf[20];
1960 
1961   ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
1962   ExpectedMemoryInfo result1 =
1963       GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
1964   ExpectedMemoryInfo result2 =
1965       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1966   ExpectedMemoryInfo result3 =
1967       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1968   ExpectedMemoryInfo result4 =
1969       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
1970 
1971   EXPECT_CALL(*command_buffer(), OnFlush())
1972       .WillOnce(DoAll(SetMemory(result1.ptr, uint32_t(sizeof(kString))),
1973                       SetMemory(mem1.ptr, kString)))
1974       .WillOnce(SetMemory(result2.ptr, GLuint(GL_NO_ERROR)))
1975       .WillOnce(SetMemory(result3.ptr, GLuint(GL_NO_ERROR)))
1976       .WillOnce(SetMemory(result4.ptr, GLuint(GL_NO_ERROR)))
1977       .RetiresOnSaturation();
1978 
1979   // try bufsize not big enough.
1980   struct Cmds {
1981     cmd::SetBucketSize set_bucket_size1;
1982     cmds::GetUniformBlocksCHROMIUM get_uniform_blocks;
1983     cmd::GetBucketStart get_bucket_start;
1984     cmd::SetToken set_token1;
1985     cmd::SetBucketSize set_bucket_size2;
1986   };
1987   Cmds expected;
1988   expected.set_bucket_size1.Init(kBucketId, 0);
1989   expected.get_uniform_blocks.Init(kProgramId, kBucketId);
1990   expected.get_bucket_start.Init(
1991       kBucketId, result1.id, result1.offset,
1992       MaxTransferBufferSize(), mem1.id, mem1.offset);
1993   expected.set_token1.Init(GetNextToken());
1994   expected.set_bucket_size2.Init(kBucketId, 0);
1995   gl_->GetUniformBlocksCHROMIUM(kProgramId, 6, &size, &buf);
1996   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
1997   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), gl_->GetError());
1998   ClearCommands();
1999 
2000   // try bad bufsize
2001   gl_->GetUniformBlocksCHROMIUM(kProgramId, -1, &size, &buf);
2002   EXPECT_TRUE(NoCommandsWritten());
2003   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2004   ClearCommands();
2005   // try no size ptr.
2006   gl_->GetUniformBlocksCHROMIUM(kProgramId, sizeof(buf), nullptr, &buf);
2007   EXPECT_TRUE(NoCommandsWritten());
2008   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
2009 }
2010 
2011 // Test that things are cached
TEST_F(GLES2ImplementationTest,GetIntegerCacheRead)2012 TEST_F(GLES2ImplementationTest, GetIntegerCacheRead) {
2013   struct PNameValue {
2014     GLenum pname;
2015     GLint expected;
2016   };
2017   const PNameValue pairs[] = {
2018       {GL_ACTIVE_TEXTURE, GL_TEXTURE0, },
2019       {GL_TEXTURE_BINDING_2D, 0, },
2020       {GL_TEXTURE_BINDING_CUBE_MAP, 0, },
2021       {GL_TEXTURE_BINDING_EXTERNAL_OES, 0, },
2022       {GL_FRAMEBUFFER_BINDING, 0, },
2023       {GL_RENDERBUFFER_BINDING, 0, },
2024       {GL_ARRAY_BUFFER_BINDING, 0, },
2025       {GL_ELEMENT_ARRAY_BUFFER_BINDING, 0, },
2026       {GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, kMaxCombinedTextureImageUnits, },
2027       {GL_MAX_CUBE_MAP_TEXTURE_SIZE, kMaxCubeMapTextureSize, },
2028       {GL_MAX_FRAGMENT_UNIFORM_VECTORS, kMaxFragmentUniformVectors, },
2029       {GL_MAX_RENDERBUFFER_SIZE, kMaxRenderbufferSize, },
2030       {GL_MAX_TEXTURE_IMAGE_UNITS, kMaxTextureImageUnits, },
2031       {GL_MAX_TEXTURE_SIZE, kMaxTextureSize, },
2032       {GL_MAX_VARYING_VECTORS, kMaxVaryingVectors, },
2033       {GL_MAX_VERTEX_ATTRIBS, kMaxVertexAttribs, },
2034       {GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, kMaxVertexTextureImageUnits, },
2035       {GL_MAX_VERTEX_UNIFORM_VECTORS, kMaxVertexUniformVectors, },
2036       {GL_NUM_COMPRESSED_TEXTURE_FORMATS, kNumCompressedTextureFormats, },
2037       {GL_NUM_SHADER_BINARY_FORMATS, kNumShaderBinaryFormats, }, };
2038   size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2039   for (size_t ii = 0; ii < num_pairs; ++ii) {
2040     const PNameValue& pv = pairs[ii];
2041     GLint v = -1;
2042     gl_->GetIntegerv(pv.pname, &v);
2043     EXPECT_TRUE(NoCommandsWritten());
2044     EXPECT_EQ(pv.expected, v);
2045   }
2046 
2047   ExpectedMemoryInfo result1 =
2048       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2049 
2050   EXPECT_CALL(*command_buffer(), OnFlush())
2051       .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2052       .RetiresOnSaturation();
2053   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2054 }
2055 
TEST_F(GLES2ImplementationTest,GetIntegerDisjointValue)2056 TEST_F(GLES2ImplementationTest, GetIntegerDisjointValue) {
2057   ExpectedMemoryInfo mem = GetExpectedMappedMemory(sizeof(DisjointValueSync));
2058   gl_->SetDisjointValueSyncCHROMIUM();
2059   ASSERT_EQ(mem.id, GetQueryTracker()->DisjointCountSyncShmID());
2060   ASSERT_EQ(mem.offset, GetQueryTracker()->DisjointCountSyncShmOffset());
2061   DisjointValueSync* disjoint_sync =
2062       reinterpret_cast<DisjointValueSync*>(mem.ptr);
2063 
2064   ClearCommands();
2065   GLint disjoint_value = -1;
2066   gl_->GetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
2067   EXPECT_TRUE(NoCommandsWritten());
2068   EXPECT_EQ(0, disjoint_value);
2069 
2070   // After setting disjoint, it should be true.
2071   disjoint_value = -1;
2072   disjoint_sync->SetDisjointCount(1);
2073   gl_->GetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
2074   EXPECT_TRUE(NoCommandsWritten());
2075   EXPECT_EQ(1, disjoint_value);
2076 
2077   // After checking disjoint, it should be false again.
2078   disjoint_value = -1;
2079   gl_->GetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
2080   EXPECT_TRUE(NoCommandsWritten());
2081   EXPECT_EQ(0, disjoint_value);
2082 
2083   // Check for errors.
2084   ExpectedMemoryInfo result1 =
2085       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2086   EXPECT_CALL(*command_buffer(), OnFlush())
2087       .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2088       .RetiresOnSaturation();
2089   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2090 }
2091 
TEST_F(GLES2ImplementationTest,GetIntegerCacheWrite)2092 TEST_F(GLES2ImplementationTest, GetIntegerCacheWrite) {
2093   struct PNameValue {
2094     GLenum pname;
2095     GLint expected;
2096   };
2097   gl_->ActiveTexture(GL_TEXTURE4);
2098   gl_->BindBuffer(GL_ARRAY_BUFFER, 2);
2099   gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, 3);
2100   gl_->BindFramebuffer(GL_FRAMEBUFFER, 4);
2101   gl_->BindRenderbuffer(GL_RENDERBUFFER, 5);
2102   gl_->BindTexture(GL_TEXTURE_2D, 6);
2103   gl_->BindTexture(GL_TEXTURE_CUBE_MAP, 7);
2104   gl_->BindTexture(GL_TEXTURE_EXTERNAL_OES, 8);
2105 
2106   const PNameValue pairs[] = {{GL_ACTIVE_TEXTURE, GL_TEXTURE4, },
2107                               {GL_ARRAY_BUFFER_BINDING, 2, },
2108                               {GL_ELEMENT_ARRAY_BUFFER_BINDING, 3, },
2109                               {GL_FRAMEBUFFER_BINDING, 4, },
2110                               {GL_RENDERBUFFER_BINDING, 5, },
2111                               {GL_TEXTURE_BINDING_2D, 6, },
2112                               {GL_TEXTURE_BINDING_CUBE_MAP, 7, },
2113                               {GL_TEXTURE_BINDING_EXTERNAL_OES, 8, }, };
2114   size_t num_pairs = sizeof(pairs) / sizeof(pairs[0]);
2115   for (size_t ii = 0; ii < num_pairs; ++ii) {
2116     const PNameValue& pv = pairs[ii];
2117     GLint v = -1;
2118     gl_->GetIntegerv(pv.pname, &v);
2119     EXPECT_EQ(pv.expected, v);
2120   }
2121 
2122   ExpectedMemoryInfo result1 =
2123       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
2124 
2125   EXPECT_CALL(*command_buffer(), OnFlush())
2126       .WillOnce(SetMemory(result1.ptr, GLuint(GL_NO_ERROR)))
2127       .RetiresOnSaturation();
2128   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
2129 }
2130 
CheckRect(int width,int height,GLenum format,GLenum type,int alignment,const uint8_t * r1,const uint8_t * r2)2131 static bool CheckRect(int width,
2132                       int height,
2133                       GLenum format,
2134                       GLenum type,
2135                       int alignment,
2136                       const uint8_t* r1,
2137                       const uint8_t* r2) {
2138   uint32_t size = 0;
2139   uint32_t unpadded_row_size = 0;
2140   uint32_t padded_row_size = 0;
2141   if (!GLES2Util::ComputeImageDataSizes(
2142       width, height, 1, format, type, alignment, &size, &unpadded_row_size,
2143       &padded_row_size)) {
2144     return false;
2145   }
2146 
2147   int r2_stride = static_cast<int>(padded_row_size);
2148 
2149   for (int y = 0; y < height; ++y) {
2150     if (memcmp(r1, r2, unpadded_row_size) != 0) {
2151       return false;
2152     }
2153     r1 += padded_row_size;
2154     r2 += r2_stride;
2155   }
2156   return true;
2157 }
2158 
ACTION_P7(CheckRectAction,width,height,format,type,alignment,r1,r2)2159 ACTION_P7(CheckRectAction, width, height, format, type, alignment, r1, r2) {
2160   EXPECT_TRUE(CheckRect(
2161       width, height, format, type, alignment, r1, r2));
2162 }
2163 
TEST_F(GLES2ImplementationTest,TexImage2D)2164 TEST_F(GLES2ImplementationTest, TexImage2D) {
2165   struct Cmds {
2166     cmds::TexImage2D tex_image_2d;
2167     cmd::SetToken set_token;
2168   };
2169   struct Cmds2 {
2170     cmds::TexImage2D tex_image_2d;
2171     cmd::SetToken set_token;
2172   };
2173   const GLenum kTarget = GL_TEXTURE_2D;
2174   const GLint kLevel = 0;
2175   const GLenum kFormat = GL_RGB;
2176   const GLsizei kWidth = 3;
2177   const GLsizei kHeight = 4;
2178   const GLint kBorder = 0;
2179   const GLenum kType = GL_UNSIGNED_BYTE;
2180   const GLint kPixelStoreUnpackAlignment = 4;
2181   static uint8_t pixels[] = {
2182       11, 12, 13, 13,  14,  15,  15,  16,  17,  101, 102, 103, 21, 22, 23,
2183       23, 24, 25, 25,  26,  27,  201, 202, 203, 31,  32,  33,  33, 34, 35,
2184       35, 36, 37, 123, 124, 125, 41,  42,  43,  43,  44,  45,  45, 46, 47,
2185   };
2186 
2187   ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels));
2188 
2189   Cmds expected;
2190   expected.tex_image_2d.Init(
2191       kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2192       mem1.id, mem1.offset);
2193   expected.set_token.Init(GetNextToken());
2194   gl_->TexImage2D(
2195       kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2196       pixels);
2197   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2198   EXPECT_TRUE(CheckRect(
2199       kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment,
2200       pixels, mem1.ptr));
2201 }
2202 
TEST_F(GLES2ImplementationTest,TexImage2DViaMappedMem)2203 TEST_F(GLES2ImplementationTest, TexImage2DViaMappedMem) {
2204   if (!AllowExtraTransferBufferSize()) {
2205     LOG(WARNING) << "Low memory device do not support MappedMem. Skipping test";
2206     return;
2207   }
2208 
2209   struct Cmds {
2210     cmds::TexImage2D tex_image_2d;
2211     cmd::SetToken set_token;
2212   };
2213   const GLenum kTarget = GL_TEXTURE_2D;
2214   const GLint kLevel = 0;
2215   const GLenum kFormat = GL_RGB;
2216   const GLsizei kWidth = 3;
2217   const GLint kBorder = 0;
2218   const GLenum kType = GL_UNSIGNED_BYTE;
2219   const GLint kPixelStoreUnpackAlignment = 4;
2220 
2221   uint32_t size = 0;
2222   uint32_t unpadded_row_size = 0;
2223   uint32_t padded_row_size = 0;
2224   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2225       kWidth, 2, 1, kFormat, kType, kPixelStoreUnpackAlignment,
2226       &size, &unpadded_row_size, &padded_row_size));
2227   const GLsizei kMaxHeight = (MaxTransferBufferSize() / padded_row_size) * 2;
2228   const GLsizei kHeight = kMaxHeight * 2;
2229   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2230       kWidth, kHeight, 1, kFormat, kType, kPixelStoreUnpackAlignment,
2231       &size, &unpadded_row_size, &padded_row_size));
2232 
2233   std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
2234   for (uint32_t ii = 0; ii < size; ++ii) {
2235     pixels[ii] = static_cast<uint8_t>(ii);
2236   }
2237 
2238   ExpectedMemoryInfo mem1 = GetExpectedMappedMemory(size);
2239 
2240   Cmds expected;
2241   expected.tex_image_2d.Init(
2242       kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2243       mem1.id, mem1.offset);
2244   expected.set_token.Init(GetNextToken());
2245   gl_->TexImage2D(
2246       kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2247       pixels.get());
2248   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2249   EXPECT_TRUE(CheckRect(
2250       kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment,
2251       pixels.get(), mem1.ptr));
2252 }
2253 
2254 // Test TexImage2D with 2 writes
TEST_F(GLES2ImplementationTest,TexImage2DViaTexSubImage2D)2255 TEST_F(GLES2ImplementationTest, TexImage2DViaTexSubImage2D) {
2256   // Set limit to 1 to effectively disable mapped memory.
2257   SetMappedMemoryLimit(1);
2258 
2259   struct Cmds {
2260     cmds::TexImage2D tex_image_2d;
2261     cmds::TexSubImage2D tex_sub_image_2d1;
2262     cmd::SetToken set_token1;
2263     cmds::TexSubImage2D tex_sub_image_2d2;
2264     cmd::SetToken set_token2;
2265   };
2266   const GLenum kTarget = GL_TEXTURE_2D;
2267   const GLint kLevel = 0;
2268   const GLenum kFormat = GL_RGB;
2269   const GLint kBorder = 0;
2270   const GLenum kType = GL_UNSIGNED_BYTE;
2271   const GLint kPixelStoreUnpackAlignment = 4;
2272   const GLsizei kWidth = 3;
2273 
2274   uint32_t size = 0;
2275   uint32_t unpadded_row_size = 0;
2276   uint32_t padded_row_size = 0;
2277   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2278       kWidth, 2, 1, kFormat, kType, kPixelStoreUnpackAlignment,
2279       &size, &unpadded_row_size, &padded_row_size));
2280   const GLsizei kHeight = (MaxTransferBufferSize() / padded_row_size) * 2;
2281   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2282       kWidth, kHeight, 1, kFormat, kType, kPixelStoreUnpackAlignment, &size,
2283       nullptr, nullptr));
2284   uint32_t half_size = 0;
2285   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2286       kWidth, kHeight / 2, 1, kFormat, kType, kPixelStoreUnpackAlignment,
2287       &half_size, nullptr, nullptr));
2288 
2289   std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
2290   for (uint32_t ii = 0; ii < size; ++ii) {
2291     pixels[ii] = static_cast<uint8_t>(ii);
2292   }
2293 
2294   ExpectedMemoryInfo mem1 = GetExpectedMemory(half_size);
2295   ExpectedMemoryInfo mem2 = GetExpectedMemory(half_size);
2296 
2297   Cmds expected;
2298   expected.tex_image_2d.Init(
2299       kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2300       0, 0);
2301   expected.tex_sub_image_2d1.Init(
2302       kTarget, kLevel, 0, 0, kWidth, kHeight / 2, kFormat, kType,
2303       mem1.id, mem1.offset, true);
2304   expected.set_token1.Init(GetNextToken());
2305   expected.tex_sub_image_2d2.Init(
2306       kTarget, kLevel, 0, kHeight / 2, kWidth, kHeight / 2, kFormat, kType,
2307       mem2.id, mem2.offset, true);
2308   expected.set_token2.Init(GetNextToken());
2309 
2310   // TODO(gman): Make it possible to run this test
2311   // EXPECT_CALL(*command_buffer(), OnFlush())
2312   //     .WillOnce(CheckRectAction(
2313   //         kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2314   //         false, pixels.get(),
2315   //         GetExpectedTransferAddressFromOffsetAs<uint8_t>(offset1,
2316   //         half_size)))
2317   //     .RetiresOnSaturation();
2318 
2319   gl_->TexImage2D(
2320       kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2321       pixels.get());
2322   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2323   EXPECT_TRUE(CheckRect(
2324       kWidth, kHeight / 2, kFormat, kType, kPixelStoreUnpackAlignment,
2325       pixels.get() + kHeight / 2 * padded_row_size, mem2.ptr));
2326 }
2327 
TEST_F(GLES2ImplementationTest,SubImage2DUnpack)2328 TEST_F(GLES2ImplementationTest, SubImage2DUnpack) {
2329   static const GLint unpack_alignments[] = { 1, 2, 4, 8 };
2330 
2331   static const GLenum kFormat = GL_RGB;
2332   static const GLenum kType = GL_UNSIGNED_BYTE;
2333   static const GLint kLevel = 0;
2334   static const GLint kBorder = 0;
2335   // We're testing using the unpack params to pull a subimage out of a larger
2336   // source of pixels. Here we specify the subimage by its border rows /
2337   // columns.
2338   static const GLint kSrcWidth = 33;
2339   static const GLint kSrcSubImageX0 = 11;
2340   static const GLint kSrcSubImageX1 = 20;
2341   static const GLint kSrcSubImageY0 = 18;
2342   static const GLint kSrcSubImageY1 = 23;
2343   static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0;
2344   static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0;
2345 
2346   // these are only used in the texsubimage tests
2347   static const GLint kTexWidth = 1023;
2348   static const GLint kTexHeight = 511;
2349   static const GLint kTexSubXOffset = 419;
2350   static const GLint kTexSubYOffset = 103;
2351 
2352   struct {
2353     cmds::PixelStorei pixel_store_i;
2354     cmds::TexImage2D tex_image_2d;
2355   } texImageExpected;
2356 
2357   struct  {
2358     cmds::PixelStorei pixel_store_i;
2359     cmds::TexImage2D tex_image_2d;
2360     cmds::TexSubImage2D tex_sub_image_2d;
2361   } texSubImageExpected;
2362 
2363   uint32_t pixel_size;
2364   PixelStoreParams pixel_params;
2365   // Makes sure the pixels size is large enough for all tests.
2366   pixel_params.alignment = 8;
2367   ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3(
2368       kSrcWidth, kSrcSubImageY1, 1, kFormat, kType,
2369       pixel_params, &pixel_size, nullptr, nullptr, nullptr, nullptr));
2370   std::unique_ptr<uint8_t[]> src_pixels;
2371   src_pixels.reset(new uint8_t[pixel_size]);
2372   for (size_t i = 0; i < pixel_size; ++i) {
2373     src_pixels[i] = static_cast<uint8_t>(i % 255);
2374   }
2375 
2376   for (int sub = 0; sub < 2; ++sub) {
2377     for (size_t a = 0; a < base::size(unpack_alignments); ++a) {
2378       const void* commands = GetPut();
2379 
2380       GLint alignment = unpack_alignments[a];
2381       gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment);
2382       gl_->PixelStorei(GL_UNPACK_ROW_LENGTH, kSrcWidth);
2383       gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS, kSrcSubImageX0);
2384       gl_->PixelStorei(GL_UNPACK_SKIP_ROWS, kSrcSubImageY0);
2385 
2386       uint32_t client_size;
2387       uint32_t client_unpadded_row_size;
2388       uint32_t client_padded_row_size;
2389       uint32_t client_skip_size;
2390       {
2391         PixelStoreParams params;
2392         params.alignment = alignment;
2393         params.row_length = kSrcWidth;
2394         params.skip_pixels = kSrcSubImageX0;
2395         params.skip_rows = kSrcSubImageY0;
2396         ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3(
2397             kSrcSubImageWidth, kSrcSubImageHeight, 1, kFormat, kType, params,
2398             &client_size, &client_unpadded_row_size, &client_padded_row_size,
2399             &client_skip_size, nullptr));
2400         ASSERT_TRUE(client_size + client_skip_size <= pixel_size);
2401       }
2402 
2403       uint32_t service_size;
2404       uint32_t service_unpadded_row_size;
2405       uint32_t service_padded_row_size;
2406       uint32_t service_skip_size;
2407       {
2408         PixelStoreParams params;
2409         // For pixels we send to service side, we already applied all unpack
2410         // parameters except for UNPACK_ALIGNMENT.
2411         params.alignment = alignment;
2412         ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3(
2413             kSrcSubImageWidth, kSrcSubImageHeight, 1, kFormat, kType, params,
2414             &service_size, &service_unpadded_row_size, &service_padded_row_size,
2415             &service_skip_size, nullptr));
2416         ASSERT_TRUE(service_size <= MaxTransferBufferSize());
2417         ASSERT_TRUE(service_skip_size == 0);
2418         ASSERT_TRUE(client_unpadded_row_size == service_unpadded_row_size);
2419       }
2420 
2421       ExpectedMemoryInfo mem = GetExpectedMemory(service_size);
2422       if (sub) {
2423         gl_->TexImage2D(
2424             GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight, kBorder,
2425             kFormat, kType, nullptr);
2426         gl_->TexSubImage2D(
2427             GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset,
2428             kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType,
2429             src_pixels.get());
2430         texSubImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment);
2431         texSubImageExpected.tex_image_2d.Init(
2432             GL_TEXTURE_2D, kLevel, kFormat, kTexWidth, kTexHeight,
2433             kFormat, kType, 0, 0);
2434         texSubImageExpected.tex_sub_image_2d.Init(
2435             GL_TEXTURE_2D, kLevel, kTexSubXOffset, kTexSubYOffset,
2436             kSrcSubImageWidth, kSrcSubImageHeight, kFormat, kType, mem.id,
2437             mem.offset, GL_FALSE);
2438         EXPECT_EQ(0, memcmp(&texSubImageExpected, commands,
2439                             sizeof(texSubImageExpected)));
2440       } else {
2441         gl_->TexImage2D(
2442             GL_TEXTURE_2D, kLevel, kFormat,
2443             kSrcSubImageWidth, kSrcSubImageHeight, kBorder, kFormat, kType,
2444             src_pixels.get());
2445         texImageExpected.pixel_store_i.Init(GL_UNPACK_ALIGNMENT, alignment);
2446         texImageExpected.tex_image_2d.Init(
2447             GL_TEXTURE_2D, kLevel, kFormat, kSrcSubImageWidth,
2448             kSrcSubImageHeight, kFormat, kType, mem.id, mem.offset);
2449         EXPECT_EQ(0, memcmp(&texImageExpected, commands,
2450                             sizeof(texImageExpected)));
2451       }
2452       for (int y = 0; y < kSrcSubImageHeight; ++y) {
2453         const uint8_t* src_row =
2454             src_pixels.get() + client_skip_size + y * client_padded_row_size;
2455         const uint8_t* dst_row = mem.ptr + y * service_padded_row_size;
2456         EXPECT_EQ(0, memcmp(src_row, dst_row, service_unpadded_row_size));
2457       }
2458       ClearCommands();
2459     }
2460   }
2461 }
2462 
TEST_F(GLES3ImplementationTest,SubImage3DUnpack)2463 TEST_F(GLES3ImplementationTest, SubImage3DUnpack) {
2464   static const GLint unpack_alignments[] = { 1, 2, 4, 8 };
2465 
2466   static const GLenum kFormat = GL_RGB;
2467   static const GLenum kType = GL_UNSIGNED_BYTE;
2468   static const GLint kLevel = 0;
2469   static const GLint kBorder = 0;
2470   // We're testing using the unpack params to pull a subimage out of a larger
2471   // source of pixels. Here we specify the subimage by its border rows /
2472   // columns.
2473   static const GLint kSrcWidth = 23;
2474   static const GLint kSrcHeight = 7;
2475   static const GLint kSrcSubImageX0 = 11;
2476   static const GLint kSrcSubImageX1 = 16;
2477   static const GLint kSrcSubImageY0 = 1;
2478   static const GLint kSrcSubImageY1 = 4;
2479   static const GLint kSrcSubImageZ0 = 2;
2480   static const GLint kSrcSubImageZ1 = 5;
2481   static const GLint kSrcSubImageWidth = kSrcSubImageX1 - kSrcSubImageX0;
2482   static const GLint kSrcSubImageHeight = kSrcSubImageY1 - kSrcSubImageY0;
2483   static const GLint kSrcSubImageDepth = kSrcSubImageZ1 - kSrcSubImageZ0;
2484 
2485   // these are only used in the texsubimage tests
2486   static const GLint kTexWidth = 255;
2487   static const GLint kTexHeight = 127;
2488   static const GLint kTexDepth = 11;
2489   static const GLint kTexSubXOffset = 119;
2490   static const GLint kTexSubYOffset = 63;
2491   static const GLint kTexSubZOffset = 1;
2492 
2493   struct {
2494     cmds::PixelStorei pixel_store_i[3];
2495     cmds::TexImage3D tex_image_3d;
2496   } texImageExpected;
2497 
2498   struct  {
2499     cmds::PixelStorei pixel_store_i[3];
2500     cmds::TexImage3D tex_image_3d;
2501     cmds::TexSubImage3D tex_sub_image_3d;
2502   } texSubImageExpected;
2503 
2504   uint32_t pixel_size;
2505   PixelStoreParams pixel_params;
2506   // Makes sure the pixels size is large enough for all tests.
2507   pixel_params.alignment = 8;
2508   ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3(
2509       kSrcWidth, kSrcHeight, kSrcSubImageZ1, kFormat, kType,
2510       pixel_params, &pixel_size, nullptr, nullptr, nullptr, nullptr));
2511   std::unique_ptr<uint8_t[]> src_pixels;
2512   src_pixels.reset(new uint8_t[pixel_size]);
2513   for (size_t i = 0; i < pixel_size; ++i) {
2514     src_pixels[i] = static_cast<uint8_t>(i % 255);
2515   }
2516 
2517   for (int sub = 0; sub < 2; ++sub) {
2518     for (size_t a = 0; a < base::size(unpack_alignments); ++a) {
2519       const void* commands = GetPut();
2520 
2521       GLint alignment = unpack_alignments[a];
2522       gl_->PixelStorei(GL_UNPACK_ALIGNMENT, alignment);
2523       gl_->PixelStorei(GL_UNPACK_ROW_LENGTH, kSrcWidth);
2524       gl_->PixelStorei(GL_UNPACK_IMAGE_HEIGHT, kSrcHeight);
2525       gl_->PixelStorei(GL_UNPACK_SKIP_PIXELS, kSrcSubImageX0);
2526       gl_->PixelStorei(GL_UNPACK_SKIP_ROWS, kSrcSubImageY0);
2527       gl_->PixelStorei(GL_UNPACK_SKIP_IMAGES, kSrcSubImageZ0);
2528 
2529       uint32_t client_size;
2530       uint32_t client_unpadded_row_size;
2531       uint32_t client_padded_row_size;
2532       uint32_t client_skip_size;
2533       {
2534         PixelStoreParams params;
2535         params.alignment = alignment;
2536         params.row_length = kSrcWidth;
2537         params.image_height = kSrcHeight;
2538         params.skip_pixels = kSrcSubImageX0;
2539         params.skip_rows = kSrcSubImageY0;
2540         params.skip_images = kSrcSubImageZ0;
2541         ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3(
2542             kSrcSubImageWidth, kSrcSubImageHeight, kSrcSubImageDepth,
2543             kFormat, kType, params,
2544             &client_size, &client_unpadded_row_size, &client_padded_row_size,
2545             &client_skip_size, nullptr));
2546         ASSERT_TRUE(client_size + client_skip_size <= pixel_size);
2547       }
2548 
2549       uint32_t service_size;
2550       uint32_t service_unpadded_row_size;
2551       uint32_t service_padded_row_size;
2552       uint32_t service_skip_size;
2553       {
2554         PixelStoreParams params;
2555         // For pixels we send to service side, we already applied all unpack
2556         // parameters except for UNPACK_ALIGNMENT.
2557         params.alignment = alignment;
2558         ASSERT_TRUE(GLES2Util::ComputeImageDataSizesES3(
2559             kSrcSubImageWidth, kSrcSubImageHeight, kSrcSubImageDepth,
2560             kFormat, kType, params,
2561             &service_size, &service_unpadded_row_size, &service_padded_row_size,
2562             &service_skip_size, nullptr));
2563         ASSERT_TRUE(service_size <= MaxTransferBufferSize());
2564         ASSERT_TRUE(service_skip_size == 0);
2565         ASSERT_TRUE(client_unpadded_row_size == service_unpadded_row_size);
2566       }
2567 
2568       ExpectedMemoryInfo mem = GetExpectedMemory(service_size);
2569       if (sub) {
2570         gl_->TexImage3D(
2571             GL_TEXTURE_3D, kLevel, kFormat, kTexWidth, kTexHeight, kTexDepth,
2572             kBorder, kFormat, kType, nullptr);
2573         gl_->TexSubImage3D(
2574             GL_TEXTURE_3D, kLevel,
2575             kTexSubXOffset, kTexSubYOffset, kTexSubZOffset,
2576             kSrcSubImageWidth, kSrcSubImageHeight, kSrcSubImageDepth,
2577             kFormat, kType, src_pixels.get());
2578         texSubImageExpected.pixel_store_i[0].Init(
2579             GL_UNPACK_ALIGNMENT, alignment);
2580         texSubImageExpected.pixel_store_i[1].Init(
2581             GL_UNPACK_ROW_LENGTH, kSrcWidth);
2582         texSubImageExpected.pixel_store_i[2].Init(
2583             GL_UNPACK_IMAGE_HEIGHT, kSrcHeight);
2584         texSubImageExpected.tex_image_3d.Init(
2585             GL_TEXTURE_3D, kLevel, kFormat, kTexWidth, kTexHeight, kTexDepth,
2586             kFormat, kType, 0, 0);
2587         texSubImageExpected.tex_sub_image_3d.Init(
2588             GL_TEXTURE_3D, kLevel,
2589             kTexSubXOffset, kTexSubYOffset, kTexSubZOffset,
2590             kSrcSubImageWidth, kSrcSubImageHeight, kSrcSubImageDepth,
2591             kFormat, kType, mem.id, mem.offset, GL_FALSE);
2592         EXPECT_EQ(0, memcmp(&texSubImageExpected, commands,
2593                             sizeof(texSubImageExpected)));
2594       } else {
2595         gl_->TexImage3D(
2596             GL_TEXTURE_3D, kLevel, kFormat,
2597             kSrcSubImageWidth, kSrcSubImageHeight, kSrcSubImageDepth,
2598             kBorder, kFormat, kType, src_pixels.get());
2599         texImageExpected.pixel_store_i[0].Init(GL_UNPACK_ALIGNMENT, alignment);
2600         texImageExpected.pixel_store_i[1].Init(
2601             GL_UNPACK_ROW_LENGTH, kSrcWidth);
2602         texImageExpected.pixel_store_i[2].Init(
2603             GL_UNPACK_IMAGE_HEIGHT, kSrcHeight);
2604         texImageExpected.tex_image_3d.Init(
2605             GL_TEXTURE_3D, kLevel, kFormat,
2606             kSrcSubImageWidth, kSrcSubImageHeight, kSrcSubImageDepth,
2607             kFormat, kType, mem.id, mem.offset);
2608         EXPECT_EQ(0, memcmp(&texImageExpected, commands,
2609                             sizeof(texImageExpected)));
2610       }
2611       for (int z = 0; z < kSrcSubImageDepth; ++z) {
2612         for (int y = 0; y < kSrcSubImageHeight; ++y) {
2613           const uint8_t* src_row =  src_pixels.get() + client_skip_size +
2614               (kSrcHeight * z + y) * client_padded_row_size;
2615           const uint8_t* dst_row = mem.ptr +
2616               (kSrcSubImageHeight * z + y) * service_padded_row_size;
2617           EXPECT_EQ(0, memcmp(src_row, dst_row, service_unpadded_row_size));
2618         }
2619       }
2620       ClearCommands();
2621     }
2622   }
2623 }
2624 
2625 // Test texture related calls with invalid arguments.
TEST_F(GLES2ImplementationTest,TextureInvalidArguments)2626 TEST_F(GLES2ImplementationTest, TextureInvalidArguments) {
2627   struct Cmds {
2628     cmds::TexImage2D tex_image_2d;
2629     cmd::SetToken set_token;
2630   };
2631   const GLenum kTarget = GL_TEXTURE_2D;
2632   const GLint kLevel = 0;
2633   const GLenum kFormat = GL_RGB;
2634   const GLsizei kWidth = 3;
2635   const GLsizei kHeight = 4;
2636   const GLint kBorder = 0;
2637   const GLint kInvalidBorder = 1;
2638   const GLenum kType = GL_UNSIGNED_BYTE;
2639   const GLint kPixelStoreUnpackAlignment = 4;
2640   static uint8_t pixels[] = {
2641       11, 12, 13, 13,  14,  15,  15,  16,  17,  101, 102, 103, 21, 22, 23,
2642       23, 24, 25, 25,  26,  27,  201, 202, 203, 31,  32,  33,  33, 34, 35,
2643       35, 36, 37, 123, 124, 125, 41,  42,  43,  43,  44,  45,  45, 46, 47,
2644   };
2645 
2646   // Verify that something works.
2647 
2648   ExpectedMemoryInfo mem1 = GetExpectedMemory(sizeof(pixels));
2649 
2650   Cmds expected;
2651   expected.tex_image_2d.Init(
2652       kTarget, kLevel, kFormat, kWidth, kHeight, kFormat, kType,
2653       mem1.id, mem1.offset);
2654   expected.set_token.Init(GetNextToken());
2655   gl_->TexImage2D(
2656       kTarget, kLevel, kFormat, kWidth, kHeight, kBorder, kFormat, kType,
2657       pixels);
2658   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2659   EXPECT_TRUE(CheckRect(
2660       kWidth, kHeight, kFormat, kType, kPixelStoreUnpackAlignment,
2661       pixels, mem1.ptr));
2662 
2663   ClearCommands();
2664 
2665   // Use invalid border.
2666   gl_->TexImage2D(
2667       kTarget, kLevel, kFormat, kWidth, kHeight, kInvalidBorder, kFormat, kType,
2668       pixels);
2669 
2670   EXPECT_TRUE(NoCommandsWritten());
2671   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
2672 
2673   ClearCommands();
2674 
2675   // Checking for CompressedTexImage2D argument validation is a bit tricky due
2676   // to (runtime-detected) compression formats. Try to infer the error with an
2677   // aux check.
2678   const GLenum kCompressedFormat = GL_ETC1_RGB8_OES;
2679   gl_->CompressedTexImage2D(kTarget, kLevel, kCompressedFormat, kWidth, kHeight,
2680                             kBorder, base::size(pixels), pixels);
2681 
2682   // In the above, kCompressedFormat and base::size(pixels) are possibly wrong
2683   // values. First ensure that these do not cause failures at the client. If
2684   // this check ever fails, it probably means that client checks more than at
2685   // the time of writing of this test. In this case, more code needs to be
2686   // written for this test.
2687   EXPECT_FALSE(NoCommandsWritten());
2688 
2689   ClearCommands();
2690 
2691   // Changing border to invalid border should make the call fail at the client
2692   // checks.
2693   gl_->CompressedTexImage2D(kTarget, kLevel, kCompressedFormat, kWidth, kHeight,
2694                             kInvalidBorder, base::size(pixels), pixels);
2695   EXPECT_TRUE(NoCommandsWritten());
2696   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
2697 }
2698 
TEST_F(GLES2ImplementationTest,TexImage3DSingleCommand)2699 TEST_F(GLES2ImplementationTest, TexImage3DSingleCommand) {
2700   struct Cmds {
2701     cmds::TexImage3D tex_image_3d;
2702   };
2703   const GLenum kTarget = GL_TEXTURE_3D;
2704   const GLint kLevel = 0;
2705   const GLint kBorder = 0;
2706   const GLenum kFormat = GL_RGB;
2707   const GLenum kType = GL_UNSIGNED_BYTE;
2708   const GLint kPixelStoreUnpackAlignment = 4;
2709   const GLsizei kWidth = 3;
2710   const GLsizei kDepth = 2;
2711 
2712   uint32_t size = 0;
2713   uint32_t unpadded_row_size = 0;
2714   uint32_t padded_row_size = 0;
2715   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2716       kWidth, 2, kDepth, kFormat, kType, kPixelStoreUnpackAlignment,
2717       &size, &unpadded_row_size, &padded_row_size));
2718   // Makes sure we can just send over the data in one command.
2719   const GLsizei kHeight = MaxTransferBufferSize() / padded_row_size / kDepth;
2720   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2721       kWidth, kHeight, kDepth, kFormat, kType, kPixelStoreUnpackAlignment,
2722       &size, nullptr, nullptr));
2723 
2724   std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
2725   for (uint32_t ii = 0; ii < size; ++ii) {
2726     pixels[ii] = static_cast<uint8_t>(ii);
2727   }
2728 
2729   ExpectedMemoryInfo mem = GetExpectedMemory(size);
2730 
2731   Cmds expected;
2732   expected.tex_image_3d.Init(
2733       kTarget, kLevel, kFormat, kWidth, kHeight, kDepth,
2734       kFormat, kType, mem.id, mem.offset);
2735 
2736   gl_->TexImage3D(
2737       kTarget, kLevel, kFormat, kWidth, kHeight, kDepth, kBorder,
2738       kFormat, kType, pixels.get());
2739 
2740   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2741   EXPECT_TRUE(CheckRect(kWidth, kHeight * kDepth, kFormat, kType,
2742                         kPixelStoreUnpackAlignment,
2743                         reinterpret_cast<uint8_t*>(pixels.get()), mem.ptr));
2744 }
2745 
TEST_F(GLES2ImplementationTest,TexImage3DViaMappedMem)2746 TEST_F(GLES2ImplementationTest, TexImage3DViaMappedMem) {
2747   if (!AllowExtraTransferBufferSize()) {
2748     LOG(WARNING) << "Low memory device do not support MappedMem. Skipping test";
2749     return;
2750   }
2751 
2752   struct Cmds {
2753     cmds::TexImage3D tex_image_3d;
2754   };
2755   const GLenum kTarget = GL_TEXTURE_3D;
2756   const GLint kLevel = 0;
2757   const GLint kBorder = 0;
2758   const GLenum kFormat = GL_RGB;
2759   const GLenum kType = GL_UNSIGNED_BYTE;
2760   const GLint kPixelStoreUnpackAlignment = 4;
2761   const GLsizei kWidth = 3;
2762   const GLsizei kDepth = 2;
2763 
2764   uint32_t size = 0;
2765   uint32_t unpadded_row_size = 0;
2766   uint32_t padded_row_size = 0;
2767   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2768       kWidth, 2, kDepth, kFormat, kType, kPixelStoreUnpackAlignment,
2769       &size, &unpadded_row_size, &padded_row_size));
2770   // Makes sure we can just send over the data in one command.
2771   const GLsizei kMaxHeight = MaxTransferBufferSize() / padded_row_size / kDepth;
2772   const GLsizei kHeight = kMaxHeight * 2;
2773   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2774       kWidth, kHeight, kDepth, kFormat, kType, kPixelStoreUnpackAlignment,
2775       &size, nullptr, nullptr));
2776 
2777   std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
2778   for (uint32_t ii = 0; ii < size; ++ii) {
2779     pixels[ii] = static_cast<uint8_t>(ii);
2780   }
2781 
2782   ExpectedMemoryInfo mem = GetExpectedMappedMemory(size);
2783 
2784   Cmds expected;
2785   expected.tex_image_3d.Init(
2786       kTarget, kLevel, kFormat, kWidth, kHeight, kDepth,
2787       kFormat, kType, mem.id, mem.offset);
2788 
2789   gl_->TexImage3D(
2790       kTarget, kLevel, kFormat, kWidth, kHeight, kDepth, kBorder,
2791       kFormat, kType, pixels.get());
2792 
2793   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2794   EXPECT_TRUE(CheckRect(kWidth, kHeight * kDepth, kFormat, kType,
2795                         kPixelStoreUnpackAlignment,
2796                         reinterpret_cast<uint8_t*>(pixels.get()), mem.ptr));
2797 }
2798 
TEST_F(GLES2ImplementationTest,TexImage3DViaTexSubImage3D)2799 TEST_F(GLES2ImplementationTest, TexImage3DViaTexSubImage3D) {
2800   // Set limit to 1 to effectively disable mapped memory.
2801   SetMappedMemoryLimit(1);
2802 
2803   struct Cmds {
2804     cmds::TexImage3D tex_image_3d;
2805     cmds::TexSubImage3D tex_sub_image_3d1;
2806     cmd::SetToken set_token;
2807     cmds::TexSubImage3D tex_sub_image_3d2;
2808   };
2809   const GLenum kTarget = GL_TEXTURE_3D;
2810   const GLint kLevel = 0;
2811   const GLint kBorder = 0;
2812   const GLenum kFormat = GL_RGB;
2813   const GLenum kType = GL_UNSIGNED_BYTE;
2814   const GLint kPixelStoreUnpackAlignment = 4;
2815   const GLsizei kWidth = 3;
2816 
2817   uint32_t size = 0;
2818   uint32_t unpadded_row_size = 0;
2819   uint32_t padded_row_size = 0;
2820   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2821       kWidth, 2, 1, kFormat, kType, kPixelStoreUnpackAlignment,
2822       &size, &unpadded_row_size, &padded_row_size));
2823   // Makes sure the data is more than one command can hold.
2824   const GLsizei kHeight = MaxTransferBufferSize() / padded_row_size + 3;
2825   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2826       kWidth, kHeight, 1, kFormat, kType, kPixelStoreUnpackAlignment, &size,
2827       nullptr, nullptr));
2828   uint32_t first_size = padded_row_size * (kHeight - 3);
2829   uint32_t second_size =
2830       padded_row_size * 3 - (padded_row_size - unpadded_row_size);
2831   EXPECT_EQ(size, first_size + second_size);
2832   ExpectedMemoryInfo mem1 = GetExpectedMemory(first_size);
2833   ExpectedMemoryInfo mem2 = GetExpectedMemory(second_size);
2834   std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
2835   for (uint32_t ii = 0; ii < size; ++ii) {
2836     pixels[ii] = static_cast<uint8_t>(ii);
2837   }
2838 
2839   Cmds expected;
2840   expected.tex_image_3d.Init(
2841       kTarget, kLevel, kFormat, kWidth, kHeight, 1, kFormat, kType, 0, 0);
2842   expected.tex_sub_image_3d1.Init(
2843       kTarget, kLevel, 0, 0, 0, kWidth, kHeight - 3, 1, kFormat, kType,
2844       mem1.id, mem1.offset, GL_TRUE);
2845   expected.tex_sub_image_3d2.Init(
2846       kTarget, kLevel, 0, kHeight - 3, 0, kWidth, 3, 1, kFormat, kType,
2847       mem2.id, mem2.offset, GL_TRUE);
2848   expected.set_token.Init(GetNextToken());
2849 
2850   gl_->TexImage3D(
2851       kTarget, kLevel, kFormat, kWidth, kHeight, 1, kBorder,
2852       kFormat, kType, pixels.get());
2853   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2854 }
2855 
2856 // Test TexSubImage3D with 4 writes
TEST_F(GLES2ImplementationTest,TexSubImage3D4Writes)2857 TEST_F(GLES2ImplementationTest, TexSubImage3D4Writes) {
2858   struct Cmds {
2859     cmds::TexSubImage3D tex_sub_image_3d1_1;
2860     cmd::SetToken set_token1;
2861     cmds::TexSubImage3D tex_sub_image_3d1_2;
2862     cmd::SetToken set_token2;
2863     cmds::TexSubImage3D tex_sub_image_3d2_1;
2864     cmd::SetToken set_token3;
2865     cmds::TexSubImage3D tex_sub_image_3d2_2;
2866   };
2867   const GLenum kTarget = GL_TEXTURE_3D;
2868   const GLint kLevel = 0;
2869   const GLint kXOffset = 0;
2870   const GLint kYOffset = 0;
2871   const GLint kZOffset = 0;
2872   const GLenum kFormat = GL_RGB;
2873   const GLenum kType = GL_UNSIGNED_BYTE;
2874   const GLint kPixelStoreUnpackAlignment = 4;
2875   const GLsizei kWidth = 3;
2876   const GLsizei kDepth = 2;
2877 
2878   uint32_t size = 0;
2879   uint32_t unpadded_row_size = 0;
2880   uint32_t padded_row_size = 0;
2881   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2882       kWidth, 2, 1, kFormat, kType, kPixelStoreUnpackAlignment,
2883       &size, &unpadded_row_size, &padded_row_size));
2884   const GLsizei kHeight = MaxTransferBufferSize() / padded_row_size + 2;
2885   ASSERT_TRUE(GLES2Util::ComputeImageDataSizes(
2886       kWidth, kHeight, kDepth, kFormat, kType, kPixelStoreUnpackAlignment,
2887       &size, nullptr, nullptr));
2888   uint32_t first_size = (kHeight - 2) * padded_row_size;
2889   uint32_t second_size = 2 * padded_row_size;
2890   uint32_t third_size = first_size;
2891   uint32_t fourth_size = second_size - (padded_row_size - unpadded_row_size);
2892   EXPECT_EQ(size, first_size + second_size + third_size + fourth_size);
2893 
2894   std::unique_ptr<uint8_t[]> pixels(new uint8_t[size]);
2895   for (uint32_t ii = 0; ii < size; ++ii) {
2896     pixels[ii] = static_cast<uint8_t>(ii);
2897   }
2898 
2899   ExpectedMemoryInfo mem1_1 = GetExpectedMemory(first_size);
2900   ExpectedMemoryInfo mem1_2 = GetExpectedMemory(second_size);
2901   ExpectedMemoryInfo mem2_1 = GetExpectedMemory(third_size);
2902   ExpectedMemoryInfo mem2_2 = GetExpectedMemory(fourth_size);
2903 
2904   Cmds expected;
2905   expected.tex_sub_image_3d1_1.Init(
2906       kTarget, kLevel, kXOffset, kYOffset, kZOffset,
2907       kWidth, kHeight - 2, 1, kFormat, kType,
2908       mem1_1.id, mem1_1.offset, GL_FALSE);
2909   expected.tex_sub_image_3d1_2.Init(
2910       kTarget, kLevel, kXOffset, kYOffset + kHeight - 2, kZOffset,
2911       kWidth, 2, 1, kFormat, kType, mem1_2.id, mem1_2.offset, GL_FALSE);
2912   expected.tex_sub_image_3d2_1.Init(
2913       kTarget, kLevel, kXOffset, kYOffset, kZOffset + 1,
2914       kWidth, kHeight - 2, 1, kFormat, kType,
2915       mem2_1.id, mem2_1.offset, GL_FALSE);
2916   expected.tex_sub_image_3d2_2.Init(
2917       kTarget, kLevel, kXOffset, kYOffset + kHeight - 2, kZOffset + 1,
2918       kWidth, 2, 1, kFormat, kType, mem2_2.id, mem2_2.offset, GL_FALSE);
2919   expected.set_token1.Init(GetNextToken());
2920   expected.set_token2.Init(GetNextToken());
2921   expected.set_token3.Init(GetNextToken());
2922 
2923   gl_->TexSubImage3D(
2924       kTarget, kLevel, kXOffset, kYOffset, kZOffset, kWidth, kHeight, kDepth,
2925       kFormat, kType, pixels.get());
2926 
2927   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
2928   uint32_t offset_to_last = first_size + second_size + third_size;
2929   EXPECT_TRUE(CheckRect(
2930       kWidth, 2, kFormat, kType, kPixelStoreUnpackAlignment,
2931       reinterpret_cast<uint8_t*>(pixels.get()) + offset_to_last, mem2_2.ptr));
2932 }
2933 
2934 // glGen* Ids must not be reused until glDelete* commands have been
2935 // flushed by glFlush.
TEST_F(GLES2ImplementationStrictSharedTest,FlushGenerationTestBuffers)2936 TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestBuffers) {
2937   FlushGenerationTest<GenBuffersAPI>();
2938 }
TEST_F(GLES2ImplementationStrictSharedTest,FlushGenerationTestRenderbuffers)2939 TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestRenderbuffers) {
2940   FlushGenerationTest<GenRenderbuffersAPI>();
2941 }
TEST_F(GLES2ImplementationStrictSharedTest,FlushGenerationTestTextures)2942 TEST_F(GLES2ImplementationStrictSharedTest, FlushGenerationTestTextures) {
2943   FlushGenerationTest<GenTexturesAPI>();
2944 }
2945 
2946 // glGen* Ids must not be reused cross-context until glDelete* commands are
2947 // flushed by glFlush, and the Ids are lazily freed after.
TEST_F(GLES2ImplementationStrictSharedTest,CrossContextGenerationTestBuffers)2948 TEST_F(GLES2ImplementationStrictSharedTest, CrossContextGenerationTestBuffers) {
2949   CrossContextGenerationTest<GenBuffersAPI>();
2950 }
TEST_F(GLES2ImplementationStrictSharedTest,CrossContextGenerationTestRenderbuffers)2951 TEST_F(GLES2ImplementationStrictSharedTest,
2952        CrossContextGenerationTestRenderbuffers) {
2953   CrossContextGenerationTest<GenRenderbuffersAPI>();
2954 }
TEST_F(GLES2ImplementationStrictSharedTest,CrossContextGenerationTestTextures)2955 TEST_F(GLES2ImplementationStrictSharedTest,
2956        CrossContextGenerationTestTextures) {
2957   CrossContextGenerationTest<GenTexturesAPI>();
2958 }
2959 
2960 // Test Delete which causes auto flush.  Tests a regression case that occurred
2961 // in testing.
TEST_F(GLES2ImplementationStrictSharedTest,CrossContextGenerationAutoFlushTestBuffers)2962 TEST_F(GLES2ImplementationStrictSharedTest,
2963        CrossContextGenerationAutoFlushTestBuffers) {
2964   CrossContextGenerationAutoFlushTest<GenBuffersAPI>();
2965 }
TEST_F(GLES2ImplementationStrictSharedTest,CrossContextGenerationAutoFlushTestRenderbuffers)2966 TEST_F(GLES2ImplementationStrictSharedTest,
2967        CrossContextGenerationAutoFlushTestRenderbuffers) {
2968   CrossContextGenerationAutoFlushTest<GenRenderbuffersAPI>();
2969 }
TEST_F(GLES2ImplementationStrictSharedTest,CrossContextGenerationAutoFlushTestTextures)2970 TEST_F(GLES2ImplementationStrictSharedTest,
2971        CrossContextGenerationAutoFlushTestTextures) {
2972   CrossContextGenerationAutoFlushTest<GenTexturesAPI>();
2973 }
2974 
2975 // Test deleting an invalid ID.
TEST_F(GLES2ImplementationStrictSharedTest,DeletingInvalidIdGeneratesErrorBuffers)2976 TEST_F(GLES2ImplementationStrictSharedTest,
2977        DeletingInvalidIdGeneratesErrorBuffers) {
2978   DeletingInvalidIdGeneratesError<GenBuffersAPI>();
2979 }
TEST_F(GLES2ImplementationStrictSharedTest,DeletingInvalidIdGeneratesErrorRenderbuffers)2980 TEST_F(GLES2ImplementationStrictSharedTest,
2981        DeletingInvalidIdGeneratesErrorRenderbuffers) {
2982   DeletingInvalidIdGeneratesError<GenRenderbuffersAPI>();
2983 }
TEST_F(GLES2ImplementationStrictSharedTest,DeletingInvalidIdGeneratesErrorTextures)2984 TEST_F(GLES2ImplementationStrictSharedTest,
2985        DeletingInvalidIdGeneratesErrorTextures) {
2986   DeletingInvalidIdGeneratesError<GenTexturesAPI>();
2987 }
2988 
2989 // Test double-deleting the same ID.
TEST_F(GLES2ImplementationStrictSharedTest,DoubleDeletingIdGeneratesErrorBuffers)2990 TEST_F(GLES2ImplementationStrictSharedTest,
2991        DoubleDeletingIdGeneratesErrorBuffers) {
2992   DoubleDeletingIdGeneratesError<GenBuffersAPI>();
2993 }
TEST_F(GLES2ImplementationStrictSharedTest,DoubleDeletingIdGeneratesErrorRenderbuffers)2994 TEST_F(GLES2ImplementationStrictSharedTest,
2995        DoubleDeletingIdGeneratesErrorRenderbuffers) {
2996   DoubleDeletingIdGeneratesError<GenRenderbuffersAPI>();
2997 }
TEST_F(GLES2ImplementationStrictSharedTest,DoubleDeletingIdGeneratesErrorTextures)2998 TEST_F(GLES2ImplementationStrictSharedTest,
2999        DoubleDeletingIdGeneratesErrorTextures) {
3000   DoubleDeletingIdGeneratesError<GenTexturesAPI>();
3001 }
3002 
TEST_F(GLES2ImplementationTest,GetString)3003 TEST_F(GLES2ImplementationTest, GetString) {
3004   const uint32_t kBucketId = GLES2Implementation::kResultBucketId;
3005   const Str7 kString = {"foobar"};
3006   // GL_CHROMIUM_map_sub is hard coded into GLES2Implementation.
3007   const char* expected_str =
3008       "foobar "
3009       "GL_CHROMIUM_image "
3010       "GL_CHROMIUM_map_sub "
3011       "GL_CHROMIUM_ordering_barrier "
3012       "GL_CHROMIUM_sync_point "
3013       "GL_EXT_unpack_subimage";
3014   const char kBad = 0x12;
3015   struct Cmds {
3016     cmd::SetBucketSize set_bucket_size1;
3017     cmds::GetString get_string;
3018     cmd::GetBucketStart get_bucket_start;
3019     cmd::SetToken set_token1;
3020     cmd::SetBucketSize set_bucket_size2;
3021   };
3022   ExpectedMemoryInfo mem1 = GetExpectedMemory(MaxTransferBufferSize());
3023   ExpectedMemoryInfo result1 =
3024       GetExpectedResultMemory(sizeof(cmd::GetBucketStart::Result));
3025   Cmds expected;
3026   expected.set_bucket_size1.Init(kBucketId, 0);
3027   expected.get_string.Init(GL_EXTENSIONS, kBucketId);
3028   expected.get_bucket_start.Init(
3029       kBucketId, result1.id, result1.offset,
3030       MaxTransferBufferSize(), mem1.id, mem1.offset);
3031   expected.set_token1.Init(GetNextToken());
3032   expected.set_bucket_size2.Init(kBucketId, 0);
3033   char buf[sizeof(kString) + 1];
3034   memset(buf, kBad, sizeof(buf));
3035 
3036   EXPECT_CALL(*command_buffer(), OnFlush())
3037       .WillOnce(DoAll(SetMemory(result1.ptr, uint32_t(sizeof(kString))),
3038                       SetMemory(mem1.ptr, kString)))
3039       .RetiresOnSaturation();
3040 
3041   const GLubyte* result = gl_->GetString(GL_EXTENSIONS);
3042   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3043   EXPECT_STREQ(expected_str, reinterpret_cast<const char*>(result));
3044 }
3045 
TEST_F(GLES2ImplementationTest,CreateProgram)3046 TEST_F(GLES2ImplementationTest, CreateProgram) {
3047   struct Cmds {
3048     cmds::CreateProgram cmd;
3049   };
3050 
3051   Cmds expected;
3052   expected.cmd.Init(kProgramsAndShadersStartId);
3053   GLuint id = gl_->CreateProgram();
3054   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3055   EXPECT_EQ(kProgramsAndShadersStartId, id);
3056 }
3057 
TEST_F(GLES2ImplementationTest,BufferDataLargerThanTransferBuffer)3058 TEST_F(GLES2ImplementationTest, BufferDataLargerThanTransferBuffer) {
3059   struct Cmds {
3060     cmds::BufferData set_size;
3061     cmds::BufferSubData copy_data1;
3062     cmd::SetToken set_token1;
3063     cmds::BufferSubData copy_data2;
3064     cmd::SetToken set_token2;
3065   };
3066   const unsigned kUsableSize =
3067       kTransferBufferSize - GLES2Implementation::kStartingOffset;
3068   uint8_t buf[kUsableSize * 2] = {
3069       0,
3070   };
3071 
3072   ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize);
3073   ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize);
3074 
3075   Cmds expected;
3076   expected.set_size.Init(GL_ARRAY_BUFFER, base::size(buf), 0, 0,
3077                          GL_DYNAMIC_DRAW);
3078   expected.copy_data1.Init(
3079       GL_ARRAY_BUFFER, 0, kUsableSize, mem1.id, mem1.offset);
3080   expected.set_token1.Init(GetNextToken());
3081   expected.copy_data2.Init(
3082       GL_ARRAY_BUFFER, kUsableSize, kUsableSize, mem2.id, mem2.offset);
3083   expected.set_token2.Init(GetNextToken());
3084   gl_->BufferData(GL_ARRAY_BUFFER, base::size(buf), buf, GL_DYNAMIC_DRAW);
3085   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3086 }
3087 
TEST_F(GLES2ImplementationTest,MultiDrawArraysWEBGLLargerThanTransferBuffer)3088 TEST_F(GLES2ImplementationTest, MultiDrawArraysWEBGLLargerThanTransferBuffer) {
3089   struct Cmds {
3090     cmds::MultiDrawBeginCHROMIUM begin;
3091     cmds::MultiDrawArraysCHROMIUM draw1;
3092     cmd::SetToken set_token1;
3093     cmds::MultiDrawArraysCHROMIUM draw2;
3094     cmd::SetToken set_token2;
3095     cmds::MultiDrawEndCHROMIUM end;
3096   };
3097   const unsigned kUsableSize =
3098       kTransferBufferSize - GLES2Implementation::kStartingOffset;
3099   const unsigned kDrawCount = kUsableSize / sizeof(int);
3100   const unsigned kChunkDrawCount = kDrawCount / 2;
3101   const unsigned kCountsOffset = kChunkDrawCount * sizeof(int);
3102   GLint firsts[kDrawCount] = {0};
3103   GLsizei counts[kDrawCount] = {0};
3104 
3105   ExpectedMemoryInfo mem1 = GetExpectedMemory(kUsableSize);
3106   ExpectedMemoryInfo mem2 = GetExpectedMemory(kUsableSize);
3107 
3108   Cmds expected;
3109   expected.begin.Init(kDrawCount);
3110   expected.draw1.Init(GL_TRIANGLES, mem1.id, mem1.offset, mem1.id,
3111                       mem1.offset + kCountsOffset, kChunkDrawCount);
3112   expected.set_token1.Init(GetNextToken());
3113   expected.draw2.Init(GL_TRIANGLES, mem2.id, mem2.offset, mem2.id,
3114                       mem2.offset + kCountsOffset, kChunkDrawCount);
3115   expected.set_token2.Init(GetNextToken());
3116   expected.end.Init();
3117   gl_->MultiDrawArraysWEBGL(GL_TRIANGLES, firsts, counts, kDrawCount);
3118   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3119 }
3120 
TEST_F(GLES2ImplementationTest,CapabilitiesAreCached)3121 TEST_F(GLES2ImplementationTest, CapabilitiesAreCached) {
3122   static const GLenum kStates[] = {
3123     GL_DITHER,
3124     GL_BLEND,
3125     GL_CULL_FACE,
3126     GL_DEPTH_TEST,
3127     GL_POLYGON_OFFSET_FILL,
3128     GL_SAMPLE_ALPHA_TO_COVERAGE,
3129     GL_SAMPLE_COVERAGE,
3130     GL_SCISSOR_TEST,
3131     GL_STENCIL_TEST,
3132   };
3133   struct Cmds {
3134     cmds::Enable enable_cmd;
3135   };
3136   Cmds expected;
3137 
3138   for (size_t ii = 0; ii < base::size(kStates); ++ii) {
3139     GLenum state = kStates[ii];
3140     expected.enable_cmd.Init(state);
3141     GLboolean result = gl_->IsEnabled(state);
3142     EXPECT_EQ(static_cast<GLboolean>(ii == 0), result);
3143     EXPECT_TRUE(NoCommandsWritten());
3144     const void* commands = GetPut();
3145     if (!result) {
3146       gl_->Enable(state);
3147       EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
3148     }
3149     ClearCommands();
3150     result = gl_->IsEnabled(state);
3151     EXPECT_TRUE(result);
3152     EXPECT_TRUE(NoCommandsWritten());
3153   }
3154 }
3155 
TEST_F(GLES2ImplementationTest,BindVertexArrayOES)3156 TEST_F(GLES2ImplementationTest, BindVertexArrayOES) {
3157   GLuint id = 0;
3158   gl_->GenVertexArraysOES(1, &id);
3159   ClearCommands();
3160 
3161   struct Cmds {
3162     cmds::BindVertexArrayOES cmd;
3163   };
3164   Cmds expected;
3165   expected.cmd.Init(id);
3166 
3167   const void* commands = GetPut();
3168   gl_->BindVertexArrayOES(id);
3169   EXPECT_EQ(0, memcmp(&expected, commands, sizeof(expected)));
3170   ClearCommands();
3171   gl_->BindVertexArrayOES(id);
3172   EXPECT_TRUE(NoCommandsWritten());
3173 }
3174 
TEST_F(GLES2ImplementationTest,BeginEndQueryEXT)3175 TEST_F(GLES2ImplementationTest, BeginEndQueryEXT) {
3176   // Test GetQueryivEXT returns 0 if no current query.
3177   GLint param = -1;
3178   gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, &param);
3179   EXPECT_EQ(0, param);
3180 
3181   GLuint expected_ids[2] = { 1, 2 }; // These must match what's actually genned.
3182   struct GenCmds {
3183     cmds::GenQueriesEXTImmediate gen;
3184     GLuint data[2];
3185   };
3186   GenCmds expected_gen_cmds;
3187   expected_gen_cmds.gen.Init(base::size(expected_ids), &expected_ids[0]);
3188   GLuint ids[base::size(expected_ids)] = {
3189       0,
3190   };
3191   gl_->GenQueriesEXT(base::size(expected_ids), &ids[0]);
3192   EXPECT_EQ(0, memcmp(
3193       &expected_gen_cmds, commands_, sizeof(expected_gen_cmds)));
3194   GLuint id1 = ids[0];
3195   GLuint id2 = ids[1];
3196   ClearCommands();
3197 
3198   // Test BeginQueryEXT fails if id = 0.
3199   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, 0);
3200   EXPECT_TRUE(NoCommandsWritten());
3201   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3202 
3203   // Test BeginQueryEXT inserts command.
3204   struct BeginCmds {
3205     cmds::BeginQueryEXT begin_query;
3206   };
3207   BeginCmds expected_begin_cmds;
3208   const void* commands = GetPut();
3209   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1);
3210   QueryTracker::Query* query = GetQuery(id1);
3211   ASSERT_TRUE(query != nullptr);
3212   expected_begin_cmds.begin_query.Init(
3213       GL_ANY_SAMPLES_PASSED_EXT, id1, query->shm_id(), query->shm_offset());
3214   EXPECT_EQ(0, memcmp(
3215       &expected_begin_cmds, commands, sizeof(expected_begin_cmds)));
3216   ClearCommands();
3217 
3218   // Test GetQueryivEXT returns id.
3219   param = -1;
3220   gl_->GetQueryivEXT(GL_ANY_SAMPLES_PASSED_EXT, GL_CURRENT_QUERY_EXT, &param);
3221   EXPECT_EQ(id1, static_cast<GLuint>(param));
3222   gl_->GetQueryivEXT(
3223       GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_CURRENT_QUERY_EXT, &param);
3224   EXPECT_EQ(0, param);
3225 
3226   // Test BeginQueryEXT fails if between Begin/End.
3227   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id2);
3228   EXPECT_TRUE(NoCommandsWritten());
3229   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3230 
3231   // Test EndQueryEXT fails if target not same as current query.
3232   ClearCommands();
3233   gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT);
3234   EXPECT_TRUE(NoCommandsWritten());
3235   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3236 
3237   // Test EndQueryEXT sends command
3238   struct EndCmds {
3239     cmds::EndQueryEXT end_query;
3240   };
3241   commands = GetPut();
3242   gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3243   EndCmds expected_end_cmds;
3244   expected_end_cmds.end_query.Init(
3245       GL_ANY_SAMPLES_PASSED_EXT, query->submit_count());
3246   EXPECT_EQ(0, memcmp(
3247       &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3248 
3249   // Test EndQueryEXT fails if no current query.
3250   ClearCommands();
3251   gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3252   EXPECT_TRUE(NoCommandsWritten());
3253   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3254 
3255   // Test 2nd Begin/End increments count.
3256   base::subtle::Atomic32 old_submit_count = query->submit_count();
3257   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_EXT, id1);
3258   EXPECT_EQ(old_submit_count, query->submit_count());
3259   commands = GetPut();
3260   gl_->EndQueryEXT(GL_ANY_SAMPLES_PASSED_EXT);
3261   EXPECT_NE(old_submit_count, query->submit_count());
3262   expected_end_cmds.end_query.Init(
3263       GL_ANY_SAMPLES_PASSED_EXT, query->submit_count());
3264   EXPECT_EQ(0, memcmp(
3265       &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3266 
3267   // Test BeginQueryEXT fails if target changed.
3268   ClearCommands();
3269   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, id1);
3270   EXPECT_TRUE(NoCommandsWritten());
3271   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3272 
3273   // Test GetQueryObjectuivEXT fails if unused id
3274   GLuint available = 0xBDu;
3275   ClearCommands();
3276   gl_->GetQueryObjectuivEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3277   EXPECT_TRUE(NoCommandsWritten());
3278   EXPECT_EQ(0xBDu, available);
3279   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3280 
3281   // Test GetQueryObjectuivEXT fails if bad id
3282   ClearCommands();
3283   gl_->GetQueryObjectuivEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3284   EXPECT_TRUE(NoCommandsWritten());
3285   EXPECT_EQ(0xBDu, available);
3286   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3287 
3288   // Test GetQueryObjectuivEXT CheckResultsAvailable
3289   ClearCommands();
3290   gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3291   EXPECT_EQ(0u, available);
3292 
3293   // Test GetQueryObjectui64vEXT fails if unused id
3294   GLuint64 available2 = 0xBDu;
3295   ClearCommands();
3296   gl_->GetQueryObjectui64vEXT(id2, GL_QUERY_RESULT_AVAILABLE_EXT, &available2);
3297   EXPECT_TRUE(NoCommandsWritten());
3298   EXPECT_EQ(0xBDu, available2);
3299   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3300 
3301   // Test GetQueryObjectui64vEXT fails if bad id
3302   ClearCommands();
3303   gl_->GetQueryObjectui64vEXT(4567, GL_QUERY_RESULT_AVAILABLE_EXT, &available2);
3304   EXPECT_TRUE(NoCommandsWritten());
3305   EXPECT_EQ(0xBDu, available2);
3306   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3307 
3308   // Test GetQueryObjectui64vEXT CheckResultsAvailable
3309   ClearCommands();
3310   gl_->GetQueryObjectui64vEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available2);
3311   EXPECT_EQ(0u, available2);
3312 }
3313 
TEST_F(GLES2ImplementationManualInitTest,BadQueryTargets)3314 TEST_F(GLES2ImplementationManualInitTest, BadQueryTargets) {
3315   ContextInitOptions init_options;
3316   init_options.sync_query = false;
3317   init_options.occlusion_query_boolean = false;
3318   init_options.timer_queries = false;
3319   ASSERT_TRUE(Initialize(init_options));
3320 
3321   GLuint id = 0;
3322   gl_->GenQueriesEXT(1, &id);
3323   ClearCommands();
3324 
3325   gl_->BeginQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM, id);
3326   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3327   EXPECT_EQ(nullptr, GetQuery(id));
3328 
3329   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED, id);
3330   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3331   EXPECT_EQ(nullptr, GetQuery(id));
3332 
3333   gl_->BeginQueryEXT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE, id);
3334   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3335   EXPECT_EQ(nullptr, GetQuery(id));
3336 
3337   gl_->BeginQueryEXT(GL_TIME_ELAPSED_EXT, id);
3338   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3339   EXPECT_EQ(nullptr, GetQuery(id));
3340 
3341   gl_->BeginQueryEXT(0x123, id);
3342   EXPECT_EQ(GL_INVALID_ENUM, CheckError());
3343   EXPECT_EQ(nullptr, GetQuery(id));
3344 
3345   gl_->QueryCounterEXT(id, GL_TIMESTAMP_EXT);
3346   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3347   EXPECT_EQ(nullptr, GetQuery(id));
3348 
3349   gl_->QueryCounterEXT(id, 0x123);
3350   EXPECT_EQ(GL_INVALID_ENUM, CheckError());
3351   EXPECT_EQ(nullptr, GetQuery(id));
3352 }
3353 
TEST_F(GLES2ImplementationTest,SetDisjointSync)3354 TEST_F(GLES2ImplementationTest, SetDisjointSync) {
3355   struct SetDisjointSyncCmd {
3356     cmds::SetDisjointValueSyncCHROMIUM disjoint_sync;
3357   };
3358   SetDisjointSyncCmd expected_disjoint_sync_cmd;
3359   const void* commands = GetPut();
3360   gl_->SetDisjointValueSyncCHROMIUM();
3361   expected_disjoint_sync_cmd.disjoint_sync.Init(
3362       GetQueryTracker()->DisjointCountSyncShmID(),
3363       GetQueryTracker()->DisjointCountSyncShmOffset());
3364 
3365   EXPECT_EQ(0, memcmp(&expected_disjoint_sync_cmd, commands,
3366                       sizeof(expected_disjoint_sync_cmd)));
3367 }
3368 
TEST_F(GLES2ImplementationTest,QueryCounterEXT)3369 TEST_F(GLES2ImplementationTest, QueryCounterEXT) {
3370   // These must match what's actually genned.
3371   GLuint expected_ids[3] = {1, 2, 3};
3372   struct GenCmds {
3373     cmds::GenQueriesEXTImmediate gen;
3374     GLuint data[3];
3375   };
3376   GenCmds expected_gen_cmds;
3377   expected_gen_cmds.gen.Init(base::size(expected_ids), &expected_ids[0]);
3378   GLuint ids[base::size(expected_ids)] = {
3379       0,
3380   };
3381   gl_->GenQueriesEXT(base::size(expected_ids), &ids[0]);
3382   EXPECT_EQ(0, memcmp(
3383       &expected_gen_cmds, commands_, sizeof(expected_gen_cmds)));
3384   GLuint id1 = ids[0];
3385   GLuint id2 = ids[1];
3386   GLuint id3 = ids[2];
3387   ClearCommands();
3388 
3389   // Make sure disjoint value is synchronized already.
3390   gl_->SetDisjointValueSyncCHROMIUM();
3391   ClearCommands();
3392 
3393   // Test QueryCounterEXT fails if id = 0.
3394   gl_->QueryCounterEXT(0, GL_TIMESTAMP_EXT);
3395   EXPECT_TRUE(NoCommandsWritten());
3396   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3397 
3398   // Test QueryCounterEXT fails if target is unknown.
3399   ClearCommands();
3400   gl_->QueryCounterEXT(id1, GL_TIME_ELAPSED_EXT);
3401   EXPECT_TRUE(NoCommandsWritten());
3402   EXPECT_EQ(GL_INVALID_ENUM, CheckError());
3403 
3404   // Test QueryCounterEXT inserts command.
3405   struct QueryCounterCmds {
3406     cmds::QueryCounterEXT query_counter;
3407   };
3408   QueryCounterCmds expected_query_counter_cmds;
3409   const void* commands = GetPut();
3410   gl_->QueryCounterEXT(id1, GL_TIMESTAMP_EXT);
3411   EXPECT_EQ(GL_NO_ERROR, CheckError());
3412   QueryTracker::Query* query = GetQuery(id1);
3413   ASSERT_TRUE(query != nullptr);
3414   expected_query_counter_cmds.query_counter.Init(
3415       id1, GL_TIMESTAMP_EXT, query->shm_id(), query->shm_offset(),
3416       query->submit_count());
3417   EXPECT_EQ(0, memcmp(&expected_query_counter_cmds, commands,
3418                       sizeof(expected_query_counter_cmds)));
3419 
3420   // Test QueryCounterEXT fails if id is reused with different target.
3421   ClearCommands();
3422   gl_->QueryCounterEXT(id1, GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM);
3423   EXPECT_TRUE(NoCommandsWritten());
3424   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3425 
3426   // Test 2nd QueryCounterEXT succeeds.
3427   commands = GetPut();
3428   gl_->QueryCounterEXT(id2, GL_TIMESTAMP_EXT);
3429   EXPECT_EQ(GL_NO_ERROR, CheckError());
3430   QueryTracker::Query* query2 = GetQuery(id2);
3431   ASSERT_TRUE(query2 != nullptr);
3432   expected_query_counter_cmds.query_counter.Init(
3433       id2, GL_TIMESTAMP_EXT, query2->shm_id(), query2->shm_offset(),
3434       query2->submit_count());
3435   EXPECT_EQ(0, memcmp(&expected_query_counter_cmds, commands,
3436                       sizeof(expected_query_counter_cmds)));
3437   ClearCommands();
3438 
3439   // Test 3rd QueryCounterEXT succeeds.
3440   commands = GetPut();
3441   gl_->QueryCounterEXT(id3, GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM);
3442   EXPECT_EQ(GL_NO_ERROR, CheckError());
3443   QueryTracker::Query* query3 = GetQuery(id3);
3444   ASSERT_TRUE(query3 != nullptr);
3445   expected_query_counter_cmds.query_counter.Init(
3446       id3, GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM, query3->shm_id(),
3447       query3->shm_offset(), query3->submit_count());
3448   EXPECT_EQ(0, memcmp(&expected_query_counter_cmds, commands,
3449                       sizeof(expected_query_counter_cmds)));
3450   ClearCommands();
3451 
3452   // Test QueryCounterEXT increments count.
3453   base::subtle::Atomic32 old_submit_count = query->submit_count();
3454   commands = GetPut();
3455   gl_->QueryCounterEXT(id1, GL_TIMESTAMP_EXT);
3456   EXPECT_EQ(GL_NO_ERROR, CheckError());
3457   EXPECT_NE(old_submit_count, query->submit_count());
3458   expected_query_counter_cmds.query_counter.Init(
3459       id1, GL_TIMESTAMP_EXT, query->shm_id(), query->shm_offset(),
3460       query->submit_count());
3461   EXPECT_EQ(0, memcmp(&expected_query_counter_cmds, commands,
3462                       sizeof(expected_query_counter_cmds)));
3463   ClearCommands();
3464 
3465   // Test GetQueryObjectuivEXT CheckResultsAvailable.
3466   GLuint available = 0xBDu;
3467   ClearCommands();
3468   gl_->GetQueryObjectuivEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3469   EXPECT_EQ(0u, available);
3470 
3471   available = 0xBDu;
3472   ClearCommands();
3473   gl_->GetQueryObjectuivEXT(id3, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3474   EXPECT_EQ(0u, available);
3475 
3476   // Test GetQueryObjectui64vEXT CheckResultsAvailable.
3477   GLuint64 available2 = 0xBDu;
3478   ClearCommands();
3479   gl_->GetQueryObjectui64vEXT(id1, GL_QUERY_RESULT_AVAILABLE_EXT, &available2);
3480   EXPECT_EQ(0u, available2);
3481 
3482   available2 = 0xBDu;
3483   ClearCommands();
3484   gl_->GetQueryObjectui64vEXT(id3, GL_QUERY_RESULT_AVAILABLE_EXT, &available2);
3485   EXPECT_EQ(0u, available2);
3486 }
3487 
TEST_F(GLES2ImplementationTest,ErrorQuery)3488 TEST_F(GLES2ImplementationTest, ErrorQuery) {
3489   GLuint id = 0;
3490   gl_->GenQueriesEXT(1, &id);
3491   ClearCommands();
3492 
3493   // Test BeginQueryEXT does NOT insert commands.
3494   gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id);
3495   EXPECT_TRUE(NoCommandsWritten());
3496   QueryTracker::Query* query = GetQuery(id);
3497   ASSERT_TRUE(query != nullptr);
3498 
3499   // Test EndQueryEXT sends both begin and end command
3500   struct EndCmds {
3501     cmds::BeginQueryEXT begin_query;
3502     cmds::EndQueryEXT end_query;
3503   };
3504   const void* commands = GetPut();
3505   gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM);
3506   EndCmds expected_end_cmds;
3507   expected_end_cmds.begin_query.Init(
3508       GL_GET_ERROR_QUERY_CHROMIUM, id, query->shm_id(), query->shm_offset());
3509   expected_end_cmds.end_query.Init(
3510       GL_GET_ERROR_QUERY_CHROMIUM, query->submit_count());
3511   EXPECT_EQ(0, memcmp(
3512       &expected_end_cmds, commands, sizeof(expected_end_cmds)));
3513   ClearCommands();
3514 
3515   // Check result is not yet available.
3516   GLuint available = 0xBDu;
3517   gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3518   EXPECT_TRUE(NoCommandsWritten());
3519   EXPECT_EQ(0u, available);
3520 
3521   // Test no commands are sent if there is a client side error.
3522 
3523   // Generate a client side error
3524   gl_->ActiveTexture(GL_TEXTURE0 - 1);
3525 
3526   gl_->BeginQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM, id);
3527   gl_->EndQueryEXT(GL_GET_ERROR_QUERY_CHROMIUM);
3528   EXPECT_TRUE(NoCommandsWritten());
3529 
3530   // Check result is available.
3531   gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_AVAILABLE_EXT, &available);
3532   EXPECT_TRUE(NoCommandsWritten());
3533   EXPECT_NE(0u, available);
3534 
3535   // Check result.
3536   GLuint result = 0xBDu;
3537   gl_->GetQueryObjectuivEXT(id, GL_QUERY_RESULT_EXT, &result);
3538   EXPECT_TRUE(NoCommandsWritten());
3539   EXPECT_EQ(static_cast<GLuint>(GL_INVALID_ENUM), result);
3540 }
3541 
3542 #if !defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS)
TEST_F(GLES2ImplementationTest,VertexArrays)3543 TEST_F(GLES2ImplementationTest, VertexArrays) {
3544   const GLuint kAttribIndex1 = 1;
3545   const GLint kNumComponents1 = 3;
3546   const GLsizei kClientStride = 12;
3547 
3548   GLuint id = 0;
3549   gl_->GenVertexArraysOES(1, &id);
3550   ClearCommands();
3551 
3552   gl_->BindVertexArrayOES(id);
3553 
3554   // Test that VertexAttribPointer cannot be called with a bound buffer of 0
3555   // unless the offset is nullptr
3556   gl_->BindBuffer(GL_ARRAY_BUFFER, 0);
3557 
3558   gl_->VertexAttribPointer(
3559       kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE, kClientStride,
3560       reinterpret_cast<const void*>(4));
3561   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3562 
3563   gl_->VertexAttribPointer(kAttribIndex1, kNumComponents1, GL_FLOAT, GL_FALSE,
3564                            kClientStride, nullptr);
3565   EXPECT_EQ(GL_NO_ERROR, CheckError());
3566 }
3567 #endif
3568 
TEST_F(GLES2ImplementationTest,Disable)3569 TEST_F(GLES2ImplementationTest, Disable) {
3570   struct Cmds {
3571     cmds::Disable cmd;
3572   };
3573   Cmds expected;
3574   expected.cmd.Init(GL_DITHER);  // Note: DITHER defaults to enabled.
3575 
3576   gl_->Disable(GL_DITHER);
3577   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3578   // Check it's cached and not called again.
3579   ClearCommands();
3580   gl_->Disable(GL_DITHER);
3581   EXPECT_TRUE(NoCommandsWritten());
3582 }
3583 
TEST_F(GLES2ImplementationTest,Enable)3584 TEST_F(GLES2ImplementationTest, Enable) {
3585   struct Cmds {
3586     cmds::Enable cmd;
3587   };
3588   Cmds expected;
3589   expected.cmd.Init(GL_BLEND);  // Note: BLEND defaults to disabled.
3590 
3591   gl_->Enable(GL_BLEND);
3592   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3593   // Check it's cached and not called again.
3594   ClearCommands();
3595   gl_->Enable(GL_BLEND);
3596   EXPECT_TRUE(NoCommandsWritten());
3597 }
3598 
TEST_F(GLES2ImplementationTest,CreateAndConsumeTextureCHROMIUM)3599 TEST_F(GLES2ImplementationTest, CreateAndConsumeTextureCHROMIUM) {
3600   struct Cmds {
3601     cmds::CreateAndConsumeTextureINTERNALImmediate cmd;
3602     GLbyte data[GL_MAILBOX_SIZE_CHROMIUM];
3603   };
3604 
3605   Mailbox mailbox = Mailbox::Generate();
3606   Cmds expected;
3607   expected.cmd.Init(kTexturesStartId, mailbox.name);
3608   GLuint id = gl_->CreateAndConsumeTextureCHROMIUM(mailbox.name);
3609   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3610   EXPECT_EQ(kTexturesStartId, id);
3611 }
3612 
TEST_F(GLES2ImplementationTest,CreateAndTexStorage2DSharedImageCHROMIUM)3613 TEST_F(GLES2ImplementationTest, CreateAndTexStorage2DSharedImageCHROMIUM) {
3614   struct Cmds {
3615     cmds::CreateAndTexStorage2DSharedImageINTERNALImmediate cmd;
3616     GLbyte data[GL_MAILBOX_SIZE_CHROMIUM];
3617   };
3618 
3619   Mailbox mailbox = Mailbox::GenerateForSharedImage();
3620   Cmds expected;
3621   expected.cmd.Init(kTexturesStartId, GL_NONE, mailbox.name);
3622   GLuint id = gl_->CreateAndTexStorage2DSharedImageCHROMIUM(mailbox.name);
3623   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3624   EXPECT_EQ(kTexturesStartId, id);
3625 }
3626 
TEST_F(GLES2ImplementationTest,CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM)3627 TEST_F(GLES2ImplementationTest,
3628        CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM) {
3629   struct Cmds {
3630     cmds::CreateAndTexStorage2DSharedImageINTERNALImmediate cmd;
3631     GLbyte data[GL_MAILBOX_SIZE_CHROMIUM];
3632   };
3633 
3634   Mailbox mailbox = Mailbox::GenerateForSharedImage();
3635   const GLenum kFormat = GL_RGBA;
3636   Cmds expected;
3637   expected.cmd.Init(kTexturesStartId, kFormat, mailbox.name);
3638   GLuint id = gl_->CreateAndTexStorage2DSharedImageWithInternalFormatCHROMIUM(
3639       mailbox.name, kFormat);
3640   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3641   EXPECT_EQ(kTexturesStartId, id);
3642 }
3643 
TEST_F(GLES2ImplementationTest,ProduceTextureDirectCHROMIUM)3644 TEST_F(GLES2ImplementationTest, ProduceTextureDirectCHROMIUM) {
3645   struct Cmds {
3646     cmds::ProduceTextureDirectCHROMIUMImmediate cmd;
3647     GLbyte data[GL_MAILBOX_SIZE_CHROMIUM];
3648   };
3649 
3650   Mailbox mailbox;
3651   gl_->ProduceTextureDirectCHROMIUM(kTexturesStartId, mailbox.name);
3652   Cmds expected;
3653   expected.cmd.Init(kTexturesStartId, mailbox.name);
3654   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3655 }
3656 
TEST_F(GLES2ImplementationTest,LimitSizeAndOffsetTo32Bit)3657 TEST_F(GLES2ImplementationTest, LimitSizeAndOffsetTo32Bit) {
3658   GLsizeiptr size;
3659   GLintptr offset;
3660   if (sizeof(size) <= 4 || sizeof(offset) <= 4)
3661     return;
3662   // The below two casts should be no-op, as we return early if
3663   // it's 32-bit system.
3664   int64_t value64 = 0x100000000;
3665   size = static_cast<GLsizeiptr>(value64);
3666   offset = static_cast<GLintptr>(value64);
3667 
3668   const char kSizeOverflowMessage[] = "size more than 32-bit";
3669   const char kOffsetOverflowMessage[] = "offset more than 32-bit";
3670 
3671   const GLfloat buf[] = { 1.0, 1.0, 1.0, 1.0 };
3672   const GLubyte indices[] = { 0 };
3673 
3674   const GLuint kClientArrayBufferId = 0x789;
3675   const GLuint kClientElementArrayBufferId = 0x790;
3676   gl_->BindBuffer(GL_ARRAY_BUFFER, kClientArrayBufferId);
3677   gl_->BindBuffer(GL_ELEMENT_ARRAY_BUFFER, kClientElementArrayBufferId);
3678   EXPECT_EQ(GL_NO_ERROR, CheckError());
3679 
3680   // Call BufferData() should succeed with legal paramaters.
3681   gl_->BufferData(GL_ARRAY_BUFFER, sizeof(buf), buf, GL_DYNAMIC_DRAW);
3682   gl_->BufferData(
3683       GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_DYNAMIC_DRAW);
3684   EXPECT_EQ(GL_NO_ERROR, CheckError());
3685 
3686   // BufferData: size
3687   gl_->BufferData(GL_ARRAY_BUFFER, size, buf, GL_DYNAMIC_DRAW);
3688   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3689   EXPECT_STREQ(kSizeOverflowMessage, GetLastError().c_str());
3690 
3691   // Call BufferSubData() should succeed with legal paramaters.
3692   gl_->BufferSubData(GL_ARRAY_BUFFER, 0, sizeof(buf[0]), buf);
3693   EXPECT_EQ(GL_NO_ERROR, CheckError());
3694 
3695   // BufferSubData: offset
3696   gl_->BufferSubData(GL_ARRAY_BUFFER, offset, 1, buf);
3697   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3698   EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3699 
3700   // BufferSubData: size
3701   EXPECT_EQ(GL_NO_ERROR, CheckError());
3702   gl_->BufferSubData(GL_ARRAY_BUFFER, 0, size, buf);
3703   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3704   EXPECT_STREQ(kSizeOverflowMessage, GetLastError().c_str());
3705 
3706   // Call MapBufferSubDataCHROMIUM() should succeed with legal paramaters.
3707   void* mem =
3708       gl_->MapBufferSubDataCHROMIUM(GL_ARRAY_BUFFER, 0, 1, GL_WRITE_ONLY);
3709   EXPECT_TRUE(nullptr != mem);
3710   EXPECT_EQ(GL_NO_ERROR, CheckError());
3711   gl_->UnmapBufferSubDataCHROMIUM(mem);
3712 
3713   // MapBufferSubDataCHROMIUM: offset
3714   EXPECT_TRUE(nullptr == gl_->MapBufferSubDataCHROMIUM(GL_ARRAY_BUFFER, offset,
3715                                                        1, GL_WRITE_ONLY));
3716   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3717   EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3718 
3719   // MapBufferSubDataCHROMIUM: size
3720   EXPECT_EQ(GL_NO_ERROR, CheckError());
3721   EXPECT_TRUE(nullptr == gl_->MapBufferSubDataCHROMIUM(GL_ARRAY_BUFFER, 0, size,
3722                                                        GL_WRITE_ONLY));
3723   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3724   EXPECT_STREQ(kSizeOverflowMessage, GetLastError().c_str());
3725 
3726   // Call DrawElements() should succeed with legal paramaters.
3727   gl_->DrawElements(GL_POINTS, 1, GL_UNSIGNED_BYTE, nullptr);
3728   EXPECT_EQ(GL_NO_ERROR, CheckError());
3729 
3730   // DrawElements: offset
3731   gl_->DrawElements(
3732       GL_POINTS, 1, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset));
3733   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3734   EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3735 
3736   // Call DrawElementsInstancedANGLE() should succeed with legal paramaters.
3737   gl_->DrawElementsInstancedANGLE(GL_POINTS, 1, GL_UNSIGNED_BYTE, nullptr, 1);
3738   EXPECT_EQ(GL_NO_ERROR, CheckError());
3739 
3740   // DrawElementsInstancedANGLE: offset
3741   gl_->DrawElementsInstancedANGLE(
3742       GL_POINTS, 1, GL_UNSIGNED_BYTE, reinterpret_cast<void*>(offset), 1);
3743   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3744   EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3745 
3746   // Call VertexAttribPointer() should succeed with legal paramaters.
3747   const GLuint kAttribIndex = 1;
3748   const GLsizei kStride = 4;
3749   gl_->VertexAttribPointer(kAttribIndex, 1, GL_FLOAT, GL_FALSE, kStride,
3750                            nullptr);
3751   EXPECT_EQ(GL_NO_ERROR, CheckError());
3752 
3753   // VertexAttribPointer: offset
3754   gl_->VertexAttribPointer(
3755       kAttribIndex, 1, GL_FLOAT, GL_FALSE, kStride,
3756       reinterpret_cast<void*>(offset));
3757   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3758   EXPECT_STREQ(kOffsetOverflowMessage, GetLastError().c_str());
3759 }
3760 
TEST_F(GLES2ImplementationTest,TraceBeginCHROMIUM)3761 TEST_F(GLES2ImplementationTest, TraceBeginCHROMIUM) {
3762   const uint32_t kCategoryBucketId = GLES2Implementation::kResultBucketId;
3763   const uint32_t kNameBucketId = GLES2Implementation::kResultBucketId + 1;
3764   const std::string category_name = "test category";
3765   const std::string trace_name = "test trace";
3766   const size_t kPaddedString1Size =
3767       transfer_buffer_->RoundToAlignment(category_name.size() + 1);
3768   const size_t kPaddedString2Size =
3769       transfer_buffer_->RoundToAlignment(trace_name.size() + 1);
3770 
3771   gl_->TraceBeginCHROMIUM(category_name.c_str(), trace_name.c_str());
3772   EXPECT_EQ(GL_NO_ERROR, CheckError());
3773 
3774   struct Cmds {
3775     cmd::SetBucketSize category_size1;
3776     cmd::SetBucketData category_data;
3777     cmd::SetToken set_token1;
3778     cmd::SetBucketSize name_size1;
3779     cmd::SetBucketData name_data;
3780     cmd::SetToken set_token2;
3781     cmds::TraceBeginCHROMIUM trace_call_begin;
3782     cmd::SetBucketSize category_size2;
3783     cmd::SetBucketSize name_size2;
3784   };
3785 
3786   ExpectedMemoryInfo mem1 = GetExpectedMemory(kPaddedString1Size);
3787   ExpectedMemoryInfo mem2 = GetExpectedMemory(kPaddedString2Size);
3788 
3789   ASSERT_STREQ(category_name.c_str(), reinterpret_cast<char*>(mem1.ptr));
3790   ASSERT_STREQ(trace_name.c_str(), reinterpret_cast<char*>(mem2.ptr));
3791 
3792   Cmds expected;
3793   expected.category_size1.Init(kCategoryBucketId, category_name.size() + 1);
3794   expected.category_data.Init(
3795       kCategoryBucketId, 0, category_name.size() + 1, mem1.id, mem1.offset);
3796   expected.set_token1.Init(GetNextToken());
3797   expected.name_size1.Init(kNameBucketId, trace_name.size() + 1);
3798   expected.name_data.Init(
3799       kNameBucketId, 0, trace_name.size() + 1, mem2.id, mem2.offset);
3800   expected.set_token2.Init(GetNextToken());
3801   expected.trace_call_begin.Init(kCategoryBucketId, kNameBucketId);
3802   expected.category_size2.Init(kCategoryBucketId, 0);
3803   expected.name_size2.Init(kNameBucketId, 0);
3804 
3805   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3806 }
3807 
TEST_F(GLES2ImplementationTest,SetActiveURLCHROMIUM)3808 TEST_F(GLES2ImplementationTest, SetActiveURLCHROMIUM) {
3809   const uint32_t kURLBucketId = GLES2Implementation::kResultBucketId;
3810   const std::string url = "chrome://test";
3811   const size_t kPaddedStringSize =
3812       transfer_buffer_->RoundToAlignment(url.size());
3813 
3814   gl_->SetActiveURLCHROMIUM(url.c_str());
3815   EXPECT_EQ(GL_NO_ERROR, CheckError());
3816 
3817   struct Cmds {
3818     cmd::SetBucketSize url_size;
3819     cmd::SetBucketData url_data;
3820     cmd::SetToken set_token;
3821     cmds::SetActiveURLCHROMIUM set_url_call;
3822     cmd::SetBucketSize url_size_end;
3823   };
3824 
3825   ExpectedMemoryInfo mem = GetExpectedMemory(kPaddedStringSize);
3826   EXPECT_EQ(0,
3827             memcmp(url.c_str(), reinterpret_cast<char*>(mem.ptr), url.size()));
3828 
3829   Cmds expected;
3830   expected.url_size.Init(kURLBucketId, url.size());
3831   expected.url_data.Init(kURLBucketId, 0, url.size(), mem.id, mem.offset);
3832   expected.set_token.Init(GetNextToken());
3833   expected.set_url_call.Init(kURLBucketId);
3834   expected.url_size_end.Init(kURLBucketId, 0);
3835   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
3836 
3837   // Same URL shouldn't make any commands.
3838   EXPECT_FALSE(NoCommandsWritten());
3839   ClearCommands();
3840   gl_->SetActiveURLCHROMIUM(url.c_str());
3841   EXPECT_TRUE(NoCommandsWritten());
3842 }
3843 
TEST_F(GLES2ImplementationTest,AllowNestedTracesCHROMIUM)3844 TEST_F(GLES2ImplementationTest, AllowNestedTracesCHROMIUM) {
3845   const std::string category1_name = "test category 1";
3846   const std::string trace1_name = "test trace 1";
3847   const std::string category2_name = "test category 2";
3848   const std::string trace2_name = "test trace 2";
3849 
3850   gl_->TraceBeginCHROMIUM(category1_name.c_str(), trace1_name.c_str());
3851   EXPECT_EQ(GL_NO_ERROR, CheckError());
3852 
3853   gl_->TraceBeginCHROMIUM(category2_name.c_str(), trace2_name.c_str());
3854   EXPECT_EQ(GL_NO_ERROR, CheckError());
3855 
3856   gl_->TraceEndCHROMIUM();
3857   EXPECT_EQ(GL_NO_ERROR, CheckError());
3858 
3859   gl_->TraceEndCHROMIUM();
3860   EXPECT_EQ(GL_NO_ERROR, CheckError());
3861 
3862   // No more corresponding begin tracer marker should error.
3863   gl_->TraceEndCHROMIUM();
3864   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
3865 }
3866 
TEST_F(GLES2ImplementationTest,GenSyncTokenCHROMIUM)3867 TEST_F(GLES2ImplementationTest, GenSyncTokenCHROMIUM) {
3868   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
3869   const CommandBufferId kCommandBufferId =
3870       CommandBufferId::FromUnsafeValue(234u);
3871   const GLuint64 kFenceSync = 123u;
3872   SyncToken sync_token;
3873 
3874   EXPECT_CALL(*gpu_control_, GetNamespaceID())
3875       .WillRepeatedly(Return(kNamespaceId));
3876   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
3877       .WillRepeatedly(Return(kCommandBufferId));
3878 
3879   gl_->GenSyncTokenCHROMIUM(nullptr);
3880   EXPECT_TRUE(NoCommandsWritten());
3881   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
3882 
3883   const void* commands = GetPut();
3884   cmd::InsertFenceSync insert_fence_sync;
3885   insert_fence_sync.Init(kFenceSync);
3886 
3887   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
3888       .WillOnce(Return(kFenceSync));
3889   EXPECT_CALL(*gpu_control_, EnsureWorkVisible());
3890   gl_->GenSyncTokenCHROMIUM(sync_token.GetData());
3891   EXPECT_EQ(0, memcmp(&insert_fence_sync, commands, sizeof(insert_fence_sync)));
3892   EXPECT_EQ(GL_NO_ERROR, CheckError());
3893 
3894   EXPECT_TRUE(sync_token.verified_flush());
3895   EXPECT_EQ(kNamespaceId, sync_token.namespace_id());
3896   EXPECT_EQ(kCommandBufferId, sync_token.command_buffer_id());
3897   EXPECT_EQ(kFenceSync, sync_token.release_count());
3898 }
3899 
TEST_F(GLES2ImplementationTest,GenUnverifiedSyncTokenCHROMIUM)3900 TEST_F(GLES2ImplementationTest, GenUnverifiedSyncTokenCHROMIUM) {
3901   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
3902   const CommandBufferId kCommandBufferId =
3903       CommandBufferId::FromUnsafeValue(234u);
3904   const GLuint64 kFenceSync = 123u;
3905   SyncToken sync_token;
3906 
3907   EXPECT_CALL(*gpu_control_, GetNamespaceID())
3908       .WillRepeatedly(Return(kNamespaceId));
3909   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
3910       .WillRepeatedly(Return(kCommandBufferId));
3911 
3912   gl_->GenUnverifiedSyncTokenCHROMIUM(nullptr);
3913   EXPECT_TRUE(NoCommandsWritten());
3914   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
3915 
3916   const void* commands = GetPut();
3917   cmd::InsertFenceSync insert_fence_sync;
3918   insert_fence_sync.Init(kFenceSync);
3919 
3920   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
3921       .WillOnce(Return(kFenceSync));
3922   gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
3923   EXPECT_EQ(0, memcmp(&insert_fence_sync, commands, sizeof(insert_fence_sync)));
3924   EXPECT_EQ(GL_NO_ERROR, CheckError());
3925 
3926   EXPECT_FALSE(sync_token.verified_flush());
3927   EXPECT_EQ(kNamespaceId, sync_token.namespace_id());
3928   EXPECT_EQ(kCommandBufferId, sync_token.command_buffer_id());
3929   EXPECT_EQ(kFenceSync, sync_token.release_count());
3930 }
3931 
TEST_F(GLES2ImplementationTest,VerifySyncTokensCHROMIUM)3932 TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM) {
3933   ExpectedMemoryInfo result =
3934       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
3935   EXPECT_CALL(*command_buffer(), OnFlush())
3936       .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
3937       .RetiresOnSaturation();
3938 
3939   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
3940   const CommandBufferId kCommandBufferId =
3941       CommandBufferId::FromUnsafeValue(234u);
3942   const GLuint64 kFenceSync = 123u;
3943   gpu::SyncToken sync_token;
3944   GLbyte* sync_token_datas[] = {sync_token.GetData()};
3945 
3946   EXPECT_CALL(*gpu_control_, GetNamespaceID())
3947       .WillRepeatedly(Return(kNamespaceId));
3948   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
3949       .WillRepeatedly(Return(kCommandBufferId));
3950 
3951   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
3952       .WillOnce(Return(kFenceSync));
3953   gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
3954   EXPECT_TRUE(sync_token.HasData());
3955   EXPECT_FALSE(sync_token.verified_flush());
3956 
3957   ClearCommands();
3958   EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(sync_token))
3959       .WillOnce(Return(false));
3960   gl_->VerifySyncTokensCHROMIUM(sync_token_datas, 1);
3961   EXPECT_TRUE(NoCommandsWritten());
3962   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
3963   EXPECT_FALSE(sync_token.verified_flush());
3964 
3965   ClearCommands();
3966   EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(sync_token))
3967       .WillOnce(Return(true));
3968   EXPECT_CALL(*gpu_control_, EnsureWorkVisible());
3969   gl_->VerifySyncTokensCHROMIUM(sync_token_datas, base::size(sync_token_datas));
3970   EXPECT_TRUE(NoCommandsWritten());
3971   EXPECT_EQ(GL_NO_ERROR, CheckError());
3972 
3973   EXPECT_EQ(kNamespaceId, sync_token.namespace_id());
3974   EXPECT_EQ(kCommandBufferId, sync_token.command_buffer_id());
3975   EXPECT_EQ(kFenceSync, sync_token.release_count());
3976   EXPECT_TRUE(sync_token.verified_flush());
3977 }
3978 
TEST_F(GLES2ImplementationTest,VerifySyncTokensCHROMIUM_Sequence)3979 TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM_Sequence) {
3980   // To verify sync tokens, the sync tokens must all be verified after
3981   // CanWaitUnverifiedSyncTokens() are called. This test ensures the right
3982   // sequence.
3983   ExpectedMemoryInfo result =
3984       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
3985   EXPECT_CALL(*command_buffer(), OnFlush())
3986       .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
3987       .RetiresOnSaturation();
3988 
3989   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
3990   const CommandBufferId kCommandBufferId =
3991       CommandBufferId::FromUnsafeValue(234u);
3992   const GLuint64 kFenceSync1 = 123u;
3993   const GLuint64 kFenceSync2 = 234u;
3994   gpu::SyncToken sync_token1;
3995   gpu::SyncToken sync_token2;
3996   GLbyte* sync_token_datas[] = {sync_token1.GetData(), sync_token2.GetData()};
3997 
3998   EXPECT_CALL(*gpu_control_, GetNamespaceID())
3999       .WillRepeatedly(Return(kNamespaceId));
4000   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
4001       .WillRepeatedly(Return(kCommandBufferId));
4002 
4003   // Generate sync token 1.
4004   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
4005       .WillOnce(Return(kFenceSync1));
4006   gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token1.GetData());
4007   EXPECT_TRUE(sync_token1.HasData());
4008   EXPECT_FALSE(sync_token1.verified_flush());
4009 
4010   // Generate sync token 2.
4011   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
4012       .WillOnce(Return(kFenceSync2));
4013   gl_->GenUnverifiedSyncTokenCHROMIUM(sync_token2.GetData());
4014   EXPECT_TRUE(sync_token2.HasData());
4015   EXPECT_FALSE(sync_token2.verified_flush());
4016 
4017   // Ensure proper sequence of checking and validating.
4018   Sequence sequence;
4019   EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(sync_token1))
4020       .InSequence(sequence)
4021       .WillOnce(Return(true));
4022   EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(sync_token2))
4023       .InSequence(sequence)
4024       .WillOnce(Return(true));
4025   EXPECT_CALL(*gpu_control_, EnsureWorkVisible()).InSequence(sequence);
4026   gl_->VerifySyncTokensCHROMIUM(sync_token_datas, base::size(sync_token_datas));
4027   EXPECT_EQ(GL_NO_ERROR, CheckError());
4028 
4029   EXPECT_TRUE(sync_token1.verified_flush());
4030   EXPECT_TRUE(sync_token2.verified_flush());
4031 }
4032 
TEST_F(GLES2ImplementationTest,VerifySyncTokensCHROMIUM_EmptySyncToken)4033 TEST_F(GLES2ImplementationTest, VerifySyncTokensCHROMIUM_EmptySyncToken) {
4034   // To verify sync tokens, the sync tokens must all be verified after
4035   // CanWaitUnverifiedSyncTokens() are called. This test ensures the right
4036   // sequence.
4037   ExpectedMemoryInfo result =
4038       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
4039   EXPECT_CALL(*command_buffer(), OnFlush())
4040       .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
4041       .RetiresOnSaturation();
4042 
4043   gpu::SyncToken sync_token1, sync_token2;
4044   GLbyte* sync_token_datas[] = {sync_token1.GetData(), sync_token2.GetData()};
4045 
4046   // Ensure proper sequence of checking and validating.
4047   EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(_)).Times(0);
4048   EXPECT_CALL(*gpu_control_, EnsureWorkVisible()).Times(0);
4049   gl_->VerifySyncTokensCHROMIUM(sync_token_datas, base::size(sync_token_datas));
4050   EXPECT_TRUE(NoCommandsWritten());
4051   EXPECT_EQ(GL_NO_ERROR, CheckError());
4052 
4053   EXPECT_TRUE(sync_token1.verified_flush());
4054   EXPECT_TRUE(sync_token2.verified_flush());
4055 }
4056 
TEST_F(GLES2ImplementationTest,WaitSyncTokenCHROMIUM)4057 TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUM) {
4058   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
4059   const CommandBufferId kCommandBufferId =
4060       CommandBufferId::FromUnsafeValue(234u);
4061   const GLuint64 kFenceSync = 456u;
4062 
4063   gpu::SyncToken sync_token;
4064   GLbyte* sync_token_data = sync_token.GetData();
4065 
4066   struct Cmds {
4067     cmd::InsertFenceSync insert_fence_sync;
4068   };
4069   Cmds expected;
4070   expected.insert_fence_sync.Init(kFenceSync);
4071 
4072   EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(kNamespaceId));
4073   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
4074       .WillOnce(Return(kCommandBufferId));
4075   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
4076       .WillOnce(Return(kFenceSync));
4077   EXPECT_CALL(*gpu_control_, EnsureWorkVisible());
4078   gl_->GenSyncTokenCHROMIUM(sync_token_data);
4079 
4080   EXPECT_CALL(*gpu_control_, WaitSyncToken(sync_token));
4081   gl_->WaitSyncTokenCHROMIUM(sync_token_data);
4082   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4083 }
4084 
TEST_F(GLES2ImplementationTest,WaitSyncTokenCHROMIUMErrors)4085 TEST_F(GLES2ImplementationTest, WaitSyncTokenCHROMIUMErrors) {
4086   ExpectedMemoryInfo result =
4087       GetExpectedResultMemory(sizeof(cmds::GetError::Result));
4088   EXPECT_CALL(*command_buffer(), OnFlush())
4089       .WillRepeatedly(SetMemory(result.ptr, GLuint(GL_NO_ERROR)))
4090       .RetiresOnSaturation();
4091 
4092   // Empty sync tokens should be produce no error and be a nop.
4093   ClearCommands();
4094   gl_->WaitSyncTokenCHROMIUM(nullptr);
4095   EXPECT_TRUE(NoCommandsWritten());
4096   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
4097 
4098   // Invalid sync tokens should produce no error and be a nop.
4099   ClearCommands();
4100   gpu::SyncToken invalid_sync_token;
4101   gl_->WaitSyncTokenCHROMIUM(invalid_sync_token.GetConstData());
4102   EXPECT_TRUE(NoCommandsWritten());
4103   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetError());
4104 
4105   // Unverified sync token should produce INVALID_OPERATION.
4106   ClearCommands();
4107   gpu::SyncToken unverified_sync_token(CommandBufferNamespace::GPU_IO,
4108                                        gpu::CommandBufferId(), 0);
4109   EXPECT_CALL(*gpu_control_, CanWaitUnverifiedSyncToken(unverified_sync_token))
4110       .WillOnce(Return(false));
4111   gl_->WaitSyncTokenCHROMIUM(unverified_sync_token.GetConstData());
4112   EXPECT_TRUE(NoCommandsWritten());
4113   EXPECT_EQ(static_cast<GLenum>(GL_INVALID_VALUE), gl_->GetError());
4114 }
4115 
TEST_F(GLES2ImplementationTest,IsEnabled)4116 TEST_F(GLES2ImplementationTest, IsEnabled) {
4117   // If we use a valid enum, its state is cached on client side, so no command
4118   // is actually generated, and this test will fail.
4119   // TODO(zmo): it seems we never need the command. Maybe remove it.
4120   GLenum kCap = 1;
4121   struct Cmds {
4122     cmds::IsEnabled cmd;
4123   };
4124 
4125   Cmds expected;
4126   ExpectedMemoryInfo result1 =
4127       GetExpectedResultMemory(sizeof(cmds::IsEnabled::Result));
4128   expected.cmd.Init(kCap, result1.id, result1.offset);
4129 
4130   EXPECT_CALL(*command_buffer(), OnFlush())
4131       .WillOnce(SetMemory(result1.ptr, uint32_t(GL_TRUE)))
4132       .RetiresOnSaturation();
4133 
4134   GLboolean result = gl_->IsEnabled(kCap);
4135   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4136   EXPECT_TRUE(result);
4137 }
4138 
TEST_F(GLES2ImplementationTest,ClientWaitSync)4139 TEST_F(GLES2ImplementationTest, ClientWaitSync) {
4140   const GLuint client_sync_id = 36;
4141   struct Cmds {
4142     cmds::ClientWaitSync cmd;
4143   };
4144 
4145   Cmds expected;
4146   ExpectedMemoryInfo result1 =
4147       GetExpectedResultMemory(sizeof(cmds::ClientWaitSync::Result));
4148   const GLuint64 kTimeout = 0xABCDEF0123456789;
4149   expected.cmd.Init(client_sync_id, GL_SYNC_FLUSH_COMMANDS_BIT,
4150                     kTimeout, result1.id, result1.offset);
4151 
4152   EXPECT_CALL(*command_buffer(), OnFlush())
4153       .WillOnce(SetMemory(result1.ptr, uint32_t(GL_CONDITION_SATISFIED)))
4154       .RetiresOnSaturation();
4155 
4156   GLenum result = gl_->ClientWaitSync(
4157       reinterpret_cast<GLsync>(client_sync_id), GL_SYNC_FLUSH_COMMANDS_BIT,
4158       kTimeout);
4159   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4160   EXPECT_EQ(static_cast<GLenum>(GL_CONDITION_SATISFIED), result);
4161 }
4162 
TEST_F(GLES2ImplementationTest,WaitSync)4163 TEST_F(GLES2ImplementationTest, WaitSync) {
4164   const GLuint kClientSyncId = 36;
4165   struct Cmds {
4166     cmds::WaitSync cmd;
4167   };
4168   Cmds expected;
4169   const GLuint64 kTimeout = GL_TIMEOUT_IGNORED;
4170   expected.cmd.Init(kClientSyncId, 0, kTimeout);
4171 
4172   gl_->WaitSync(reinterpret_cast<GLsync>(kClientSyncId), 0, kTimeout);
4173   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4174 }
4175 
TEST_F(GLES2ImplementationTest,MapBufferRangeUnmapBufferWrite)4176 TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferWrite) {
4177   ExpectedMemoryInfo result =
4178       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4179 
4180   EXPECT_CALL(*command_buffer(), OnFlush())
4181       .WillOnce(SetMemory(result.ptr, uint32_t(1)))
4182       .RetiresOnSaturation();
4183 
4184   const GLuint kBufferId = 123;
4185   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4186 
4187   void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
4188   EXPECT_TRUE(mem != nullptr);
4189 
4190   EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
4191 }
4192 
TEST_F(GLES2ImplementationTest,MapBufferRangeWriteWithInvalidateBit)4193 TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithInvalidateBit) {
4194   ExpectedMemoryInfo result =
4195       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4196 
4197   EXPECT_CALL(*command_buffer(), OnFlush())
4198       .WillOnce(SetMemory(result.ptr, uint32_t(1)))
4199       .RetiresOnSaturation();
4200 
4201   const GLuint kBufferId = 123;
4202   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4203 
4204   GLsizeiptr kSize = 64;
4205   void* mem = gl_->MapBufferRange(
4206       GL_ARRAY_BUFFER, 10, kSize,
4207       GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT);
4208   EXPECT_TRUE(mem != nullptr);
4209   std::vector<int8_t> zero(kSize);
4210   memset(&zero[0], 0, kSize);
4211   EXPECT_EQ(0, memcmp(mem, &zero[0], kSize));
4212 }
4213 
TEST_F(GLES2ImplementationTest,MapBufferRangeWriteWithGLError)4214 TEST_F(GLES2ImplementationTest, MapBufferRangeWriteWithGLError) {
4215   ExpectedMemoryInfo result =
4216       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4217 
4218   // Return a result of 0 to indicate an GL error.
4219   EXPECT_CALL(*command_buffer(), OnFlush())
4220       .WillOnce(SetMemory(result.ptr, uint32_t(0)))
4221       .RetiresOnSaturation();
4222 
4223   const GLuint kBufferId = 123;
4224   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4225 
4226   void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
4227   EXPECT_TRUE(mem == nullptr);
4228 }
4229 
TEST_F(GLES2ImplementationTest,MapBufferRangeUnmapBufferRead)4230 TEST_F(GLES2ImplementationTest, MapBufferRangeUnmapBufferRead) {
4231   ExpectedMemoryInfo result =
4232       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4233 
4234   EXPECT_CALL(*command_buffer(), OnFlush())
4235       .WillOnce(SetMemory(result.ptr, uint32_t(1)))
4236       .RetiresOnSaturation();
4237 
4238   const GLuint kBufferId = 123;
4239   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4240 
4241   void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT);
4242   EXPECT_TRUE(mem != nullptr);
4243 
4244   EXPECT_TRUE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
4245 }
4246 
TEST_F(GLES2ImplementationTest,MapBufferRangeReadWithGLError)4247 TEST_F(GLES2ImplementationTest, MapBufferRangeReadWithGLError) {
4248   ExpectedMemoryInfo result =
4249       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4250 
4251   // Return a result of 0 to indicate an GL error.
4252   EXPECT_CALL(*command_buffer(), OnFlush())
4253       .WillOnce(SetMemory(result.ptr, uint32_t(0)))
4254       .RetiresOnSaturation();
4255 
4256   const GLuint kBufferId = 123;
4257   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4258 
4259   void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_READ_BIT);
4260   EXPECT_TRUE(mem == nullptr);
4261 }
4262 
TEST_F(GLES2ImplementationTest,UnmapBufferFails)4263 TEST_F(GLES2ImplementationTest, UnmapBufferFails) {
4264   // No bound buffer.
4265   EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
4266   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
4267 
4268   const GLuint kBufferId = 123;
4269   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4270 
4271   // Buffer is unmapped.
4272   EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
4273   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
4274 }
4275 
TEST_F(GLES2ImplementationTest,BufferDataUnmapsDataStore)4276 TEST_F(GLES2ImplementationTest, BufferDataUnmapsDataStore) {
4277   ExpectedMemoryInfo result =
4278       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4279 
4280   EXPECT_CALL(*command_buffer(), OnFlush())
4281       .WillOnce(SetMemory(result.ptr, uint32_t(1)))
4282       .RetiresOnSaturation();
4283 
4284   const GLuint kBufferId = 123;
4285   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4286 
4287   void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
4288   EXPECT_TRUE(mem != nullptr);
4289 
4290   std::vector<uint8_t> data(16);
4291   // BufferData unmaps the data store.
4292   gl_->BufferData(GL_ARRAY_BUFFER, 16, &data[0], GL_STREAM_DRAW);
4293 
4294   EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
4295   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
4296 }
4297 
TEST_F(GLES2ImplementationTest,DeleteBuffersUnmapsDataStore)4298 TEST_F(GLES2ImplementationTest, DeleteBuffersUnmapsDataStore) {
4299   ExpectedMemoryInfo result =
4300       GetExpectedResultMemory(sizeof(cmds::MapBufferRange::Result));
4301 
4302   EXPECT_CALL(*command_buffer(), OnFlush())
4303       .WillOnce(SetMemory(result.ptr, uint32_t(1)))
4304       .RetiresOnSaturation();
4305 
4306   const GLuint kBufferId = 123;
4307   gl_->BindBuffer(GL_ARRAY_BUFFER, kBufferId);
4308 
4309   void* mem = gl_->MapBufferRange(GL_ARRAY_BUFFER, 10, 64, GL_MAP_WRITE_BIT);
4310   EXPECT_TRUE(mem != nullptr);
4311 
4312   std::vector<uint8_t> data(16);
4313   // DeleteBuffers unmaps the data store.
4314   gl_->DeleteBuffers(1, &kBufferId);
4315 
4316   EXPECT_FALSE(gl_->UnmapBuffer(GL_ARRAY_BUFFER));
4317   EXPECT_EQ(GL_INVALID_OPERATION, CheckError());
4318 }
4319 
TEST_F(GLES2ImplementationTest,GetInternalformativ)4320 TEST_F(GLES2ImplementationTest, GetInternalformativ) {
4321   const GLint kNumSampleCounts = 8;
4322   struct Cmds {
4323     cmds::GetInternalformativ cmd;
4324   };
4325   typedef cmds::GetInternalformativ::Result::Type ResultType;
4326   ResultType result = 0;
4327   Cmds expected;
4328   ExpectedMemoryInfo result1 =
4329       GetExpectedResultMemory(sizeof(uint32_t) + sizeof(ResultType));
4330   expected.cmd.Init(123, GL_RGBA8, GL_NUM_SAMPLE_COUNTS,
4331                     result1.id, result1.offset);
4332   EXPECT_CALL(*command_buffer(), OnFlush())
4333       .WillOnce(SetMemory(result1.ptr,
4334                           SizedResultHelper<ResultType>(kNumSampleCounts)))
4335       .RetiresOnSaturation();
4336   gl_->GetInternalformativ(123, GL_RGBA8, GL_NUM_SAMPLE_COUNTS, 1, &result);
4337   EXPECT_EQ(0, memcmp(&expected, commands_, sizeof(expected)));
4338   EXPECT_EQ(static_cast<ResultType>(kNumSampleCounts), result);
4339 }
4340 
CountCallback(int * count)4341 static void CountCallback(int* count) {
4342   (*count)++;
4343 }
4344 
TEST_F(GLES2ImplementationTest,SignalSyncToken)4345 TEST_F(GLES2ImplementationTest, SignalSyncToken) {
4346   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
4347   const CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(1);
4348   const uint64_t kFenceSync = 123u;
4349 
4350   EXPECT_CALL(*gpu_control_, GetNamespaceID())
4351       .WillRepeatedly(Return(kNamespaceId));
4352   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
4353       .WillRepeatedly(Return(kCommandBufferId));
4354 
4355   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
4356       .WillOnce(Return(kFenceSync));
4357   EXPECT_CALL(*gpu_control_, EnsureWorkVisible());
4358   gpu::SyncToken sync_token;
4359   gl_->GenSyncTokenCHROMIUM(sync_token.GetData());
4360 
4361   int signaled_count = 0;
4362 
4363   // Request a signal sync token, which gives a callback to the GpuControl to
4364   // run when the sync token is reached.
4365   base::OnceClosure signal_closure;
4366   EXPECT_CALL(*gpu_control_, DoSignalSyncToken(_, _))
4367       .WillOnce(Invoke([&signal_closure](const SyncToken& sync_token,
4368                                          base::OnceClosure* callback) {
4369         signal_closure = std::move(*callback);
4370       }));
4371   gl_->SignalSyncToken(sync_token,
4372                        base::BindOnce(&CountCallback, &signaled_count));
4373   EXPECT_EQ(0, signaled_count);
4374 
4375   // When GpuControl runs the callback, the original callback we gave to
4376   // GLES2Implementation is run.
4377   std::move(signal_closure).Run();
4378   EXPECT_EQ(1, signaled_count);
4379 }
4380 
TEST_F(GLES2ImplementationTest,SignalSyncTokenAfterContextLoss)4381 TEST_F(GLES2ImplementationTest, SignalSyncTokenAfterContextLoss) {
4382   const CommandBufferNamespace kNamespaceId = CommandBufferNamespace::GPU_IO;
4383   const CommandBufferId kCommandBufferId = CommandBufferId::FromUnsafeValue(1);
4384   const uint64_t kFenceSync = 123u;
4385 
4386   EXPECT_CALL(*gpu_control_, GetNamespaceID()).WillOnce(Return(kNamespaceId));
4387   EXPECT_CALL(*gpu_control_, GetCommandBufferID())
4388       .WillOnce(Return(kCommandBufferId));
4389   EXPECT_CALL(*gpu_control_, GenerateFenceSyncRelease())
4390       .WillOnce(Return(kFenceSync));
4391   EXPECT_CALL(*gpu_control_, EnsureWorkVisible());
4392   gpu::SyncToken sync_token;
4393   gl_->GenSyncTokenCHROMIUM(sync_token.GetData());
4394 
4395   int signaled_count = 0;
4396 
4397   // Request a signal sync token, which gives a callback to the GpuControl to
4398   // run when the sync token is reached.
4399   base::OnceClosure signal_closure;
4400   EXPECT_CALL(*gpu_control_, DoSignalSyncToken(_, _))
4401       .WillOnce(Invoke([&signal_closure](const SyncToken& sync_token,
4402                                          base::OnceClosure* callback) {
4403         signal_closure = std::move(*callback);
4404       }));
4405   gl_->SignalSyncToken(sync_token,
4406                        base::BindOnce(&CountCallback, &signaled_count));
4407   EXPECT_EQ(0, signaled_count);
4408 
4409   // Inform the GLES2Implementation that the context is lost.
4410   GpuControlClient* gl_as_client = gl_;
4411   gl_as_client->OnGpuControlLostContext();
4412 
4413   // When GpuControl runs the callback, the original callback we gave to
4414   // GLES2Implementation is *not* run, since the context is lost and we
4415   // have already run the lost context callback.
4416   std::move(signal_closure).Run();
4417   EXPECT_EQ(0, signaled_count);
4418 }
4419 
TEST_F(GLES2ImplementationTest,ReportLoss)4420 TEST_F(GLES2ImplementationTest, ReportLoss) {
4421   GpuControlClient* gl_as_client = gl_;
4422   int lost_count = 0;
4423   gl_->SetLostContextCallback(base::BindOnce(&CountCallback, &lost_count));
4424   EXPECT_EQ(0, lost_count);
4425 
4426   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR());
4427   gl_as_client->OnGpuControlLostContext();
4428   EXPECT_NE(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR());
4429   // The lost context callback should be run when GLES2Implementation is
4430   // notified of the loss.
4431   EXPECT_EQ(1, lost_count);
4432 }
4433 
TEST_F(GLES2ImplementationTest,ReportLossReentrant)4434 TEST_F(GLES2ImplementationTest, ReportLossReentrant) {
4435   GpuControlClient* gl_as_client = gl_;
4436   int lost_count = 0;
4437   gl_->SetLostContextCallback(base::BindOnce(&CountCallback, &lost_count));
4438   EXPECT_EQ(0, lost_count);
4439 
4440   EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR());
4441   gl_as_client->OnGpuControlLostContextMaybeReentrant();
4442   EXPECT_NE(static_cast<GLenum>(GL_NO_ERROR), gl_->GetGraphicsResetStatusKHR());
4443   // The lost context callback should not be run yet to avoid calling back into
4444   // clients re-entrantly, and having them re-enter GLES2Implementation.
4445   EXPECT_EQ(0, lost_count);
4446 }
4447 
TEST_F(GLES2ImplementationManualInitTest,FailInitOnBGRMismatch1)4448 TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch1) {
4449   ContextInitOptions init_options;
4450   init_options.bind_generates_resource_client = false;
4451   init_options.bind_generates_resource_service = true;
4452   EXPECT_FALSE(Initialize(init_options));
4453 }
4454 
TEST_F(GLES2ImplementationManualInitTest,FailInitOnBGRMismatch2)4455 TEST_F(GLES2ImplementationManualInitTest, FailInitOnBGRMismatch2) {
4456   ContextInitOptions init_options;
4457   init_options.bind_generates_resource_client = true;
4458   init_options.bind_generates_resource_service = false;
4459   EXPECT_FALSE(Initialize(init_options));
4460 }
4461 
TEST_F(GLES2ImplementationManualInitTest,FailInitOnTransferBufferFail)4462 TEST_F(GLES2ImplementationManualInitTest, FailInitOnTransferBufferFail) {
4463   ContextInitOptions init_options;
4464   init_options.transfer_buffer_initialize_fail = true;
4465   EXPECT_FALSE(Initialize(init_options));
4466 }
4467 
TEST_F(GLES2ImplementationTest,DiscardableMemoryDelete)4468 TEST_F(GLES2ImplementationTest, DiscardableMemoryDelete) {
4469   const GLuint texture_id = 1;
4470   EXPECT_FALSE(
4471       share_group_->discardable_texture_manager()->TextureIsValid(texture_id));
4472   gl_->InitializeDiscardableTextureCHROMIUM(texture_id);
4473   EXPECT_TRUE(
4474       share_group_->discardable_texture_manager()->TextureIsValid(texture_id));
4475 
4476   // Deleting a texture should clear its discardable entry.
4477   gl_->DeleteTextures(1, &texture_id);
4478   EXPECT_FALSE(
4479       share_group_->discardable_texture_manager()->TextureIsValid(texture_id));
4480 }
4481 
TEST_F(GLES2ImplementationTest,DiscardableTextureLockFail)4482 TEST_F(GLES2ImplementationTest, DiscardableTextureLockFail) {
4483   const GLuint texture_id = 1;
4484   gl_->InitializeDiscardableTextureCHROMIUM(texture_id);
4485   EXPECT_TRUE(
4486       share_group_->discardable_texture_manager()->TextureIsValid(texture_id));
4487 
4488   // Unlock the handle on the client side.
4489   gl_->UnlockDiscardableTextureCHROMIUM(texture_id);
4490 
4491   // Unlock and delete the handle on the service side.
4492   ClientDiscardableHandle client_handle =
4493       share_group_->discardable_texture_manager()->GetHandleForTesting(
4494           texture_id);
4495   ServiceDiscardableHandle service_handle(client_handle.BufferForTesting(),
4496                                           client_handle.byte_offset(),
4497                                           client_handle.shm_id());
4498   service_handle.Unlock();
4499   EXPECT_TRUE(service_handle.Delete());
4500 
4501   // Trying to re-lock the texture via GL should fail and delete the entry.
4502   EXPECT_FALSE(gl_->LockDiscardableTextureCHROMIUM(texture_id));
4503   EXPECT_FALSE(
4504       share_group_->discardable_texture_manager()->TextureIsValid(texture_id));
4505 }
4506 
TEST_F(GLES2ImplementationTest,DiscardableTextureDoubleInitError)4507 TEST_F(GLES2ImplementationTest, DiscardableTextureDoubleInitError) {
4508   const GLuint texture_id = 1;
4509   gl_->InitializeDiscardableTextureCHROMIUM(texture_id);
4510   EXPECT_EQ(GL_NO_ERROR, CheckError());
4511   gl_->InitializeDiscardableTextureCHROMIUM(texture_id);
4512   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
4513 }
4514 
TEST_F(GLES2ImplementationTest,DiscardableTextureLockError)4515 TEST_F(GLES2ImplementationTest, DiscardableTextureLockError) {
4516   const GLuint texture_id = 1;
4517   EXPECT_FALSE(gl_->LockDiscardableTextureCHROMIUM(texture_id));
4518   EXPECT_EQ(GL_INVALID_VALUE, CheckError());
4519 }
4520 
TEST_F(GLES2ImplementationTest,DiscardableTextureLockCounting)4521 TEST_F(GLES2ImplementationTest, DiscardableTextureLockCounting) {
4522   const GLint texture_id = 1;
4523   gl_->InitializeDiscardableTextureCHROMIUM(texture_id);
4524   EXPECT_TRUE(
4525       share_group_->discardable_texture_manager()->TextureIsValid(texture_id));
4526 
4527   // Bind the texture.
4528   gl_->BindTexture(GL_TEXTURE_2D, texture_id);
4529   GLint bound_texture_id = 0;
4530   gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture_id);
4531   EXPECT_EQ(texture_id, bound_texture_id);
4532 
4533   // Lock the texture 3 more times (for 4 locks total).
4534   for (int i = 0; i < 3; ++i) {
4535     gl_->LockDiscardableTextureCHROMIUM(texture_id);
4536   }
4537 
4538   // Unlock 4 times. Only after the last unlock should the texture be unbound.
4539   for (int i = 0; i < 4; ++i) {
4540     gl_->UnlockDiscardableTextureCHROMIUM(texture_id);
4541     bound_texture_id = 0;
4542     gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, &bound_texture_id);
4543     if (i < 3) {
4544       EXPECT_EQ(texture_id, bound_texture_id);
4545     } else {
4546       EXPECT_EQ(0, bound_texture_id);
4547     }
4548   }
4549 }
4550 
4551 struct ErrorMessageCounter {
ErrorMessageCountergpu::gles2::ErrorMessageCounter4552   explicit ErrorMessageCounter(GLES2Implementation* gl) : gl(gl) {}
4553 
Callbackgpu::gles2::ErrorMessageCounter4554   void Callback(const char* message, int32_t id) {
4555     if (++num_calls == 1)
4556       gl->ShaderBinary(-1, nullptr, 0, nullptr, 0);
4557   }
4558 
4559   GLES2Implementation* gl;
4560   int32_t num_calls = 0;
4561 };
4562 
TEST_F(GLES2ImplementationTest,ReentrantErrorCallbacksShouldNotCrash)4563 TEST_F(GLES2ImplementationTest, ReentrantErrorCallbacksShouldNotCrash) {
4564   ErrorMessageCounter counter(gl_);
4565   gl_->SetErrorMessageCallback(base::BindRepeating(
4566       &ErrorMessageCounter::Callback, base::Unretained(&counter)));
4567   // Call any function which can easily provoke an error. See also the
4568   // callback above.
4569   gl_->ShaderBinary(-1, nullptr, 0, nullptr, 0);
4570   EXPECT_EQ(2, counter.num_calls);
4571   ResetErrorMessageCallback();
4572 }
4573 
TEST_F(GLES2ImplementationTest,DeleteZero)4574 TEST_F(GLES2ImplementationTest, DeleteZero) {
4575   gl_->DeleteProgram(0);
4576   EXPECT_EQ(GL_NO_ERROR, CheckError());
4577   gl_->DeleteShader(0);
4578   EXPECT_EQ(GL_NO_ERROR, CheckError());
4579   gl_->DeleteSync(0);
4580   EXPECT_EQ(GL_NO_ERROR, CheckError());
4581 }
4582 
4583 #include "base/macros.h"
4584 #include "gpu/command_buffer/client/gles2_implementation_unittest_autogen.h"
4585 
4586 }  // namespace gles2
4587 }  // namespace gpu
4588