Home | History | Annotate | Download | only in service
      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 
     22 using ::testing::_;
     23 using ::testing::DoAll;
     24 using ::testing::InSequence;
     25 using ::testing::MatcherCast;
     26 using ::testing::Pointee;
     27 using ::testing::NotNull;
     28 using ::testing::Return;
     29 using ::testing::SetArrayArgument;
     30 using ::testing::SetArgumentPointee;
     31 using ::testing::StrEq;
     32 using ::testing::StrictMock;
     33 
     34 namespace gpu {
     35 namespace gles2 {
     36 
     37 // GCC requires these declarations, but MSVC requires they not be present
     38 #ifndef COMPILER_MSVC
     39 const GLuint TestHelper::kServiceBlackTexture2dId;
     40 const GLuint TestHelper::kServiceDefaultTexture2dId;
     41 const GLuint TestHelper::kServiceBlackTextureCubemapId;
     42 const GLuint TestHelper::kServiceDefaultTextureCubemapId;
     43 const GLuint TestHelper::kServiceBlackExternalTextureId;
     44 const GLuint TestHelper::kServiceDefaultExternalTextureId;
     45 const GLuint TestHelper::kServiceBlackRectangleTextureId;
     46 const GLuint TestHelper::kServiceDefaultRectangleTextureId;
     47 
     48 const GLint TestHelper::kMaxSamples;
     49 const GLint TestHelper::kMaxRenderbufferSize;
     50 const GLint TestHelper::kMaxTextureSize;
     51 const GLint TestHelper::kMaxCubeMapTextureSize;
     52 const GLint TestHelper::kNumVertexAttribs;
     53 const GLint TestHelper::kNumTextureUnits;
     54 const GLint TestHelper::kMaxTextureImageUnits;
     55 const GLint TestHelper::kMaxVertexTextureImageUnits;
     56 const GLint TestHelper::kMaxFragmentUniformVectors;
     57 const GLint TestHelper::kMaxFragmentUniformComponents;
     58 const GLint TestHelper::kMaxVaryingVectors;
     59 const GLint TestHelper::kMaxVaryingFloats;
     60 const GLint TestHelper::kMaxVertexUniformVectors;
     61 const GLint TestHelper::kMaxVertexUniformComponents;
     62 #endif
     63 
     64 void 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 
    143 void 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 
    178 void 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 
    208 void 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 
    244 void 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 
    302 void TestHelper::SetupFeatureInfoInitExpectations(
    303       ::gfx::MockGLInterface* gl, const char* extensions) {
    304   SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", "");
    305 }
    306 
    307 void 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 
    397 void 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 
    476 void 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 
    582 void 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 
    598 void 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 
    622 void 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
    646 void 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
    712 void TestHelper::SetShaderStates(
    713       ::gfx::MockGLInterface* gl, Shader* shader, bool valid) {
    714   SetShaderStates(gl, shader, valid, NULL, NULL, NULL, NULL, NULL, NULL);
    715 }
    716 
    717 ScopedGLImplementationSetter::ScopedGLImplementationSetter(
    718     gfx::GLImplementation implementation)
    719     : old_implementation_(gfx::GetGLImplementation()) {
    720   gfx::SetGLImplementation(implementation);
    721 }
    722 
    723 ScopedGLImplementationSetter::~ScopedGLImplementationSetter() {
    724   gfx::SetGLImplementation(old_implementation_);
    725 }
    726 
    727 }  // namespace gles2
    728 }  // namespace gpu
    729 
    730