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, ¤t[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(¤t_attrib, ¤t, 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, ¶m);
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, ¶m);
3221 EXPECT_EQ(id1, static_cast<GLuint>(param));
3222 gl_->GetQueryivEXT(
3223 GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, GL_CURRENT_QUERY_EXT, ¶m);
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