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#ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_BASE_H_
6#define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_BASE_H_
7
8#include "gpu/command_buffer/common/gles2_cmd_format.h"
9#include "gpu/command_buffer/common/gles2_cmd_utils.h"
10#include "gpu/command_buffer/service/buffer_manager.h"
11#include "gpu/command_buffer/service/cmd_buffer_engine.h"
12#include "gpu/command_buffer/service/context_group.h"
13#include "gpu/command_buffer/service/framebuffer_manager.h"
14#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
15#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
16#include "gpu/command_buffer/service/program_manager.h"
17#include "gpu/command_buffer/service/query_manager.h"
18#include "gpu/command_buffer/service/renderbuffer_manager.h"
19#include "gpu/command_buffer/service/shader_manager.h"
20#include "gpu/command_buffer/service/test_helper.h"
21#include "gpu/command_buffer/service/texture_manager.h"
22#include "gpu/command_buffer/service/vertex_array_manager.h"
23#include "testing/gtest/include/gtest/gtest.h"
24#include "ui/gl/gl_context_stub_with_extensions.h"
25#include "ui/gl/gl_surface_stub.h"
26#include "ui/gl/gl_mock.h"
27
28namespace base {
29class CommandLine;
30}
31
32namespace gpu {
33namespace gles2 {
34
35class MemoryTracker;
36
37class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> {
38 public:
39  GLES2DecoderTestBase();
40  virtual ~GLES2DecoderTestBase();
41
42  // Template to call glGenXXX functions.
43  template <typename T>
44  void GenHelper(GLuint client_id) {
45    int8 buffer[sizeof(T) + sizeof(client_id)];
46    T& cmd = *reinterpret_cast<T*>(&buffer);
47    cmd.Init(1, &client_id);
48    EXPECT_EQ(error::kNoError,
49              ExecuteImmediateCmd(cmd, sizeof(client_id)));
50  }
51
52  // This template exists solely so we can specialize it for
53  // certain commands.
54  template <typename T, int id>
55  void SpecializedSetup(bool valid) {
56  }
57
58  template <typename T>
59  T* GetImmediateAs() {
60    return reinterpret_cast<T*>(immediate_buffer_);
61  }
62
63  template <typename T, typename Command>
64  T GetImmediateDataAs(Command* cmd) {
65    return reinterpret_cast<T>(ImmediateDataAddress(cmd));
66  }
67
68  void ClearSharedMemory() {
69    engine_->ClearSharedMemory();
70  }
71
72  virtual void SetUp() OVERRIDE;
73  virtual void TearDown() OVERRIDE;
74
75  template <typename T>
76  error::Error ExecuteCmd(const T& cmd) {
77    COMPILE_ASSERT(T::kArgFlags == cmd::kFixed, Cmd_kArgFlags_not_kFixed);
78    return decoder_->DoCommands(
79        1, (const void*)&cmd, ComputeNumEntries(sizeof(cmd)), 0);
80  }
81
82  template <typename T>
83  error::Error ExecuteImmediateCmd(const T& cmd, size_t data_size) {
84    COMPILE_ASSERT(T::kArgFlags == cmd::kAtLeastN, Cmd_kArgFlags_not_kAtLeastN);
85    return decoder_->DoCommands(
86        1, (const void*)&cmd, ComputeNumEntries(sizeof(cmd) + data_size), 0);
87  }
88
89  template <typename T>
90  T GetSharedMemoryAs() {
91    return reinterpret_cast<T>(shared_memory_address_);
92  }
93
94  template <typename T>
95  T GetSharedMemoryAsWithOffset(uint32 offset) {
96    void* ptr = reinterpret_cast<int8*>(shared_memory_address_) + offset;
97    return reinterpret_cast<T>(ptr);
98  }
99
100  IdAllocatorInterface* GetIdAllocator(GLuint namespace_id) {
101    return group_->GetIdAllocator(namespace_id);
102  }
103
104  Buffer* GetBuffer(GLuint service_id) {
105    return group_->buffer_manager()->GetBuffer(service_id);
106  }
107
108  Framebuffer* GetFramebuffer(GLuint service_id) {
109    return group_->framebuffer_manager()->GetFramebuffer(service_id);
110  }
111
112  Renderbuffer* GetRenderbuffer(
113      GLuint service_id) {
114    return group_->renderbuffer_manager()->GetRenderbuffer(service_id);
115  }
116
117  TextureRef* GetTexture(GLuint client_id) {
118    return group_->texture_manager()->GetTexture(client_id);
119  }
120
121  Shader* GetShader(GLuint client_id) {
122    return group_->shader_manager()->GetShader(client_id);
123  }
124
125  Program* GetProgram(GLuint client_id) {
126    return group_->program_manager()->GetProgram(client_id);
127  }
128
129  QueryManager::Query* GetQueryInfo(GLuint client_id) {
130    return decoder_->GetQueryManager()->GetQuery(client_id);
131  }
132
133  // This name doesn't match the underlying function, but doing it this way
134  // prevents the need to special-case the unit test generation
135  VertexAttribManager* GetVertexArrayInfo(GLuint client_id) {
136    return decoder_->GetVertexArrayManager()->GetVertexAttribManager(client_id);
137  }
138
139  ProgramManager* program_manager() {
140    return group_->program_manager();
141  }
142
143  ImageManager* GetImageManager() { return decoder_->GetImageManager(); }
144
145  void DoCreateProgram(GLuint client_id, GLuint service_id);
146  void DoCreateShader(GLenum shader_type, GLuint client_id, GLuint service_id);
147
148  void SetBucketAsCString(uint32 bucket_id, const char* str);
149
150  void set_memory_tracker(MemoryTracker* memory_tracker) {
151    memory_tracker_ = memory_tracker;
152  }
153
154  struct InitState {
155    InitState();
156
157    std::string extensions;
158    std::string gl_version;
159    bool has_alpha;
160    bool has_depth;
161    bool has_stencil;
162    bool request_alpha;
163    bool request_depth;
164    bool request_stencil;
165    bool bind_generates_resource;
166    bool lose_context_when_out_of_memory;
167    bool use_native_vao;  // default is true.
168  };
169
170  void InitDecoder(const InitState& init);
171  void InitDecoderWithCommandLine(const InitState& init,
172                                  const base::CommandLine* command_line);
173
174  void ResetDecoder();
175
176  const ContextGroup& group() const {
177    return *group_.get();
178  }
179
180  ::testing::StrictMock< ::gfx::MockGLInterface>* GetGLMock() const {
181    return gl_.get();
182  }
183
184  GLES2Decoder* GetDecoder() const {
185    return decoder_.get();
186  }
187
188  typedef TestHelper::AttribInfo AttribInfo;
189  typedef TestHelper::UniformInfo UniformInfo;
190
191  void SetupShader(
192      AttribInfo* attribs, size_t num_attribs,
193      UniformInfo* uniforms, size_t num_uniforms,
194      GLuint client_id, GLuint service_id,
195      GLuint vertex_shader_client_id, GLuint vertex_shader_service_id,
196      GLuint fragment_shader_client_id, GLuint fragment_shader_service_id);
197
198  void SetupInitCapabilitiesExpectations();
199  void SetupInitStateExpectations();
200  void ExpectEnableDisable(GLenum cap, bool enable);
201
202  // Setups up a shader for testing glUniform.
203  void SetupShaderForUniform(GLenum uniform_type);
204  void SetupDefaultProgram();
205  void SetupCubemapProgram();
206  void SetupSamplerExternalProgram();
207  void SetupTexture();
208
209  // Note that the error is returned as GLint instead of GLenum.
210  // This is because there is a mismatch in the types of GLenum and
211  // the error values GL_NO_ERROR, GL_INVALID_ENUM, etc. GLenum is
212  // typedef'd as unsigned int while the error values are defined as
213  // integers. This is problematic for template functions such as
214  // EXPECT_EQ that expect both types to be the same.
215  GLint GetGLError();
216
217  void DoBindBuffer(GLenum target, GLuint client_id, GLuint service_id);
218  void DoBindFramebuffer(GLenum target, GLuint client_id, GLuint service_id);
219  void DoBindRenderbuffer(GLenum target, GLuint client_id, GLuint service_id);
220  void DoRenderbufferStorageMultisampleCHROMIUM(GLenum target,
221                                                GLsizei samples,
222                                                GLenum internal_format,
223                                                GLenum gl_format,
224                                                GLsizei width,
225                                                GLsizei height);
226  void RestoreRenderbufferBindings();
227  void EnsureRenderbufferBound(bool expect_bind);
228  void DoBindTexture(GLenum target, GLuint client_id, GLuint service_id);
229  void DoBindVertexArrayOES(GLuint client_id, GLuint service_id);
230
231  bool DoIsBuffer(GLuint client_id);
232  bool DoIsFramebuffer(GLuint client_id);
233  bool DoIsProgram(GLuint client_id);
234  bool DoIsRenderbuffer(GLuint client_id);
235  bool DoIsShader(GLuint client_id);
236  bool DoIsTexture(GLuint client_id);
237
238  void DoDeleteBuffer(GLuint client_id, GLuint service_id);
239  void DoDeleteFramebuffer(
240      GLuint client_id, GLuint service_id,
241      bool reset_draw, GLenum draw_target, GLuint draw_id,
242      bool reset_read, GLenum read_target, GLuint read_id);
243  void DoDeleteProgram(GLuint client_id, GLuint service_id);
244  void DoDeleteRenderbuffer(GLuint client_id, GLuint service_id);
245  void DoDeleteShader(GLuint client_id, GLuint service_id);
246  void DoDeleteTexture(GLuint client_id, GLuint service_id);
247
248  void DoCompressedTexImage2D(
249      GLenum target, GLint level, GLenum format,
250      GLsizei width, GLsizei height, GLint border,
251      GLsizei size, uint32 bucket_id);
252  void DoTexImage2D(
253      GLenum target, GLint level, GLenum internal_format,
254      GLsizei width, GLsizei height, GLint border,
255      GLenum format, GLenum type,
256      uint32 shared_memory_id, uint32 shared_memory_offset);
257  void DoTexImage2DConvertInternalFormat(
258      GLenum target, GLint level, GLenum requested_internal_format,
259      GLsizei width, GLsizei height, GLint border,
260      GLenum format, GLenum type,
261      uint32 shared_memory_id, uint32 shared_memory_offset,
262      GLenum expected_internal_format);
263  void DoRenderbufferStorage(
264      GLenum target, GLenum internal_format, GLenum actual_format,
265      GLsizei width, GLsizei height, GLenum error);
266  void DoFramebufferRenderbuffer(
267      GLenum target,
268      GLenum attachment,
269      GLenum renderbuffer_target,
270      GLuint renderbuffer_client_id,
271      GLuint renderbuffer_service_id,
272      GLenum error);
273  void DoFramebufferTexture2D(
274      GLenum target, GLenum attachment, GLenum tex_target,
275      GLuint texture_client_id, GLuint texture_service_id,
276      GLint level, GLenum error);
277  void DoVertexAttribPointer(
278      GLuint index, GLint size, GLenum type, GLsizei stride, GLuint offset);
279  void DoVertexAttribDivisorANGLE(GLuint index, GLuint divisor);
280
281  void DoEnableDisable(GLenum cap, bool enable);
282
283  void DoEnableVertexAttribArray(GLint index);
284
285  void DoBufferData(GLenum target, GLsizei size);
286
287  void DoBufferSubData(
288      GLenum target, GLint offset, GLsizei size, const void* data);
289
290  void SetupVertexBuffer();
291  void SetupAllNeededVertexBuffers();
292
293  void SetupIndexBuffer();
294
295  void DeleteVertexBuffer();
296
297  void DeleteIndexBuffer();
298
299  void SetupClearTextureExpectations(
300      GLuint service_id,
301      GLuint old_service_id,
302      GLenum bind_target,
303      GLenum target,
304      GLint level,
305      GLenum internal_format,
306      GLenum format,
307      GLenum type,
308      GLsizei width,
309      GLsizei height);
310
311  void SetupExpectationsForRestoreClearState(
312      GLclampf restore_red,
313      GLclampf restore_green,
314      GLclampf restore_blue,
315      GLclampf restore_alpha,
316      GLuint restore_stencil,
317      GLclampf restore_depth,
318      bool restore_scissor_test);
319
320  void SetupExpectationsForFramebufferClearing(
321      GLenum target,
322      GLuint clear_bits,
323      GLclampf restore_red,
324      GLclampf restore_green,
325      GLclampf restore_blue,
326      GLclampf restore_alpha,
327      GLuint restore_stencil,
328      GLclampf restore_depth,
329      bool restore_scissor_test);
330
331  void SetupExpectationsForFramebufferClearingMulti(
332      GLuint read_framebuffer_service_id,
333      GLuint draw_framebuffer_service_id,
334      GLenum target,
335      GLuint clear_bits,
336      GLclampf restore_red,
337      GLclampf restore_green,
338      GLclampf restore_blue,
339      GLclampf restore_alpha,
340      GLuint restore_stencil,
341      GLclampf restore_depth,
342      bool restore_scissor_test);
343
344  void SetupExpectationsForDepthMask(bool mask);
345  void SetupExpectationsForEnableDisable(GLenum cap, bool enable);
346  void SetupExpectationsForColorMask(bool red,
347                                     bool green,
348                                     bool blue,
349                                     bool alpha);
350  void SetupExpectationsForStencilMask(GLuint front_mask, GLuint back_mask);
351
352  void SetupExpectationsForApplyingDirtyState(
353      bool framebuffer_is_rgb,
354      bool framebuffer_has_depth,
355      bool framebuffer_has_stencil,
356      GLuint color_bits,  // NOTE! bits are 0x1000, 0x0100, 0x0010, and 0x0001
357      bool depth_mask,
358      bool depth_enabled,
359      GLuint front_stencil_mask,
360      GLuint back_stencil_mask,
361      bool stencil_enabled);
362
363  void SetupExpectationsForApplyingDefaultDirtyState();
364
365  void AddExpectationsForSimulatedAttrib0WithError(
366      GLsizei num_vertices, GLuint buffer_id, GLenum error);
367
368  void AddExpectationsForSimulatedAttrib0(
369      GLsizei num_vertices, GLuint buffer_id);
370
371  void AddExpectationsForGenVertexArraysOES();
372  void AddExpectationsForDeleteVertexArraysOES();
373  void AddExpectationsForDeleteBoundVertexArraysOES();
374  void AddExpectationsForBindVertexArrayOES();
375  void AddExpectationsForRestoreAttribState(GLuint attrib);
376
377  GLvoid* BufferOffset(unsigned i) {
378    return static_cast<int8 *>(NULL)+(i);
379  }
380
381  template <typename Command, typename Result>
382  bool IsObjectHelper(GLuint client_id) {
383    Result* result = static_cast<Result*>(shared_memory_address_);
384    Command cmd;
385    cmd.Init(client_id, kSharedMemoryId, kSharedMemoryOffset);
386    EXPECT_EQ(error::kNoError, ExecuteCmd(cmd));
387    bool isObject = static_cast<bool>(*result);
388    EXPECT_EQ(GL_NO_ERROR, GetGLError());
389    return isObject;
390  }
391
392 protected:
393  static const int kBackBufferWidth = 128;
394  static const int kBackBufferHeight = 64;
395
396  static const GLint kMaxTextureSize = 2048;
397  static const GLint kMaxCubeMapTextureSize = 256;
398  static const GLint kNumVertexAttribs = 16;
399  static const GLint kNumTextureUnits = 8;
400  static const GLint kMaxTextureImageUnits = 8;
401  static const GLint kMaxVertexTextureImageUnits = 2;
402  static const GLint kMaxFragmentUniformVectors = 16;
403  static const GLint kMaxVaryingVectors = 8;
404  static const GLint kMaxVertexUniformVectors = 128;
405  static const GLint kMaxViewportWidth = 8192;
406  static const GLint kMaxViewportHeight = 8192;
407
408  static const GLint kViewportX = 0;
409  static const GLint kViewportY = 0;
410  static const GLint kViewportWidth = kBackBufferWidth;
411  static const GLint kViewportHeight = kBackBufferHeight;
412
413  static const GLuint kServiceAttrib0BufferId = 801;
414  static const GLuint kServiceFixedAttribBufferId = 802;
415
416  static const GLuint kServiceBufferId = 301;
417  static const GLuint kServiceFramebufferId = 302;
418  static const GLuint kServiceRenderbufferId = 303;
419  static const GLuint kServiceTextureId = 304;
420  static const GLuint kServiceProgramId = 305;
421  static const GLuint kServiceShaderId = 306;
422  static const GLuint kServiceElementBufferId = 308;
423  static const GLuint kServiceQueryId = 309;
424  static const GLuint kServiceVertexArrayId = 310;
425
426  static const int32 kSharedMemoryId = 401;
427  static const size_t kSharedBufferSize = 2048;
428  static const uint32 kSharedMemoryOffset = 132;
429  static const int32 kInvalidSharedMemoryId = 402;
430  static const uint32 kInvalidSharedMemoryOffset = kSharedBufferSize + 1;
431  static const uint32 kInitialResult = 0xBDBDBDBDu;
432  static const uint8 kInitialMemoryValue = 0xBDu;
433
434  static const uint32 kNewClientId = 501;
435  static const uint32 kNewServiceId = 502;
436  static const uint32 kInvalidClientId = 601;
437
438  static const GLuint kServiceVertexShaderId = 321;
439  static const GLuint kServiceFragmentShaderId = 322;
440
441  static const GLuint kServiceCopyTextureChromiumShaderId = 701;
442  static const GLuint kServiceCopyTextureChromiumProgramId = 721;
443
444  static const GLuint kServiceCopyTextureChromiumTextureBufferId = 751;
445  static const GLuint kServiceCopyTextureChromiumVertexBufferId = 752;
446  static const GLuint kServiceCopyTextureChromiumFBOId = 753;
447  static const GLuint kServiceCopyTextureChromiumPositionAttrib = 761;
448  static const GLuint kServiceCopyTextureChromiumTexAttrib = 762;
449  static const GLuint kServiceCopyTextureChromiumSamplerLocation = 763;
450
451  static const GLsizei kNumVertices = 100;
452  static const GLsizei kNumIndices = 10;
453  static const int kValidIndexRangeStart = 1;
454  static const int kValidIndexRangeCount = 7;
455  static const int kInvalidIndexRangeStart = 0;
456  static const int kInvalidIndexRangeCount = 7;
457  static const int kOutOfRangeIndexRangeEnd = 10;
458  static const GLuint kMaxValidIndex = 7;
459
460  static const GLint kMaxAttribLength = 10;
461  static const char* kAttrib1Name;
462  static const char* kAttrib2Name;
463  static const char* kAttrib3Name;
464  static const GLint kAttrib1Size = 1;
465  static const GLint kAttrib2Size = 1;
466  static const GLint kAttrib3Size = 1;
467  static const GLint kAttrib1Location = 0;
468  static const GLint kAttrib2Location = 1;
469  static const GLint kAttrib3Location = 2;
470  static const GLenum kAttrib1Type = GL_FLOAT_VEC4;
471  static const GLenum kAttrib2Type = GL_FLOAT_VEC2;
472  static const GLenum kAttrib3Type = GL_FLOAT_VEC3;
473  static const GLint kInvalidAttribLocation = 30;
474  static const GLint kBadAttribIndex = kNumVertexAttribs;
475
476  static const GLint kMaxUniformLength = 12;
477  static const char* kUniform1Name;
478  static const char* kUniform2Name;
479  static const char* kUniform3Name;
480  static const GLint kUniform1Size = 1;
481  static const GLint kUniform2Size = 3;
482  static const GLint kUniform3Size = 2;
483  static const GLint kUniform1RealLocation = 3;
484  static const GLint kUniform2RealLocation = 10;
485  static const GLint kUniform2ElementRealLocation = 12;
486  static const GLint kUniform3RealLocation = 20;
487  static const GLint kUniform1FakeLocation = 0;               // These are
488  static const GLint kUniform2FakeLocation = 1;               // hardcoded
489  static const GLint kUniform2ElementFakeLocation = 0x10001;  // to match
490  static const GLint kUniform3FakeLocation = 2;               // ProgramManager.
491  static const GLint kUniform1DesiredLocation = -1;
492  static const GLint kUniform2DesiredLocation = -1;
493  static const GLint kUniform3DesiredLocation = -1;
494  static const GLenum kUniform1Type = GL_SAMPLER_2D;
495  static const GLenum kUniform2Type = GL_INT_VEC2;
496  static const GLenum kUniform3Type = GL_FLOAT_VEC3;
497  static const GLenum kUniformSamplerExternalType = GL_SAMPLER_EXTERNAL_OES;
498  static const GLenum kUniformCubemapType = GL_SAMPLER_CUBE;
499  static const GLint kInvalidUniformLocation = 30;
500  static const GLint kBadUniformIndex = 1000;
501
502  // Use StrictMock to make 100% sure we know how GL will be called.
503  scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_;
504  scoped_refptr<gfx::GLSurfaceStub> surface_;
505  scoped_refptr<gfx::GLContextStubWithExtensions> context_;
506  scoped_ptr<MockGLES2Decoder> mock_decoder_;
507  scoped_ptr<GLES2Decoder> decoder_;
508  MemoryTracker* memory_tracker_;
509
510  GLuint client_buffer_id_;
511  GLuint client_framebuffer_id_;
512  GLuint client_program_id_;
513  GLuint client_renderbuffer_id_;
514  GLuint client_shader_id_;
515  GLuint client_texture_id_;
516  GLuint client_element_buffer_id_;
517  GLuint client_vertex_shader_id_;
518  GLuint client_fragment_shader_id_;
519  GLuint client_query_id_;
520  GLuint client_vertexarray_id_;
521
522  uint32 shared_memory_id_;
523  uint32 shared_memory_offset_;
524  void* shared_memory_address_;
525  void* shared_memory_base_;
526
527  GLuint service_renderbuffer_id_;
528  bool service_renderbuffer_valid_;
529
530  uint32 immediate_buffer_[64];
531
532  const bool ignore_cached_state_for_test_;
533  bool cached_color_mask_red_;
534  bool cached_color_mask_green_;
535  bool cached_color_mask_blue_;
536  bool cached_color_mask_alpha_;
537  bool cached_depth_mask_;
538  GLuint cached_stencil_front_mask_;
539  GLuint cached_stencil_back_mask_;
540
541  struct EnableFlags {
542    EnableFlags();
543    bool cached_blend;
544    bool cached_cull_face;
545    bool cached_depth_test;
546    bool cached_dither;
547    bool cached_polygon_offset_fill;
548    bool cached_sample_alpha_to_coverage;
549    bool cached_sample_coverage;
550    bool cached_scissor_test;
551    bool cached_stencil_test;
552  };
553
554  EnableFlags enable_flags_;
555
556 private:
557  class MockCommandBufferEngine : public CommandBufferEngine {
558   public:
559    MockCommandBufferEngine();
560
561    virtual ~MockCommandBufferEngine();
562
563    virtual scoped_refptr<gpu::Buffer> GetSharedMemoryBuffer(int32 shm_id)
564        OVERRIDE;
565
566    void ClearSharedMemory() {
567      memset(valid_buffer_->memory(), kInitialMemoryValue, kSharedBufferSize);
568    }
569
570    virtual void set_token(int32 token) OVERRIDE;
571
572    virtual bool SetGetBuffer(int32 /* transfer_buffer_id */) OVERRIDE;
573
574    // Overridden from CommandBufferEngine.
575    virtual bool SetGetOffset(int32 offset) OVERRIDE;
576
577    // Overridden from CommandBufferEngine.
578    virtual int32 GetGetOffset() OVERRIDE;
579
580   private:
581    scoped_refptr<gpu::Buffer> valid_buffer_;
582    scoped_refptr<gpu::Buffer> invalid_buffer_;
583  };
584
585  // MockGLStates is used to track GL states and emulate driver
586  // behaviors on top of MockGLInterface.
587  class MockGLStates {
588   public:
589    MockGLStates()
590        : bound_array_buffer_object_(0),
591          bound_vertex_array_object_(0) {
592    }
593
594    ~MockGLStates() {
595    }
596
597    void OnBindArrayBuffer(GLuint id) {
598      bound_array_buffer_object_ = id;
599    }
600
601    void OnBindVertexArrayOES(GLuint id) {
602      bound_vertex_array_object_ = id;
603    }
604
605    void OnVertexAttribNullPointer() {
606      // When a vertex array object is bound, some drivers (AMD Linux,
607      // Qualcomm, etc.) have a bug where it incorrectly generates an
608      // GL_INVALID_OPERATION on glVertexAttribPointer() if pointer
609      // is NULL, no buffer is bound on GL_ARRAY_BUFFER.
610      // Make sure we don't trigger this bug.
611      if (bound_vertex_array_object_ != 0)
612        EXPECT_TRUE(bound_array_buffer_object_ != 0);
613    }
614
615   private:
616    GLuint bound_array_buffer_object_;
617    GLuint bound_vertex_array_object_;
618  };  // class MockGLStates
619
620  void AddExpectationsForVertexAttribManager();
621  void SetupMockGLBehaviors();
622
623  scoped_ptr< ::testing::StrictMock<MockCommandBufferEngine> > engine_;
624  scoped_refptr<ContextGroup> group_;
625  MockGLStates gl_states_;
626};
627
628class GLES2DecoderWithShaderTestBase : public GLES2DecoderTestBase {
629 public:
630  GLES2DecoderWithShaderTestBase()
631      : GLES2DecoderTestBase() {
632  }
633
634 protected:
635  virtual void SetUp() OVERRIDE;
636  virtual void TearDown() OVERRIDE;
637
638};
639
640// SpecializedSetup specializations that are needed in multiple unittest files.
641template <>
642void GLES2DecoderTestBase::SpecializedSetup<cmds::LinkProgram, 0>(bool valid);
643
644}  // namespace gles2
645}  // namespace gpu
646
647#endif  // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_BASE_H_
648