1 // Copyright 2015 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 #include <stdint.h>
6
7 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
8 #include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
9
10 using ::gl::MockGLInterface;
11 using ::testing::_;
12 using ::testing::Return;
13 using ::testing::SetArgPointee;
14
15 namespace gpu {
16 namespace gles2 {
17
18 namespace {
19
20 } // namespace anonymous
21
TEST_P(GLES3DecoderTest,BindBufferBaseValidArgs)22 TEST_P(GLES3DecoderTest, BindBufferBaseValidArgs) {
23 EXPECT_CALL(
24 *gl_, BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kServiceBufferId));
25 SpecializedSetup<cmds::BindBufferBase, 0>(true);
26 cmds::BindBufferBase cmd;
27 cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, client_buffer_id_);
28 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
29 EXPECT_EQ(GL_NO_ERROR, GetGLError());
30 }
31
TEST_P(GLES3DecoderTest,BindBufferBaseValidArgsNewId)32 TEST_P(GLES3DecoderTest, BindBufferBaseValidArgsNewId) {
33 EXPECT_CALL(*gl_,
34 BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewServiceId));
35 EXPECT_CALL(*gl_, GenBuffersARB(1, _))
36 .WillOnce(SetArgPointee<1>(kNewServiceId));
37 SpecializedSetup<cmds::BindBufferBase, 0>(true);
38 cmds::BindBufferBase cmd;
39 cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId);
40 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
41 EXPECT_EQ(GL_NO_ERROR, GetGLError());
42 EXPECT_TRUE(GetBuffer(kNewClientId) != nullptr);
43 }
44
TEST_P(GLES3DecoderTest,BindBufferRangeValidArgs)45 TEST_P(GLES3DecoderTest, BindBufferRangeValidArgs) {
46 const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER;
47 const GLintptr kRangeOffset = 4;
48 const GLsizeiptr kRangeSize = 8;
49 const GLsizeiptr kBufferSize = kRangeOffset + kRangeSize;
50 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
51 DoBufferData(kTarget, kBufferSize);
52 EXPECT_CALL(*gl_, BindBufferRange(kTarget, 2, kServiceBufferId,
53 kRangeOffset, kRangeSize));
54 SpecializedSetup<cmds::BindBufferRange, 0>(true);
55 cmds::BindBufferRange cmd;
56 cmd.Init(kTarget, 2, client_buffer_id_, kRangeOffset, kRangeSize);
57 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
58 EXPECT_EQ(GL_NO_ERROR, GetGLError());
59 }
60
TEST_P(GLES3DecoderTest,BindBufferRangeValidArgsWithNoData)61 TEST_P(GLES3DecoderTest, BindBufferRangeValidArgsWithNoData) {
62 const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER;
63 const GLintptr kRangeOffset = 4;
64 const GLsizeiptr kRangeSize = 8;
65 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
66 EXPECT_CALL(*gl_, BindBufferBase(kTarget, 2, kServiceBufferId));
67 SpecializedSetup<cmds::BindBufferRange, 0>(true);
68 cmds::BindBufferRange cmd;
69 cmd.Init(kTarget, 2, client_buffer_id_, kRangeOffset, kRangeSize);
70 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
71 EXPECT_EQ(GL_NO_ERROR, GetGLError());
72 }
73
TEST_P(GLES3DecoderTest,BindBufferRangeValidArgsWithLessData)74 TEST_P(GLES3DecoderTest, BindBufferRangeValidArgsWithLessData) {
75 const GLenum kTarget = GL_TRANSFORM_FEEDBACK_BUFFER;
76 const GLintptr kRangeOffset = 4;
77 const GLsizeiptr kRangeSize = 8;
78 const GLsizeiptr kBufferSize = kRangeOffset + kRangeSize - 4;
79 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
80 DoBufferData(kTarget, kBufferSize);
81 EXPECT_CALL(*gl_, BindBufferRange(kTarget, 2, kServiceBufferId,
82 kRangeOffset, kRangeSize - 4));
83 SpecializedSetup<cmds::BindBufferRange, 0>(true);
84 cmds::BindBufferRange cmd;
85 cmd.Init(kTarget, 2, client_buffer_id_, kRangeOffset, kRangeSize);
86 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
87 EXPECT_EQ(GL_NO_ERROR, GetGLError());
88 }
89
TEST_P(GLES3DecoderTest,BindBufferRangeValidArgsNewId)90 TEST_P(GLES3DecoderTest, BindBufferRangeValidArgsNewId) {
91 EXPECT_CALL(*gl_, BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 2,
92 kNewServiceId));
93 EXPECT_CALL(*gl_, GenBuffersARB(1, _))
94 .WillOnce(SetArgPointee<1>(kNewServiceId));
95 SpecializedSetup<cmds::BindBufferRange, 0>(true);
96 cmds::BindBufferRange cmd;
97 cmd.Init(GL_TRANSFORM_FEEDBACK_BUFFER, 2, kNewClientId, 4, 4);
98 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
99 EXPECT_EQ(GL_NO_ERROR, GetGLError());
100 EXPECT_TRUE(GetBuffer(kNewClientId) != nullptr);
101 }
102
TEST_P(GLES3DecoderTest,MapBufferRangeUnmapBufferReadSucceeds)103 TEST_P(GLES3DecoderTest, MapBufferRangeUnmapBufferReadSucceeds) {
104 const GLenum kTarget = GL_ARRAY_BUFFER;
105 const GLintptr kOffset = 10;
106 const GLsizeiptr kSize = 64;
107 const GLbitfield kAccess = GL_MAP_READ_BIT;
108
109 uint32_t result_shm_id = shared_memory_id_;
110 uint32_t result_shm_offset = kSharedMemoryOffset;
111 uint32_t data_shm_id = shared_memory_id_;
112 // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
113 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
114
115 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
116 DoBufferData(kTarget, kSize + kOffset);
117
118 std::vector<int8_t> data(kSize);
119 for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
120 data[ii] = static_cast<int8_t>(ii % 255);
121 }
122
123 { // MapBufferRange
124 EXPECT_CALL(*gl_,
125 MapBufferRange(kTarget, kOffset, kSize, kAccess))
126 .WillOnce(Return(&data[0]))
127 .RetiresOnSaturation();
128
129 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
130
131 cmds::MapBufferRange cmd;
132 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
133 result_shm_id, result_shm_offset);
134 *result = 0;
135 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
136 int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
137 EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
138 EXPECT_EQ(1u, *result);
139 }
140
141 { // UnmapBuffer
142 EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
143 .WillOnce(Return(GL_TRUE))
144 .RetiresOnSaturation();
145
146 cmds::UnmapBuffer cmd;
147 cmd.Init(kTarget);
148 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
149 }
150
151 EXPECT_EQ(GL_NO_ERROR, GetGLError());
152 }
153
TEST_P(GLES3DecoderTest,MapBufferRangeUnmapBufferWriteSucceeds)154 TEST_P(GLES3DecoderTest, MapBufferRangeUnmapBufferWriteSucceeds) {
155 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
156 const GLintptr kOffset = 10;
157 const GLsizeiptr kSize = 64;
158 const GLsizeiptr kTotalSize = kOffset + kSize;
159 const GLbitfield kAccess = GL_MAP_WRITE_BIT;
160 const GLbitfield kMappedAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
161
162 uint32_t result_shm_id = shared_memory_id_;
163 uint32_t result_shm_offset = kSharedMemoryOffset;
164 uint32_t data_shm_id = shared_memory_id_;
165 // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
166 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
167
168 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
169 int8_t* client_data = GetSharedMemoryAs<int8_t*>() + sizeof(uint32_t);
170
171 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
172 Buffer* buffer = GetBuffer(client_buffer_id_);
173 EXPECT_TRUE(buffer != nullptr);
174 DoBufferData(kTarget, kTotalSize);
175 std::vector<int8_t> gpu_data(kTotalSize);
176 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
177 gpu_data[ii] = static_cast<int8_t>(ii % 128);
178 }
179 DoBufferSubData(kTarget, 0, kTotalSize, &gpu_data[0]);
180
181 EXPECT_EQ(GL_NO_ERROR, GetGLError());
182 EXPECT_TRUE(buffer->shadowed());
183 const int8_t* shadow_data = reinterpret_cast<const int8_t*>(
184 buffer->GetRange(0, kTotalSize));
185 EXPECT_TRUE(shadow_data);
186 // Verify the shadow data is initialized.
187 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
188 EXPECT_EQ(static_cast<int8_t>(ii % 128), shadow_data[ii]);
189 }
190
191 { // MapBufferRange succeeds
192 EXPECT_CALL(*gl_,
193 MapBufferRange(kTarget, kOffset, kSize, kMappedAccess))
194 .WillOnce(Return(&gpu_data[kOffset]))
195 .RetiresOnSaturation();
196
197 cmds::MapBufferRange cmd;
198 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
199 result_shm_id, result_shm_offset);
200 *result = 0;
201 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
202 EXPECT_EQ(1u, *result);
203 // Verify the buffer range from GPU is copied to client mem.
204 EXPECT_EQ(0, memcmp(&gpu_data[kOffset], client_data, kSize));
205 }
206
207 // Update the client mem.
208 const int8_t kValue0 = 21;
209 memset(client_data, kValue0, kSize);
210
211 { // UnmapBuffer succeeds
212 EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
213 .WillOnce(Return(GL_TRUE))
214 .RetiresOnSaturation();
215
216 cmds::UnmapBuffer cmd;
217 cmd.Init(kTarget);
218 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
219
220 // Verify the GPU mem and shadow data are both updated
221 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
222 if (ii < kOffset) {
223 EXPECT_EQ(static_cast<int8_t>(ii % 128), gpu_data[ii]);
224 EXPECT_EQ(static_cast<int8_t>(ii % 128), shadow_data[ii]);
225 } else {
226 EXPECT_EQ(kValue0, gpu_data[ii]);
227 EXPECT_EQ(kValue0, shadow_data[ii]);
228 }
229 }
230 }
231
232 EXPECT_EQ(GL_NO_ERROR, GetGLError());
233 }
234
235
TEST_P(GLES3DecoderTest,FlushMappedBufferRangeSucceeds)236 TEST_P(GLES3DecoderTest, FlushMappedBufferRangeSucceeds) {
237 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
238 const GLintptr kMappedOffset = 10;
239 const GLsizeiptr kMappedSize = 64;
240 const GLintptr kFlushRangeOffset = 5;
241 const GLsizeiptr kFlushRangeSize = 32;
242 const GLsizeiptr kTotalSize = kMappedOffset + kMappedSize;
243 const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
244 const GLbitfield kMappedAccess = kAccess | GL_MAP_READ_BIT;
245
246 uint32_t result_shm_id = shared_memory_id_;
247 uint32_t result_shm_offset = kSharedMemoryOffset;
248 uint32_t data_shm_id = shared_memory_id_;
249 // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
250 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
251
252 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
253 int8_t* client_data = GetSharedMemoryAs<int8_t*>() + sizeof(uint32_t);
254
255 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
256 Buffer* buffer = GetBuffer(client_buffer_id_);
257 EXPECT_TRUE(buffer != nullptr);
258 DoBufferData(kTarget, kTotalSize);
259 std::vector<int8_t> gpu_data(kTotalSize);
260 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
261 gpu_data[ii] = static_cast<int8_t>(ii % 128);
262 }
263 DoBufferSubData(kTarget, 0, kTotalSize, &gpu_data[0]);
264
265 EXPECT_EQ(GL_NO_ERROR, GetGLError());
266 EXPECT_TRUE(buffer->shadowed());
267 const int8_t* shadow_data = reinterpret_cast<const int8_t*>(
268 buffer->GetRange(0, kTotalSize));
269 EXPECT_TRUE(shadow_data);
270 // Verify the shadow data is initialized.
271 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
272 EXPECT_EQ(static_cast<int8_t>(ii % 128), shadow_data[ii]);
273 }
274
275 { // MapBufferRange succeeds
276 EXPECT_CALL(*gl_, MapBufferRange(kTarget, kMappedOffset, kMappedSize,
277 kMappedAccess))
278 .WillOnce(Return(&gpu_data[kMappedOffset]))
279 .RetiresOnSaturation();
280
281 cmds::MapBufferRange cmd;
282 cmd.Init(kTarget, kMappedOffset, kMappedSize, kAccess,
283 data_shm_id, data_shm_offset,
284 result_shm_id, result_shm_offset);
285 *result = 0;
286 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
287 EXPECT_EQ(1u, *result);
288 // Verify the buffer range from GPU is copied to client mem.
289 EXPECT_EQ(0, memcmp(&gpu_data[kMappedOffset], client_data, kMappedSize));
290 }
291
292 // Update the client mem, including data within and outside the flush range.
293 const int8_t kValue0 = 21;
294 memset(client_data, kValue0, kTotalSize);
295
296 { // FlushMappedBufferRange succeeds
297 EXPECT_CALL(*gl_, FlushMappedBufferRange(kTarget, kFlushRangeOffset,
298 kFlushRangeSize))
299 .Times(1)
300 .RetiresOnSaturation();
301
302 cmds::FlushMappedBufferRange cmd;
303 cmd.Init(kTarget, kFlushRangeOffset, kFlushRangeSize);
304 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
305
306 // Verify the GPU mem and shadow data are both updated, but only within
307 // the flushed range.
308 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
309 if (ii >= kMappedOffset + kFlushRangeOffset &&
310 ii < kMappedOffset + kFlushRangeOffset + kFlushRangeSize) {
311 EXPECT_EQ(kValue0, gpu_data[ii]);
312 EXPECT_EQ(kValue0, shadow_data[ii]);
313 } else {
314 EXPECT_EQ(static_cast<int8_t>(ii % 128), gpu_data[ii]);
315 EXPECT_EQ(static_cast<int8_t>(ii % 128), shadow_data[ii]);
316 }
317 }
318 }
319
320 { // UnmapBuffer succeeds
321 EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
322 .WillOnce(Return(GL_TRUE))
323 .RetiresOnSaturation();
324
325 cmds::UnmapBuffer cmd;
326 cmd.Init(kTarget);
327 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
328
329 // Verify no further update to the GPU mem and shadow data.
330 for (GLsizeiptr ii = 0; ii < kTotalSize; ++ii) {
331 if (ii >= kMappedOffset + kFlushRangeOffset &&
332 ii < kMappedOffset + kFlushRangeOffset + kFlushRangeSize) {
333 EXPECT_EQ(kValue0, gpu_data[ii]);
334 EXPECT_EQ(kValue0, shadow_data[ii]);
335 } else {
336 EXPECT_EQ(static_cast<int8_t>(ii % 128), gpu_data[ii]);
337 EXPECT_EQ(static_cast<int8_t>(ii % 128), shadow_data[ii]);
338 }
339 }
340 }
341
342 EXPECT_EQ(GL_NO_ERROR, GetGLError());
343 }
344
TEST_P(GLES3DecoderTest,MapBufferRangeNotInitFails)345 TEST_P(GLES3DecoderTest, MapBufferRangeNotInitFails) {
346 const GLenum kTarget = GL_ARRAY_BUFFER;
347 const GLintptr kOffset = 10;
348 const GLsizeiptr kSize = 64;
349 const GLbitfield kAccess = GL_MAP_READ_BIT;
350 std::vector<int8_t> data(kSize);
351
352 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
353 *result = 1; // Any value other than 0.
354 uint32_t result_shm_id = shared_memory_id_;
355 uint32_t result_shm_offset = kSharedMemoryOffset;
356 uint32_t data_shm_id = shared_memory_id_;
357 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
358
359 cmds::MapBufferRange cmd;
360 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
361 result_shm_id, result_shm_offset);
362 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
363 }
364
TEST_P(GLES3DecoderTest,MapBufferRangeWriteInvalidateRangeSucceeds)365 TEST_P(GLES3DecoderTest, MapBufferRangeWriteInvalidateRangeSucceeds) {
366 const GLenum kTarget = GL_ARRAY_BUFFER;
367 const GLintptr kOffset = 10;
368 const GLsizeiptr kSize = 64;
369 // With MAP_INVALIDATE_RANGE_BIT, no need to append MAP_READ_BIT.
370 const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
371
372 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
373 DoBufferData(kTarget, kSize + kOffset);
374
375 std::vector<int8_t> data(kSize);
376 for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
377 data[ii] = static_cast<int8_t>(ii % 255);
378 }
379 EXPECT_CALL(*gl_,
380 MapBufferRange(kTarget, kOffset, kSize, kAccess))
381 .WillOnce(Return(&data[0]))
382 .RetiresOnSaturation();
383
384 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
385 *result = 0;
386 uint32_t result_shm_id = shared_memory_id_;
387 uint32_t result_shm_offset = kSharedMemoryOffset;
388 uint32_t data_shm_id = shared_memory_id_;
389 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
390
391 int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
392 memset(mem, 72, kSize); // Init to a random value other than 0.
393
394 cmds::MapBufferRange cmd;
395 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
396 result_shm_id, result_shm_offset);
397 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
398 }
399
TEST_P(GLES3DecoderTest,MapBufferRangeWriteInvalidateBufferSucceeds)400 TEST_P(GLES3DecoderTest, MapBufferRangeWriteInvalidateBufferSucceeds) {
401 // Test INVALIDATE_BUFFER_BIT is mapped to INVALIDATE_RANGE_BIT.
402 const GLenum kTarget = GL_ARRAY_BUFFER;
403 const GLintptr kOffset = 10;
404 const GLsizeiptr kSize = 64;
405 const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT;
406 // With MAP_INVALIDATE_BUFFER_BIT, no need to append MAP_READ_BIT.
407 const GLbitfield kFilteredAccess =
408 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
409
410 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
411 DoBufferData(kTarget, kSize + kOffset);
412
413 std::vector<int8_t> data(kSize);
414 for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
415 data[ii] = static_cast<int8_t>(ii % 255);
416 }
417 EXPECT_CALL(*gl_,
418 MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
419 .WillOnce(Return(&data[0]))
420 .RetiresOnSaturation();
421
422 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
423 *result = 0;
424 uint32_t result_shm_id = shared_memory_id_;
425 uint32_t result_shm_offset = kSharedMemoryOffset;
426 uint32_t data_shm_id = shared_memory_id_;
427 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
428
429 int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
430 memset(mem, 72, kSize); // Init to a random value other than 0.
431
432 cmds::MapBufferRange cmd;
433 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
434 result_shm_id, result_shm_offset);
435 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
436 }
437
TEST_P(GLES3DecoderTest,MapBufferRangeWriteUnsynchronizedBit)438 TEST_P(GLES3DecoderTest, MapBufferRangeWriteUnsynchronizedBit) {
439 // Test UNSYNCHRONIZED_BIT is filtered out.
440 const GLenum kTarget = GL_ARRAY_BUFFER;
441 const GLintptr kOffset = 10;
442 const GLsizeiptr kSize = 64;
443 const GLbitfield kAccess = GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
444 const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
445
446 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
447 DoBufferData(kTarget, kSize + kOffset);
448
449 std::vector<int8_t> data(kSize);
450 for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
451 data[ii] = static_cast<int8_t>(ii % 255);
452 }
453 EXPECT_CALL(*gl_,
454 MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
455 .WillOnce(Return(&data[0]))
456 .RetiresOnSaturation();
457
458 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
459 *result = 0;
460 uint32_t result_shm_id = shared_memory_id_;
461 uint32_t result_shm_offset = kSharedMemoryOffset;
462 uint32_t data_shm_id = shared_memory_id_;
463 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
464
465 int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
466 memset(mem, 72, kSize); // Init to a random value other than 0.
467
468 cmds::MapBufferRange cmd;
469 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
470 result_shm_id, result_shm_offset);
471 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
472 EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
473 }
474
TEST_P(GLES3DecoderTest,MapBufferRangeWithError)475 TEST_P(GLES3DecoderTest, MapBufferRangeWithError) {
476 const GLenum kTarget = GL_ARRAY_BUFFER;
477 const GLintptr kOffset = 10;
478 const GLsizeiptr kSize = 64;
479 const GLbitfield kAccess = GL_MAP_READ_BIT;
480 std::vector<int8_t> data(kSize);
481 for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
482 data[ii] = static_cast<int8_t>(ii % 255);
483 }
484
485 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
486 *result = 0;
487 uint32_t result_shm_id = shared_memory_id_;
488 uint32_t result_shm_offset = kSharedMemoryOffset;
489 uint32_t data_shm_id = shared_memory_id_;
490 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
491
492 int8_t* mem = reinterpret_cast<int8_t*>(&result[1]);
493 memset(mem, 72, kSize); // Init to a random value other than 0.
494
495 cmds::MapBufferRange cmd;
496 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
497 result_shm_id, result_shm_offset);
498 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
499 memset(&data[0], 72, kSize);
500 // Mem is untouched.
501 EXPECT_EQ(0, memcmp(&data[0], mem, kSize));
502 EXPECT_EQ(0u, *result);
503 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
504 }
505
TEST_P(GLES3DecoderTest,MapBufferRangeBadSharedMemoryFails)506 TEST_P(GLES3DecoderTest, MapBufferRangeBadSharedMemoryFails) {
507 const GLenum kTarget = GL_ARRAY_BUFFER;
508 const GLintptr kOffset = 10;
509 const GLsizeiptr kSize = 64;
510 const GLbitfield kAccess = GL_MAP_READ_BIT;
511 std::vector<int8_t> data(kSize);
512 for (GLsizeiptr ii = 0; ii < kSize; ++ii) {
513 data[ii] = static_cast<int8_t>(ii % 255);
514 }
515
516 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
517 DoBufferData(kTarget, kOffset + kSize);
518
519 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
520 *result = 0;
521 uint32_t result_shm_id = shared_memory_id_;
522 uint32_t result_shm_offset = kSharedMemoryOffset;
523 uint32_t data_shm_id = shared_memory_id_;
524 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(*result);
525
526 cmds::MapBufferRange cmd;
527 cmd.Init(kTarget, kOffset, kSize, kAccess,
528 kInvalidSharedMemoryId, data_shm_offset,
529 result_shm_id, result_shm_offset);
530 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
531 cmd.Init(kTarget, kOffset, kSize, kAccess,
532 data_shm_id, data_shm_offset,
533 kInvalidSharedMemoryId, result_shm_offset);
534 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
535 cmd.Init(kTarget, kOffset, kSize, kAccess,
536 data_shm_id, kInvalidSharedMemoryOffset,
537 result_shm_id, result_shm_offset);
538 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
539 cmd.Init(kTarget, kOffset, kSize, kAccess,
540 data_shm_id, data_shm_offset,
541 result_shm_id, kInvalidSharedMemoryOffset);
542 EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
543 }
544
TEST_P(GLES3DecoderTest,UnmapBufferWriteNotMappedFails)545 TEST_P(GLES3DecoderTest, UnmapBufferWriteNotMappedFails) {
546 const GLenum kTarget = GL_ARRAY_BUFFER;
547
548 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
549
550 cmds::UnmapBuffer cmd;
551 cmd.Init(kTarget);
552 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
553 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
554 }
555
TEST_P(GLES3DecoderTest,UnmapBufferWriteNoBoundBufferFails)556 TEST_P(GLES3DecoderTest, UnmapBufferWriteNoBoundBufferFails) {
557 const GLenum kTarget = GL_ARRAY_BUFFER;
558
559 cmds::UnmapBuffer cmd;
560 cmd.Init(kTarget);
561 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
562 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
563 }
564
TEST_P(GLES3DecoderTest,BufferDataDestroysDataStore)565 TEST_P(GLES3DecoderTest, BufferDataDestroysDataStore) {
566 const GLenum kTarget = GL_ARRAY_BUFFER;
567 const GLintptr kOffset = 10;
568 const GLsizeiptr kSize = 64;
569 const GLbitfield kAccess = GL_MAP_WRITE_BIT;
570 const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
571
572 uint32_t result_shm_id = shared_memory_id_;
573 uint32_t result_shm_offset = kSharedMemoryOffset;
574 uint32_t data_shm_id = shared_memory_id_;
575 // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
576 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
577
578 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
579 DoBufferData(kTarget, kSize + kOffset);
580
581 std::vector<int8_t> data(kSize);
582
583 { // MapBufferRange succeeds
584 EXPECT_CALL(*gl_,
585 MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
586 .WillOnce(Return(&data[0]))
587 .RetiresOnSaturation();
588
589 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
590
591 cmds::MapBufferRange cmd;
592 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
593 result_shm_id, result_shm_offset);
594 *result = 0;
595 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
596 EXPECT_EQ(1u, *result);
597 }
598
599 { // BufferData unmaps the data store.
600 DoBufferData(kTarget, kSize * 2);
601 EXPECT_EQ(GL_NO_ERROR, GetGLError());
602 }
603
604 { // UnmapBuffer fails.
605 cmds::UnmapBuffer cmd;
606 cmd.Init(kTarget);
607 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
608 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
609 }
610 }
611
TEST_P(GLES3DecoderTest,DeleteBuffersDestroysDataStore)612 TEST_P(GLES3DecoderTest, DeleteBuffersDestroysDataStore) {
613 const GLenum kTarget = GL_ARRAY_BUFFER;
614 const GLintptr kOffset = 10;
615 const GLsizeiptr kSize = 64;
616 const GLbitfield kAccess = GL_MAP_WRITE_BIT;
617 const GLbitfield kFilteredAccess = GL_MAP_WRITE_BIT | GL_MAP_READ_BIT;
618
619 uint32_t result_shm_id = shared_memory_id_;
620 uint32_t result_shm_offset = kSharedMemoryOffset;
621 uint32_t data_shm_id = shared_memory_id_;
622 // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
623 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
624
625 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
626 DoBufferData(kTarget, kSize + kOffset);
627
628 std::vector<int8_t> data(kSize);
629
630 { // MapBufferRange succeeds
631 EXPECT_CALL(*gl_,
632 MapBufferRange(kTarget, kOffset, kSize, kFilteredAccess))
633 .WillOnce(Return(&data[0]))
634 .RetiresOnSaturation();
635
636 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
637
638 cmds::MapBufferRange cmd;
639 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
640 result_shm_id, result_shm_offset);
641 *result = 0;
642 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
643 EXPECT_EQ(1u, *result);
644 }
645
646 { // DeleteBuffers unmaps the data store.
647 EXPECT_CALL(*gl_, BindBuffer(kTarget, 0)).Times(1).RetiresOnSaturation();
648 EXPECT_CALL(*gl_, UnmapBuffer(kTarget))
649 .WillOnce(Return(GL_TRUE))
650 .RetiresOnSaturation();
651 DoDeleteBuffer(client_buffer_id_, kServiceBufferId);
652 EXPECT_EQ(GL_NO_ERROR, GetGLError());
653 }
654
655 { // UnmapBuffer fails.
656 cmds::UnmapBuffer cmd;
657 cmd.Init(kTarget);
658 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
659 EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
660 }
661 }
662
TEST_P(GLES3DecoderTest,MapUnmapBufferInvalidTarget)663 TEST_P(GLES3DecoderTest, MapUnmapBufferInvalidTarget) {
664 const GLenum kTarget = GL_TEXTURE_2D;
665 const GLintptr kOffset = 10;
666 const GLsizeiptr kSize = 64;
667 const GLbitfield kAccess = GL_MAP_WRITE_BIT;
668
669 uint32_t result_shm_id = shared_memory_id_;
670 uint32_t result_shm_offset = kSharedMemoryOffset;
671 uint32_t data_shm_id = shared_memory_id_;
672 // uint32_t is Result for both MapBufferRange and UnmapBuffer commands.
673 uint32_t data_shm_offset = kSharedMemoryOffset + sizeof(uint32_t);
674
675 auto* result = GetSharedMemoryAs<cmds::MapBufferRange::Result*>();
676
677 {
678 cmds::MapBufferRange cmd;
679 cmd.Init(kTarget, kOffset, kSize, kAccess, data_shm_id, data_shm_offset,
680 result_shm_id, result_shm_offset);
681 *result = 0;
682 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
683 EXPECT_EQ(0u, *result);
684 EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
685 }
686
687 {
688 cmds::UnmapBuffer cmd;
689 cmd.Init(kTarget);
690 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
691 EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
692 }
693 }
694
TEST_P(GLES3DecoderTest,CopyBufferSubDataValidArgs)695 TEST_P(GLES3DecoderTest, CopyBufferSubDataValidArgs) {
696 const GLenum kTarget = GL_ELEMENT_ARRAY_BUFFER;
697 const GLsizeiptr kSize = 64;
698 const GLsizeiptr kHalfSize = kSize / 2;
699 const GLintptr kReadOffset = 0;
700 const GLintptr kWriteOffset = kHalfSize;
701 const GLsizeiptr kCopySize = 5;
702 const char kValue0 = 3;
703 const char kValue1 = 21;
704
705 // Set up the buffer so first half is kValue0 and second half is kValue1.
706 DoBindBuffer(kTarget, client_buffer_id_, kServiceBufferId);
707 DoBufferData(kTarget, kSize);
708 std::unique_ptr<char[]> data(new char[kHalfSize]);
709 memset(data.get(), kValue0, kHalfSize);
710 DoBufferSubData(kTarget, 0, kHalfSize, data.get());
711 memset(data.get(), kValue1, kHalfSize);
712 DoBufferSubData(kTarget, kHalfSize, kHalfSize, data.get());
713 EXPECT_EQ(GL_NO_ERROR, GetGLError());
714 Buffer* buffer = GetBuffer(client_buffer_id_);
715 EXPECT_TRUE(buffer);
716 const char* shadow_data = reinterpret_cast<const char*>(
717 buffer->GetRange(0, kSize));
718 EXPECT_TRUE(shadow_data);
719 // Verify the shadow data is initialized.
720 for (GLsizeiptr ii = 0; ii < kHalfSize; ++ii) {
721 EXPECT_EQ(kValue0, shadow_data[ii]);
722 }
723 for (GLsizeiptr ii = kHalfSize; ii < kSize; ++ii) {
724 EXPECT_EQ(kValue1, shadow_data[ii]);
725 }
726
727 EXPECT_CALL(*gl_, CopyBufferSubData(kTarget, kTarget,
728 kReadOffset, kWriteOffset, kCopySize));
729 cmds::CopyBufferSubData cmd;
730 cmd.Init(kTarget, kTarget, kReadOffset, kWriteOffset, kCopySize);
731 EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
732 EXPECT_EQ(GL_NO_ERROR, GetGLError());
733 // Verify the shadow data is updated.
734 for (GLsizeiptr ii = 0; ii < kHalfSize; ++ii) {
735 EXPECT_EQ(kValue0, shadow_data[ii]);
736 }
737 for (GLsizeiptr ii = kHalfSize; ii < kSize; ++ii) {
738 if (ii >= kWriteOffset && ii < kWriteOffset + kCopySize) {
739 EXPECT_EQ(kValue0, shadow_data[ii]);
740 } else {
741 EXPECT_EQ(kValue1, shadow_data[ii]);
742 }
743 }
744 }
745
746 } // namespace gles2
747 } // namespace gpu
748