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#include "gpu/command_buffer/service/test_helper.h"
6
7#include <algorithm>
8#include <string>
9
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_tokenizer.h"
12#include "gpu/command_buffer/service/buffer_manager.h"
13#include "gpu/command_buffer/service/error_state_mock.h"
14#include "gpu/command_buffer/service/gl_utils.h"
15#include "gpu/command_buffer/service/gpu_switches.h"
16#include "gpu/command_buffer/service/mocks.h"
17#include "gpu/command_buffer/service/program_manager.h"
18#include "gpu/command_buffer/service/texture_manager.h"
19#include "testing/gtest/include/gtest/gtest.h"
20#include "ui/gl/gl_mock.h"
21
22using ::testing::_;
23using ::testing::DoAll;
24using ::testing::InSequence;
25using ::testing::MatcherCast;
26using ::testing::Pointee;
27using ::testing::NotNull;
28using ::testing::Return;
29using ::testing::SetArrayArgument;
30using ::testing::SetArgumentPointee;
31using ::testing::StrEq;
32using ::testing::StrictMock;
33
34namespace gpu {
35namespace gles2 {
36
37// GCC requires these declarations, but MSVC requires they not be present
38#ifndef COMPILER_MSVC
39const GLuint TestHelper::kServiceBlackTexture2dId;
40const GLuint TestHelper::kServiceDefaultTexture2dId;
41const GLuint TestHelper::kServiceBlackTextureCubemapId;
42const GLuint TestHelper::kServiceDefaultTextureCubemapId;
43const GLuint TestHelper::kServiceBlackExternalTextureId;
44const GLuint TestHelper::kServiceDefaultExternalTextureId;
45const GLuint TestHelper::kServiceBlackRectangleTextureId;
46const GLuint TestHelper::kServiceDefaultRectangleTextureId;
47
48const GLint TestHelper::kMaxSamples;
49const GLint TestHelper::kMaxRenderbufferSize;
50const GLint TestHelper::kMaxTextureSize;
51const GLint TestHelper::kMaxCubeMapTextureSize;
52const GLint TestHelper::kNumVertexAttribs;
53const GLint TestHelper::kNumTextureUnits;
54const GLint TestHelper::kMaxTextureImageUnits;
55const GLint TestHelper::kMaxVertexTextureImageUnits;
56const GLint TestHelper::kMaxFragmentUniformVectors;
57const GLint TestHelper::kMaxFragmentUniformComponents;
58const GLint TestHelper::kMaxVaryingVectors;
59const GLint TestHelper::kMaxVaryingFloats;
60const GLint TestHelper::kMaxVertexUniformVectors;
61const GLint TestHelper::kMaxVertexUniformComponents;
62#endif
63
64void TestHelper::SetupTextureInitializationExpectations(
65    ::gfx::MockGLInterface* gl,
66    GLenum target,
67    bool use_default_textures) {
68  InSequence sequence;
69
70  bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES);
71  bool needs_faces = (target == GL_TEXTURE_CUBE_MAP);
72
73  static GLuint texture_2d_ids[] = {
74    kServiceBlackTexture2dId,
75    kServiceDefaultTexture2dId };
76  static GLuint texture_cube_map_ids[] = {
77    kServiceBlackTextureCubemapId,
78    kServiceDefaultTextureCubemapId };
79  static GLuint texture_external_oes_ids[] = {
80    kServiceBlackExternalTextureId,
81    kServiceDefaultExternalTextureId };
82  static GLuint texture_rectangle_arb_ids[] = {
83    kServiceBlackRectangleTextureId,
84    kServiceDefaultRectangleTextureId };
85
86  const GLuint* texture_ids = NULL;
87  switch (target) {
88    case GL_TEXTURE_2D:
89      texture_ids = &texture_2d_ids[0];
90      break;
91    case GL_TEXTURE_CUBE_MAP:
92      texture_ids = &texture_cube_map_ids[0];
93      break;
94    case GL_TEXTURE_EXTERNAL_OES:
95      texture_ids = &texture_external_oes_ids[0];
96      break;
97    case GL_TEXTURE_RECTANGLE_ARB:
98      texture_ids = &texture_rectangle_arb_ids[0];
99      break;
100    default:
101      NOTREACHED();
102  }
103
104  int array_size = use_default_textures ? 2 : 1;
105
106  EXPECT_CALL(*gl, GenTextures(array_size, _))
107      .WillOnce(SetArrayArgument<1>(texture_ids,
108                                    texture_ids + array_size))
109          .RetiresOnSaturation();
110  for (int ii = 0; ii < array_size; ++ii) {
111    EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii]))
112        .Times(1)
113        .RetiresOnSaturation();
114    if (needs_initialization) {
115      if (needs_faces) {
116        static GLenum faces[] = {
117          GL_TEXTURE_CUBE_MAP_POSITIVE_X,
118          GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
119          GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
120          GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
121          GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
122          GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
123        };
124        for (size_t ii = 0; ii < arraysize(faces); ++ii) {
125          EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA,
126                                      GL_UNSIGNED_BYTE, _))
127              .Times(1)
128              .RetiresOnSaturation();
129        }
130      } else {
131        EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA,
132                                    GL_UNSIGNED_BYTE, _))
133            .Times(1)
134            .RetiresOnSaturation();
135      }
136    }
137  }
138  EXPECT_CALL(*gl, BindTexture(target, 0))
139      .Times(1)
140      .RetiresOnSaturation();
141}
142
143void TestHelper::SetupTextureManagerInitExpectations(
144    ::gfx::MockGLInterface* gl,
145    const char* extensions,
146    bool use_default_textures) {
147  InSequence sequence;
148
149  SetupTextureInitializationExpectations(
150      gl, GL_TEXTURE_2D, use_default_textures);
151  SetupTextureInitializationExpectations(
152      gl, GL_TEXTURE_CUBE_MAP, use_default_textures);
153
154  bool ext_image_external = false;
155  bool arb_texture_rectangle = false;
156  base::CStringTokenizer t(extensions, extensions + strlen(extensions), " ");
157  while (t.GetNext()) {
158    if (t.token() == "GL_OES_EGL_image_external") {
159      ext_image_external = true;
160      break;
161    }
162    if (t.token() == "GL_ARB_texture_rectangle") {
163      arb_texture_rectangle = true;
164      break;
165    }
166  }
167
168  if (ext_image_external) {
169    SetupTextureInitializationExpectations(
170        gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures);
171  }
172  if (arb_texture_rectangle) {
173    SetupTextureInitializationExpectations(
174        gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures);
175  }
176}
177
178void TestHelper::SetupTextureDestructionExpectations(
179    ::gfx::MockGLInterface* gl,
180    GLenum target,
181    bool use_default_textures) {
182  if (!use_default_textures)
183    return;
184
185  GLuint texture_id = 0;
186  switch (target) {
187    case GL_TEXTURE_2D:
188      texture_id = kServiceDefaultTexture2dId;
189      break;
190    case GL_TEXTURE_CUBE_MAP:
191      texture_id = kServiceDefaultTextureCubemapId;
192      break;
193    case GL_TEXTURE_EXTERNAL_OES:
194      texture_id = kServiceDefaultExternalTextureId;
195      break;
196    case GL_TEXTURE_RECTANGLE_ARB:
197      texture_id = kServiceDefaultRectangleTextureId;
198      break;
199    default:
200      NOTREACHED();
201  }
202
203  EXPECT_CALL(*gl, DeleteTextures(1, Pointee(texture_id)))
204      .Times(1)
205      .RetiresOnSaturation();
206}
207
208void TestHelper::SetupTextureManagerDestructionExpectations(
209    ::gfx::MockGLInterface* gl,
210    const char* extensions,
211    bool use_default_textures) {
212  SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D, use_default_textures);
213  SetupTextureDestructionExpectations(
214      gl, GL_TEXTURE_CUBE_MAP, use_default_textures);
215
216  bool ext_image_external = false;
217  bool arb_texture_rectangle = false;
218  base::CStringTokenizer t(extensions, extensions + strlen(extensions), " ");
219  while (t.GetNext()) {
220    if (t.token() == "GL_OES_EGL_image_external") {
221      ext_image_external = true;
222      break;
223    }
224    if (t.token() == "GL_ARB_texture_rectangle") {
225      arb_texture_rectangle = true;
226      break;
227    }
228  }
229
230  if (ext_image_external) {
231    SetupTextureDestructionExpectations(
232        gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures);
233  }
234  if (arb_texture_rectangle) {
235    SetupTextureDestructionExpectations(
236        gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures);
237  }
238
239  EXPECT_CALL(*gl, DeleteTextures(4, _))
240      .Times(1)
241      .RetiresOnSaturation();
242}
243
244void TestHelper::SetupContextGroupInitExpectations(
245    ::gfx::MockGLInterface* gl,
246    const DisallowedFeatures& disallowed_features,
247    const char* extensions,
248    const char* gl_version,
249    bool bind_generates_resource) {
250  InSequence sequence;
251
252  SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version);
253
254  std::string l_version(base::StringToLowerASCII(std::string(gl_version)));
255  bool is_es3 = (l_version.substr(0, 12) == "opengl es 3.");
256
257  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _))
258      .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize))
259      .RetiresOnSaturation();
260  if (strstr(extensions, "GL_EXT_framebuffer_multisample") ||
261      strstr(extensions, "GL_EXT_multisampled_render_to_texture") || is_es3) {
262    EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _))
263        .WillOnce(SetArgumentPointee<1>(kMaxSamples))
264        .RetiresOnSaturation();
265  } else if (strstr(extensions, "GL_IMG_multisampled_render_to_texture")) {
266    EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES_IMG, _))
267        .WillOnce(SetArgumentPointee<1>(kMaxSamples))
268        .RetiresOnSaturation();
269  }
270  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _))
271      .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs))
272      .RetiresOnSaturation();
273  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _))
274      .WillOnce(SetArgumentPointee<1>(kNumTextureUnits))
275      .RetiresOnSaturation();
276  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_SIZE, _))
277      .WillOnce(SetArgumentPointee<1>(kMaxTextureSize))
278      .RetiresOnSaturation();
279  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _))
280      .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize))
281      .RetiresOnSaturation();
282  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _))
283      .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits))
284      .RetiresOnSaturation();
285  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _))
286      .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits))
287      .RetiresOnSaturation();
288  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _))
289      .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents))
290      .RetiresOnSaturation();
291  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _))
292      .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats))
293      .RetiresOnSaturation();
294  EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _))
295      .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents))
296      .RetiresOnSaturation();
297
298  bool use_default_textures = bind_generates_resource;
299  SetupTextureManagerInitExpectations(gl, extensions, use_default_textures);
300}
301
302void TestHelper::SetupFeatureInfoInitExpectations(
303      ::gfx::MockGLInterface* gl, const char* extensions) {
304  SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", "");
305}
306
307void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion(
308     ::gfx::MockGLInterface* gl,
309     const char* extensions,
310     const char* gl_renderer,
311     const char* gl_version) {
312  InSequence sequence;
313
314  EXPECT_CALL(*gl, GetString(GL_EXTENSIONS))
315      .WillOnce(Return(reinterpret_cast<const uint8*>(extensions)))
316      .RetiresOnSaturation();
317  EXPECT_CALL(*gl, GetString(GL_RENDERER))
318      .WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer)))
319      .RetiresOnSaturation();
320  EXPECT_CALL(*gl, GetString(GL_VERSION))
321      .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version)))
322      .RetiresOnSaturation();
323
324  std::string l_version(base::StringToLowerASCII(std::string(gl_version)));
325  bool is_es3 = (l_version.substr(0, 12) == "opengl es 3.");
326
327  if (strstr(extensions, "GL_ARB_texture_float") ||
328      (is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) {
329    static const GLuint gl_ids[] = {101, 102};
330    const GLsizei width = 16;
331    EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _))
332        .WillOnce(SetArgumentPointee<1>(gl_ids[0]))
333        .RetiresOnSaturation();
334    EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _))
335        .WillOnce(SetArgumentPointee<1>(gl_ids[0]))
336        .RetiresOnSaturation();
337    EXPECT_CALL(*gl, GenTextures(1, _))
338        .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2))
339        .RetiresOnSaturation();
340    EXPECT_CALL(*gl, GenFramebuffersEXT(1, _))
341        .WillOnce(SetArrayArgument<1>(gl_ids + 1, gl_ids + 2))
342        .RetiresOnSaturation();
343    EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[1]))
344        .Times(1)
345        .RetiresOnSaturation();
346    EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
347        GL_NEAREST))
348        .Times(1)
349        .RetiresOnSaturation();
350    EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0,
351        GL_RGBA, GL_FLOAT, _))
352        .Times(1)
353        .RetiresOnSaturation();
354    EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[1]))
355        .Times(1)
356        .RetiresOnSaturation();
357    EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER,
358        GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gl_ids[1], 0))
359        .Times(1)
360        .RetiresOnSaturation();
361    EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
362        .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
363        .RetiresOnSaturation();
364    EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0,
365        GL_RGB, GL_FLOAT, _))
366        .Times(1)
367        .RetiresOnSaturation();
368    if (is_es3) {
369      EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
370          .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT))
371          .RetiresOnSaturation();
372    } else {
373      EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER))
374          .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE))
375          .RetiresOnSaturation();
376    }
377    EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _))
378        .Times(1)
379        .RetiresOnSaturation();
380    EXPECT_CALL(*gl, DeleteTextures(1, _))
381        .Times(1)
382        .RetiresOnSaturation();
383    EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, gl_ids[0]))
384        .Times(1)
385        .RetiresOnSaturation();
386    EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, gl_ids[0]))
387        .Times(1)
388        .RetiresOnSaturation();
389#if DCHECK_IS_ON
390    EXPECT_CALL(*gl, GetError())
391        .WillOnce(Return(GL_NO_ERROR))
392        .RetiresOnSaturation();
393#endif
394  }
395}
396
397void TestHelper::SetupExpectationsForClearingUniforms(
398    ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms) {
399  for (size_t ii = 0; ii < num_uniforms; ++ii) {
400    const UniformInfo& info = uniforms[ii];
401    switch (info.type) {
402    case GL_FLOAT:
403      EXPECT_CALL(*gl, Uniform1fv(info.real_location, info.size, _))
404          .Times(1)
405          .RetiresOnSaturation();
406      break;
407    case GL_FLOAT_VEC2:
408      EXPECT_CALL(*gl, Uniform2fv(info.real_location, info.size, _))
409          .Times(1)
410          .RetiresOnSaturation();
411      break;
412    case GL_FLOAT_VEC3:
413      EXPECT_CALL(*gl, Uniform3fv(info.real_location, info.size, _))
414          .Times(1)
415          .RetiresOnSaturation();
416      break;
417    case GL_FLOAT_VEC4:
418      EXPECT_CALL(*gl, Uniform4fv(info.real_location, info.size, _))
419          .Times(1)
420          .RetiresOnSaturation();
421      break;
422    case GL_INT:
423    case GL_BOOL:
424    case GL_SAMPLER_2D:
425    case GL_SAMPLER_CUBE:
426    case GL_SAMPLER_EXTERNAL_OES:
427    case GL_SAMPLER_3D_OES:
428    case GL_SAMPLER_2D_RECT_ARB:
429      EXPECT_CALL(*gl, Uniform1iv(info.real_location, info.size, _))
430          .Times(1)
431          .RetiresOnSaturation();
432      break;
433    case GL_INT_VEC2:
434    case GL_BOOL_VEC2:
435      EXPECT_CALL(*gl, Uniform2iv(info.real_location, info.size, _))
436          .Times(1)
437          .RetiresOnSaturation();
438      break;
439    case GL_INT_VEC3:
440    case GL_BOOL_VEC3:
441      EXPECT_CALL(*gl, Uniform3iv(info.real_location, info.size, _))
442          .Times(1)
443          .RetiresOnSaturation();
444      break;
445    case GL_INT_VEC4:
446    case GL_BOOL_VEC4:
447      EXPECT_CALL(*gl, Uniform4iv(info.real_location, info.size, _))
448          .Times(1)
449          .RetiresOnSaturation();
450      break;
451    case GL_FLOAT_MAT2:
452      EXPECT_CALL(*gl, UniformMatrix2fv(
453          info.real_location, info.size, false, _))
454          .Times(1)
455          .RetiresOnSaturation();
456      break;
457    case GL_FLOAT_MAT3:
458      EXPECT_CALL(*gl, UniformMatrix3fv(
459          info.real_location, info.size, false, _))
460          .Times(1)
461          .RetiresOnSaturation();
462      break;
463    case GL_FLOAT_MAT4:
464      EXPECT_CALL(*gl, UniformMatrix4fv(
465          info.real_location, info.size, false, _))
466          .Times(1)
467          .RetiresOnSaturation();
468      break;
469    default:
470      NOTREACHED();
471      break;
472    }
473  }
474}
475
476void TestHelper::SetupProgramSuccessExpectations(
477    ::gfx::MockGLInterface* gl,
478    AttribInfo* attribs, size_t num_attribs,
479    UniformInfo* uniforms, size_t num_uniforms,
480    GLuint service_id) {
481  EXPECT_CALL(*gl,
482      GetProgramiv(service_id, GL_LINK_STATUS, _))
483      .WillOnce(SetArgumentPointee<2>(1))
484      .RetiresOnSaturation();
485  EXPECT_CALL(*gl,
486      GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _))
487      .WillOnce(SetArgumentPointee<2>(0))
488      .RetiresOnSaturation();
489  EXPECT_CALL(*gl,
490      GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _))
491      .WillOnce(SetArgumentPointee<2>(num_attribs))
492      .RetiresOnSaturation();
493  size_t max_attrib_len = 0;
494  for (size_t ii = 0; ii < num_attribs; ++ii) {
495    size_t len = strlen(attribs[ii].name) + 1;
496    max_attrib_len = std::max(max_attrib_len, len);
497  }
498  EXPECT_CALL(*gl,
499      GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _))
500      .WillOnce(SetArgumentPointee<2>(max_attrib_len))
501      .RetiresOnSaturation();
502
503  for (size_t ii = 0; ii < num_attribs; ++ii) {
504    const AttribInfo& info = attribs[ii];
505    EXPECT_CALL(*gl,
506        GetActiveAttrib(service_id, ii,
507                        max_attrib_len, _, _, _, _))
508        .WillOnce(DoAll(
509            SetArgumentPointee<3>(strlen(info.name)),
510            SetArgumentPointee<4>(info.size),
511            SetArgumentPointee<5>(info.type),
512            SetArrayArgument<6>(info.name,
513                                info.name + strlen(info.name) + 1)))
514        .RetiresOnSaturation();
515    if (!ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) {
516      EXPECT_CALL(*gl, GetAttribLocation(service_id, StrEq(info.name)))
517          .WillOnce(Return(info.location))
518          .RetiresOnSaturation();
519    }
520  }
521  EXPECT_CALL(*gl,
522      GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _))
523      .WillOnce(SetArgumentPointee<2>(num_uniforms))
524      .RetiresOnSaturation();
525
526  size_t max_uniform_len = 0;
527  for (size_t ii = 0; ii < num_uniforms; ++ii) {
528    size_t len = strlen(uniforms[ii].name) + 1;
529    max_uniform_len = std::max(max_uniform_len, len);
530  }
531  EXPECT_CALL(*gl,
532      GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _))
533      .WillOnce(SetArgumentPointee<2>(max_uniform_len))
534      .RetiresOnSaturation();
535  for (size_t ii = 0; ii < num_uniforms; ++ii) {
536    const UniformInfo& info = uniforms[ii];
537    EXPECT_CALL(*gl,
538        GetActiveUniform(service_id, ii,
539                         max_uniform_len, _, _, _, _))
540        .WillOnce(DoAll(
541            SetArgumentPointee<3>(strlen(info.name)),
542            SetArgumentPointee<4>(info.size),
543            SetArgumentPointee<5>(info.type),
544            SetArrayArgument<6>(info.name,
545                                info.name + strlen(info.name) + 1)))
546        .RetiresOnSaturation();
547  }
548
549  for (int pass = 0; pass < 2; ++pass) {
550    for (size_t ii = 0; ii < num_uniforms; ++ii) {
551      const UniformInfo& info = uniforms[ii];
552      if (ProgramManager::IsInvalidPrefix(info.name, strlen(info.name))) {
553        continue;
554      }
555      if (pass == 0) {
556        EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(info.name)))
557            .WillOnce(Return(info.real_location))
558            .RetiresOnSaturation();
559      }
560      if ((pass == 0 && info.desired_location >= 0) ||
561          (pass == 1 && info.desired_location < 0)) {
562        if (info.size > 1) {
563          std::string base_name = info.name;
564          size_t array_pos = base_name.rfind("[0]");
565          if (base_name.size() > 3 && array_pos == base_name.size() - 3) {
566            base_name = base_name.substr(0, base_name.size() - 3);
567          }
568          for (GLsizei jj = 1; jj < info.size; ++jj) {
569            std::string element_name(
570                std::string(base_name) + "[" + base::IntToString(jj) + "]");
571            EXPECT_CALL(*gl, GetUniformLocation(
572                service_id, StrEq(element_name)))
573                .WillOnce(Return(info.real_location + jj * 2))
574                .RetiresOnSaturation();
575          }
576        }
577      }
578    }
579  }
580}
581
582void TestHelper::SetupShader(
583    ::gfx::MockGLInterface* gl,
584    AttribInfo* attribs, size_t num_attribs,
585    UniformInfo* uniforms, size_t num_uniforms,
586    GLuint service_id) {
587  InSequence s;
588
589  EXPECT_CALL(*gl,
590      LinkProgram(service_id))
591      .Times(1)
592      .RetiresOnSaturation();
593
594  SetupProgramSuccessExpectations(
595      gl, attribs, num_attribs, uniforms, num_uniforms, service_id);
596}
597
598void TestHelper::DoBufferData(
599    ::gfx::MockGLInterface* gl, MockErrorState* error_state,
600    BufferManager* manager, Buffer* buffer, GLsizeiptr size, GLenum usage,
601    const GLvoid* data, GLenum error) {
602  EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _))
603      .Times(1)
604      .RetiresOnSaturation();
605  if (manager->IsUsageClientSideArray(usage)) {
606    EXPECT_CALL(*gl, BufferData(
607        buffer->target(), 0, _, usage))
608        .Times(1)
609        .RetiresOnSaturation();
610  } else {
611    EXPECT_CALL(*gl, BufferData(
612        buffer->target(), size, _, usage))
613        .Times(1)
614        .RetiresOnSaturation();
615  }
616  EXPECT_CALL(*error_state, PeekGLError(_, _, _))
617      .WillOnce(Return(error))
618      .RetiresOnSaturation();
619  manager->DoBufferData(error_state, buffer, size, usage, data);
620}
621
622void TestHelper::SetTexParameteriWithExpectations(
623    ::gfx::MockGLInterface* gl, MockErrorState* error_state,
624    TextureManager* manager, TextureRef* texture_ref,
625    GLenum pname, GLint value, GLenum error) {
626  if (error == GL_NO_ERROR) {
627    if (pname != GL_TEXTURE_POOL_CHROMIUM) {
628      EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(),
629                                     pname, value))
630          .Times(1)
631          .RetiresOnSaturation();
632    }
633  } else if (error == GL_INVALID_ENUM) {
634    EXPECT_CALL(*error_state, SetGLErrorInvalidEnum(_, _, _, value, _))
635        .Times(1)
636        .RetiresOnSaturation();
637  } else {
638    EXPECT_CALL(*error_state, SetGLErrorInvalidParami(_, _, error, _, _, _))
639        .Times(1)
640        .RetiresOnSaturation();
641  }
642  manager->SetParameteri("", error_state, texture_ref, pname, value);
643}
644
645// static
646void TestHelper::SetShaderStates(
647      ::gfx::MockGLInterface* gl, Shader* shader,
648      bool expected_valid,
649      const std::string* const expected_log_info,
650      const std::string* const expected_translated_source,
651      const ShaderTranslatorInterface::VariableMap* const expected_attrib_map,
652      const ShaderTranslatorInterface::VariableMap* const expected_uniform_map,
653      const ShaderTranslatorInterface::VariableMap* const expected_varying_map,
654      const ShaderTranslatorInterface::NameMap* const expected_name_map) {
655  const std::string empty_log_info;
656  const std::string* log_info = (expected_log_info && !expected_valid) ?
657      expected_log_info : &empty_log_info;
658  const std::string empty_translated_source;
659  const std::string* translated_source =
660      (expected_translated_source && expected_valid) ?
661          expected_translated_source : &empty_translated_source;
662  const ShaderTranslatorInterface::VariableMap empty_attrib_map;
663  const ShaderTranslatorInterface::VariableMap* attrib_map =
664      (expected_attrib_map && expected_valid) ?
665          expected_attrib_map : &empty_attrib_map;
666  const ShaderTranslatorInterface::VariableMap empty_uniform_map;
667  const ShaderTranslatorInterface::VariableMap* uniform_map =
668      (expected_uniform_map && expected_valid) ?
669          expected_uniform_map : &empty_uniform_map;
670  const ShaderTranslatorInterface::VariableMap empty_varying_map;
671  const ShaderTranslatorInterface::VariableMap* varying_map =
672      (expected_varying_map && expected_valid) ?
673          expected_varying_map : &empty_varying_map;
674  const ShaderTranslatorInterface::NameMap empty_name_map;
675  const ShaderTranslatorInterface::NameMap* name_map =
676      (expected_name_map && expected_valid) ?
677          expected_name_map : &empty_name_map;
678
679  MockShaderTranslator translator;
680  EXPECT_CALL(translator, Translate(_,
681                                    NotNull(),  // log_info
682                                    NotNull(),  // translated_source
683                                    NotNull(),  // attrib_map
684                                    NotNull(),  // uniform_map
685                                    NotNull(),  // varying_map
686                                    NotNull()))  // name_map
687      .WillOnce(DoAll(SetArgumentPointee<1>(*log_info),
688                      SetArgumentPointee<2>(*translated_source),
689                      SetArgumentPointee<3>(*attrib_map),
690                      SetArgumentPointee<4>(*uniform_map),
691                      SetArgumentPointee<5>(*varying_map),
692                      SetArgumentPointee<6>(*name_map),
693                      Return(expected_valid)))
694      .RetiresOnSaturation();
695  if (expected_valid) {
696    EXPECT_CALL(*gl, ShaderSource(shader->service_id(), 1, _, NULL))
697        .Times(1)
698        .RetiresOnSaturation();
699    EXPECT_CALL(*gl, CompileShader(shader->service_id()))
700        .Times(1)
701        .RetiresOnSaturation();
702    EXPECT_CALL(*gl, GetShaderiv(shader->service_id(),
703                                 GL_COMPILE_STATUS,
704                                 NotNull()))  // status
705        .WillOnce(SetArgumentPointee<2>(GL_TRUE))
706        .RetiresOnSaturation();
707  }
708  shader->DoCompile(&translator, Shader::kGL);
709}
710
711// static
712void TestHelper::SetShaderStates(
713      ::gfx::MockGLInterface* gl, Shader* shader, bool valid) {
714  SetShaderStates(gl, shader, valid, NULL, NULL, NULL, NULL, NULL, NULL);
715}
716
717ScopedGLImplementationSetter::ScopedGLImplementationSetter(
718    gfx::GLImplementation implementation)
719    : old_implementation_(gfx::GetGLImplementation()) {
720  gfx::SetGLImplementation(implementation);
721}
722
723ScopedGLImplementationSetter::~ScopedGLImplementationSetter() {
724  gfx::SetGLImplementation(old_implementation_);
725}
726
727}  // namespace gles2
728}  // namespace gpu
729
730