1// Copyright 2014 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 "gpu/command_buffer/service/gles2_cmd_decoder.h"
6
7#include "base/command_line.h"
8#include "base/strings/string_number_conversions.h"
9#include "gpu/command_buffer/common/gles2_cmd_format.h"
10#include "gpu/command_buffer/common/gles2_cmd_utils.h"
11#include "gpu/command_buffer/common/id_allocator.h"
12#include "gpu/command_buffer/service/async_pixel_transfer_delegate_mock.h"
13#include "gpu/command_buffer/service/async_pixel_transfer_manager.h"
14#include "gpu/command_buffer/service/async_pixel_transfer_manager_mock.h"
15#include "gpu/command_buffer/service/cmd_buffer_engine.h"
16#include "gpu/command_buffer/service/context_group.h"
17#include "gpu/command_buffer/service/context_state.h"
18#include "gpu/command_buffer/service/gl_surface_mock.h"
19#include "gpu/command_buffer/service/gles2_cmd_decoder_unittest.h"
20
21#include "gpu/command_buffer/service/gpu_switches.h"
22#include "gpu/command_buffer/service/image_manager.h"
23#include "gpu/command_buffer/service/mailbox_manager.h"
24#include "gpu/command_buffer/service/mocks.h"
25#include "gpu/command_buffer/service/program_manager.h"
26#include "gpu/command_buffer/service/test_helper.h"
27#include "testing/gtest/include/gtest/gtest.h"
28#include "ui/gl/gl_implementation.h"
29#include "ui/gl/gl_mock.h"
30#include "ui/gl/gl_surface_stub.h"
31
32#if !defined(GL_DEPTH24_STENCIL8)
33#define GL_DEPTH24_STENCIL8 0x88F0
34#endif
35
36using ::gfx::MockGLInterface;
37using ::testing::_;
38using ::testing::DoAll;
39using ::testing::InSequence;
40using ::testing::Invoke;
41using ::testing::MatcherCast;
42using ::testing::Mock;
43using ::testing::Pointee;
44using ::testing::Return;
45using ::testing::SaveArg;
46using ::testing::SetArrayArgument;
47using ::testing::SetArgumentPointee;
48using ::testing::SetArgPointee;
49using ::testing::StrEq;
50using ::testing::StrictMock;
51
52namespace gpu {
53namespace gles2 {
54
55using namespace cmds;
56
57TEST_P(GLES2DecoderWithShaderTest, GetVertexAttribPointervSucceeds) {
58  const float dummy = 0;
59  const GLuint kOffsetToTestFor = sizeof(dummy) * 4;
60  const GLuint kIndexToTest = 1;
61  GetVertexAttribPointerv::Result* result =
62      static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_);
63  result->size = 0;
64  const GLuint* result_value = result->GetData();
65  // Test that initial value is 0.
66  GetVertexAttribPointerv cmd;
67  cmd.Init(kIndexToTest,
68           GL_VERTEX_ATTRIB_ARRAY_POINTER,
69           shared_memory_id_,
70           shared_memory_offset_);
71  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
72  EXPECT_EQ(sizeof(*result_value), result->size);
73  EXPECT_EQ(0u, *result_value);
74  EXPECT_EQ(GL_NO_ERROR, GetGLError());
75
76  // Set the value and see that we get it.
77  SetupVertexBuffer();
78  DoVertexAttribPointer(kIndexToTest, 2, GL_FLOAT, 0, kOffsetToTestFor);
79  result->size = 0;
80  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
81  EXPECT_EQ(sizeof(*result_value), result->size);
82  EXPECT_EQ(kOffsetToTestFor, *result_value);
83  EXPECT_EQ(GL_NO_ERROR, GetGLError());
84}
85
86TEST_P(GLES2DecoderWithShaderTest, GetVertexAttribPointervBadArgsFails) {
87  const GLuint kIndexToTest = 1;
88  GetVertexAttribPointerv::Result* result =
89      static_cast<GetVertexAttribPointerv::Result*>(shared_memory_address_);
90  result->size = 0;
91  const GLuint* result_value = result->GetData();
92  // Test pname invalid fails.
93  GetVertexAttribPointerv cmd;
94  cmd.Init(kIndexToTest,
95           GL_VERTEX_ATTRIB_ARRAY_POINTER + 1,
96           shared_memory_id_,
97           shared_memory_offset_);
98  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
99  EXPECT_EQ(0u, result->size);
100  EXPECT_EQ(kInitialResult, *result_value);
101  EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
102
103  // Test index out of range fails.
104  result->size = 0;
105  cmd.Init(kNumVertexAttribs,
106           GL_VERTEX_ATTRIB_ARRAY_POINTER,
107           shared_memory_id_,
108           shared_memory_offset_);
109  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
110  EXPECT_EQ(0u, result->size);
111  EXPECT_EQ(kInitialResult, *result_value);
112  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
113
114  // Test memory id bad fails.
115  cmd.Init(kIndexToTest,
116           GL_VERTEX_ATTRIB_ARRAY_POINTER,
117           kInvalidSharedMemoryId,
118           shared_memory_offset_);
119  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
120
121  // Test memory offset bad fails.
122  cmd.Init(kIndexToTest,
123           GL_VERTEX_ATTRIB_ARRAY_POINTER,
124           shared_memory_id_,
125           kInvalidSharedMemoryOffset);
126  EXPECT_NE(error::kNoError, ExecuteCmd(cmd));
127}
128
129TEST_P(GLES2DecoderWithShaderTest, BindBufferToDifferentTargetFails) {
130  // Bind the buffer to GL_ARRAY_BUFFER
131  DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId);
132  // Attempt to rebind to GL_ELEMENT_ARRAY_BUFFER
133  // NOTE: Real GLES2 does not have this restriction but WebGL and we do.
134  // This can be restriction can be removed at runtime.
135  EXPECT_CALL(*gl_, BindBuffer(_, _)).Times(0);
136  BindBuffer cmd;
137  cmd.Init(GL_ELEMENT_ARRAY_BUFFER, client_buffer_id_);
138  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
139  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
140}
141
142TEST_P(GLES2DecoderWithShaderTest, VertexAttribPointer) {
143  SetupVertexBuffer();
144  static const GLenum types[] = {
145      GL_BYTE,  GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT,
146      GL_FLOAT, GL_FIXED,         GL_INT,   GL_UNSIGNED_INT,
147  };
148  static const GLsizei sizes[] = {
149      1, 1, 2, 2, 4, 4, 4, 4,
150  };
151  static const GLuint indices[] = {
152      0, 1, kNumVertexAttribs - 1, kNumVertexAttribs,
153  };
154  static const GLsizei offset_mult[] = {
155      0, 0, 1, 1, 2, 1000,
156  };
157  static const GLsizei offset_offset[] = {
158      0, 1, 0, 1, 0, 0,
159  };
160  static const GLsizei stride_mult[] = {
161      -1, 0, 0, 1, 1, 2, 1000,
162  };
163  static const GLsizei stride_offset[] = {
164      0, 0, 1, 0, 1, 0, 0,
165  };
166  for (size_t tt = 0; tt < arraysize(types); ++tt) {
167    GLenum type = types[tt];
168    GLsizei num_bytes = sizes[tt];
169    for (size_t ii = 0; ii < arraysize(indices); ++ii) {
170      GLuint index = indices[ii];
171      for (GLint size = 0; size < 5; ++size) {
172        for (size_t oo = 0; oo < arraysize(offset_mult); ++oo) {
173          GLuint offset = num_bytes * offset_mult[oo] + offset_offset[oo];
174          for (size_t ss = 0; ss < arraysize(stride_mult); ++ss) {
175            GLsizei stride = num_bytes * stride_mult[ss] + stride_offset[ss];
176            for (int normalize = 0; normalize < 2; ++normalize) {
177              bool index_good = index < static_cast<GLuint>(kNumVertexAttribs);
178              bool size_good = (size > 0 && size < 5);
179              bool offset_good = (offset % num_bytes == 0);
180              bool stride_good =
181                  (stride % num_bytes == 0) && stride >= 0 && stride <= 255;
182              bool type_good = (type != GL_INT && type != GL_UNSIGNED_INT &&
183                                type != GL_FIXED);
184              bool good = size_good && offset_good && stride_good &&
185                          type_good && index_good;
186              bool call = good && (type != GL_FIXED);
187              if (call) {
188                EXPECT_CALL(*gl_,
189                            VertexAttribPointer(index,
190                                                size,
191                                                type,
192                                                normalize,
193                                                stride,
194                                                BufferOffset(offset)));
195              }
196              VertexAttribPointer cmd;
197              cmd.Init(index, size, type, normalize, stride, offset);
198              EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
199              if (good) {
200                EXPECT_EQ(GL_NO_ERROR, GetGLError());
201              } else if (size_good && offset_good && stride_good && type_good &&
202                         !index_good) {
203                EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
204              } else if (size_good && offset_good && stride_good &&
205                         !type_good && index_good) {
206                EXPECT_EQ(GL_INVALID_ENUM, GetGLError());
207              } else if (size_good && offset_good && !stride_good &&
208                         type_good && index_good) {
209                if (stride < 0 || stride > 255) {
210                  EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
211                } else {
212                  EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
213                }
214              } else if (size_good && !offset_good && stride_good &&
215                         type_good && index_good) {
216                EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
217              } else if (!size_good && offset_good && stride_good &&
218                         type_good && index_good) {
219                EXPECT_EQ(GL_INVALID_VALUE, GetGLError());
220              } else {
221                EXPECT_NE(GL_NO_ERROR, GetGLError());
222              }
223            }
224          }
225        }
226      }
227    }
228  }
229}
230
231class GLES2DecoderVertexArraysOESTest : public GLES2DecoderWithShaderTest {
232 public:
233  GLES2DecoderVertexArraysOESTest() {}
234
235  bool vertex_array_deleted_manually_;
236
237  virtual void SetUp() {
238    InitState init;
239    init.gl_version = "opengl es 2.0";
240    init.bind_generates_resource = true;
241    InitDecoder(init);
242    SetupDefaultProgram();
243
244    AddExpectationsForGenVertexArraysOES();
245    GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_);
246
247    vertex_array_deleted_manually_ = false;
248  }
249
250  virtual void TearDown() {
251    // This should only be set if the test handled deletion of the vertex array
252    // itself. Necessary because vertex_array_objects are not sharable, and thus
253    // not managed in the ContextGroup, meaning they will be destroyed during
254    // test tear down
255    if (!vertex_array_deleted_manually_) {
256      AddExpectationsForDeleteVertexArraysOES();
257    }
258
259    GLES2DecoderWithShaderTest::TearDown();
260  }
261
262  void GenVertexArraysOESImmediateValidArgs() {
263    AddExpectationsForGenVertexArraysOES();
264    GenVertexArraysOESImmediate* cmd =
265        GetImmediateAs<GenVertexArraysOESImmediate>();
266    GLuint temp = kNewClientId;
267    cmd->Init(1, &temp);
268    EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(*cmd, sizeof(temp)));
269    EXPECT_EQ(GL_NO_ERROR, GetGLError());
270    EXPECT_TRUE(GetVertexArrayInfo(kNewClientId) != NULL);
271    AddExpectationsForDeleteVertexArraysOES();
272  }
273
274  void GenVertexArraysOESImmediateInvalidArgs() {
275    EXPECT_CALL(*gl_, GenVertexArraysOES(_, _)).Times(0);
276    GenVertexArraysOESImmediate* cmd =
277        GetImmediateAs<GenVertexArraysOESImmediate>();
278    cmd->Init(1, &client_vertexarray_id_);
279    EXPECT_EQ(error::kInvalidArguments,
280              ExecuteImmediateCmd(*cmd, sizeof(&client_vertexarray_id_)));
281  }
282
283  void DeleteVertexArraysOESImmediateValidArgs() {
284    AddExpectationsForDeleteVertexArraysOES();
285    DeleteVertexArraysOESImmediate& cmd =
286        *GetImmediateAs<DeleteVertexArraysOESImmediate>();
287    cmd.Init(1, &client_vertexarray_id_);
288    EXPECT_EQ(error::kNoError,
289              ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_)));
290    EXPECT_EQ(GL_NO_ERROR, GetGLError());
291    EXPECT_TRUE(GetVertexArrayInfo(client_vertexarray_id_) == NULL);
292    vertex_array_deleted_manually_ = true;
293  }
294
295  void DeleteVertexArraysOESImmediateInvalidArgs() {
296    DeleteVertexArraysOESImmediate& cmd =
297        *GetImmediateAs<DeleteVertexArraysOESImmediate>();
298    GLuint temp = kInvalidClientId;
299    cmd.Init(1, &temp);
300    EXPECT_EQ(error::kNoError, ExecuteImmediateCmd(cmd, sizeof(temp)));
301  }
302
303  void DeleteBoundVertexArraysOESImmediateValidArgs() {
304    BindVertexArrayOESValidArgs();
305
306    AddExpectationsForDeleteBoundVertexArraysOES();
307    DeleteVertexArraysOESImmediate& cmd =
308        *GetImmediateAs<DeleteVertexArraysOESImmediate>();
309    cmd.Init(1, &client_vertexarray_id_);
310    EXPECT_EQ(error::kNoError,
311              ExecuteImmediateCmd(cmd, sizeof(client_vertexarray_id_)));
312    EXPECT_EQ(GL_NO_ERROR, GetGLError());
313    EXPECT_TRUE(GetVertexArrayInfo(client_vertexarray_id_) == NULL);
314    vertex_array_deleted_manually_ = true;
315  }
316
317  void IsVertexArrayOESValidArgs() {
318    IsVertexArrayOES cmd;
319    cmd.Init(client_vertexarray_id_, shared_memory_id_, shared_memory_offset_);
320    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
321    EXPECT_EQ(GL_NO_ERROR, GetGLError());
322  }
323
324  void IsVertexArrayOESInvalidArgsBadSharedMemoryId() {
325    IsVertexArrayOES cmd;
326    cmd.Init(
327        client_vertexarray_id_, kInvalidSharedMemoryId, shared_memory_offset_);
328    EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
329    cmd.Init(
330        client_vertexarray_id_, shared_memory_id_, kInvalidSharedMemoryOffset);
331    EXPECT_EQ(error::kOutOfBounds, ExecuteCmd(cmd));
332  }
333
334  void BindVertexArrayOESValidArgs() {
335    AddExpectationsForBindVertexArrayOES();
336    BindVertexArrayOES cmd;
337    cmd.Init(client_vertexarray_id_);
338    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
339    EXPECT_EQ(GL_NO_ERROR, GetGLError());
340  }
341
342  void BindVertexArrayOESValidArgsNewId() {
343    BindVertexArrayOES cmd;
344    cmd.Init(kNewClientId);
345    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
346    EXPECT_EQ(GL_INVALID_OPERATION, GetGLError());
347  }
348};
349
350INSTANTIATE_TEST_CASE_P(Service,
351                        GLES2DecoderVertexArraysOESTest,
352                        ::testing::Bool());
353
354class GLES2DecoderEmulatedVertexArraysOESTest
355    : public GLES2DecoderVertexArraysOESTest {
356 public:
357  GLES2DecoderEmulatedVertexArraysOESTest() {}
358
359  virtual void SetUp() {
360    InitState init;
361    init.gl_version = "3.0";
362    init.bind_generates_resource = true;
363    init.use_native_vao = false;
364    InitDecoder(init);
365    SetupDefaultProgram();
366
367    AddExpectationsForGenVertexArraysOES();
368    GenHelper<GenVertexArraysOESImmediate>(client_vertexarray_id_);
369
370    vertex_array_deleted_manually_ = false;
371  }
372};
373
374INSTANTIATE_TEST_CASE_P(Service,
375                        GLES2DecoderEmulatedVertexArraysOESTest,
376                        ::testing::Bool());
377
378// Test vertex array objects with native support
379TEST_P(GLES2DecoderVertexArraysOESTest, GenVertexArraysOESImmediateValidArgs) {
380  GenVertexArraysOESImmediateValidArgs();
381}
382TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
383       GenVertexArraysOESImmediateValidArgs) {
384  GenVertexArraysOESImmediateValidArgs();
385}
386
387TEST_P(GLES2DecoderVertexArraysOESTest,
388       GenVertexArraysOESImmediateInvalidArgs) {
389  GenVertexArraysOESImmediateInvalidArgs();
390}
391TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
392       GenVertexArraysOESImmediateInvalidArgs) {
393  GenVertexArraysOESImmediateInvalidArgs();
394}
395
396TEST_P(GLES2DecoderVertexArraysOESTest,
397       DeleteVertexArraysOESImmediateValidArgs) {
398  DeleteVertexArraysOESImmediateValidArgs();
399}
400TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
401       DeleteVertexArraysOESImmediateValidArgs) {
402  DeleteVertexArraysOESImmediateValidArgs();
403}
404
405TEST_P(GLES2DecoderVertexArraysOESTest,
406       DeleteVertexArraysOESImmediateInvalidArgs) {
407  DeleteVertexArraysOESImmediateInvalidArgs();
408}
409TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
410       DeleteVertexArraysOESImmediateInvalidArgs) {
411  DeleteVertexArraysOESImmediateInvalidArgs();
412}
413
414TEST_P(GLES2DecoderVertexArraysOESTest,
415       DeleteBoundVertexArraysOESImmediateValidArgs) {
416  DeleteBoundVertexArraysOESImmediateValidArgs();
417}
418TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
419       DeleteBoundVertexArraysOESImmediateValidArgs) {
420  DeleteBoundVertexArraysOESImmediateValidArgs();
421}
422
423TEST_P(GLES2DecoderVertexArraysOESTest, IsVertexArrayOESValidArgs) {
424  IsVertexArrayOESValidArgs();
425}
426TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, IsVertexArrayOESValidArgs) {
427  IsVertexArrayOESValidArgs();
428}
429
430TEST_P(GLES2DecoderVertexArraysOESTest,
431       IsVertexArrayOESInvalidArgsBadSharedMemoryId) {
432  IsVertexArrayOESInvalidArgsBadSharedMemoryId();
433}
434TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
435       IsVertexArrayOESInvalidArgsBadSharedMemoryId) {
436  IsVertexArrayOESInvalidArgsBadSharedMemoryId();
437}
438
439TEST_P(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgs) {
440  BindVertexArrayOESValidArgs();
441}
442TEST_P(GLES2DecoderEmulatedVertexArraysOESTest, BindVertexArrayOESValidArgs) {
443  BindVertexArrayOESValidArgs();
444}
445
446TEST_P(GLES2DecoderVertexArraysOESTest, BindVertexArrayOESValidArgsNewId) {
447  BindVertexArrayOESValidArgsNewId();
448}
449TEST_P(GLES2DecoderEmulatedVertexArraysOESTest,
450       BindVertexArrayOESValidArgsNewId) {
451  BindVertexArrayOESValidArgsNewId();
452}
453
454TEST_P(GLES2DecoderTest, BufferDataGLError) {
455  GLenum target = GL_ARRAY_BUFFER;
456  GLsizeiptr size = 4;
457  DoBindBuffer(GL_ARRAY_BUFFER, client_buffer_id_, kServiceBufferId);
458  BufferManager* manager = group().buffer_manager();
459  Buffer* buffer = manager->GetBuffer(client_buffer_id_);
460  ASSERT_TRUE(buffer != NULL);
461  EXPECT_EQ(0, buffer->size());
462  EXPECT_CALL(*gl_, GetError())
463      .WillOnce(Return(GL_NO_ERROR))
464      .WillOnce(Return(GL_OUT_OF_MEMORY))
465      .RetiresOnSaturation();
466  EXPECT_CALL(*gl_, BufferData(target, size, _, GL_STREAM_DRAW))
467      .Times(1)
468      .RetiresOnSaturation();
469  BufferData cmd;
470  cmd.Init(target, size, 0, 0, GL_STREAM_DRAW);
471  EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
472  EXPECT_EQ(GL_OUT_OF_MEMORY, GetGLError());
473  EXPECT_EQ(0, buffer->size());
474}
475
476// TODO(gman): BufferData
477
478// TODO(gman): BufferDataImmediate
479
480// TODO(gman): BufferSubData
481
482// TODO(gman): BufferSubDataImmediate
483
484}  // namespace gles2
485}  // namespace gpu
486