| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/command_buffer/service/test_helper.h" |
| |
| #include <algorithm> |
| #include <string> |
| |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_tokenizer.h" |
| #include "gpu/command_buffer/service/buffer_manager.h" |
| #include "gpu/command_buffer/service/error_state_mock.h" |
| #include "gpu/command_buffer/service/feature_info.h" |
| #include "gpu/command_buffer/service/gl_utils.h" |
| #include "gpu/command_buffer/service/gpu_switches.h" |
| #include "gpu/command_buffer/service/mocks.h" |
| #include "gpu/command_buffer/service/program_manager.h" |
| #include "gpu/command_buffer/service/texture_manager.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gl/gl_mock.h" |
| #include "ui/gl/gl_version_info.h" |
| |
| using ::testing::_; |
| using ::testing::DoAll; |
| using ::testing::InSequence; |
| using ::testing::MatcherCast; |
| using ::testing::Pointee; |
| using ::testing::NotNull; |
| using ::testing::Return; |
| using ::testing::SetArrayArgument; |
| using ::testing::SetArgumentPointee; |
| using ::testing::StrEq; |
| using ::testing::StrictMock; |
| |
| namespace gpu { |
| namespace gles2 { |
| |
| namespace { |
| |
| template<typename T> |
| T ConstructShaderVariable( |
| GLenum type, GLint array_size, GLenum precision, |
| bool static_use, const std::string& name) { |
| T var; |
| var.type = type; |
| var.arraySize = array_size; |
| var.precision = precision; |
| var.staticUse = static_use; |
| var.name = name; |
| var.mappedName = name; // No name hashing. |
| return var; |
| } |
| |
| } // namespace anonymous |
| |
| // GCC requires these declarations, but MSVC requires they not be present |
| #ifndef COMPILER_MSVC |
| const GLuint TestHelper::kServiceBlackTexture2dId; |
| const GLuint TestHelper::kServiceDefaultTexture2dId; |
| const GLuint TestHelper::kServiceBlackTexture3dId; |
| const GLuint TestHelper::kServiceDefaultTexture3dId; |
| const GLuint TestHelper::kServiceBlackTexture2dArrayId; |
| const GLuint TestHelper::kServiceDefaultTexture2dArrayId; |
| const GLuint TestHelper::kServiceBlackTextureCubemapId; |
| const GLuint TestHelper::kServiceDefaultTextureCubemapId; |
| const GLuint TestHelper::kServiceBlackExternalTextureId; |
| const GLuint TestHelper::kServiceDefaultExternalTextureId; |
| const GLuint TestHelper::kServiceBlackRectangleTextureId; |
| const GLuint TestHelper::kServiceDefaultRectangleTextureId; |
| |
| const GLint TestHelper::kMaxSamples; |
| const GLint TestHelper::kMaxRenderbufferSize; |
| const GLint TestHelper::kMaxTextureSize; |
| const GLint TestHelper::kMaxCubeMapTextureSize; |
| const GLint TestHelper::kMaxRectangleTextureSize; |
| const GLint TestHelper::kMax3DTextureSize; |
| const GLint TestHelper::kNumVertexAttribs; |
| const GLint TestHelper::kNumTextureUnits; |
| const GLint TestHelper::kMaxTextureImageUnits; |
| const GLint TestHelper::kMaxVertexTextureImageUnits; |
| const GLint TestHelper::kMaxFragmentUniformVectors; |
| const GLint TestHelper::kMaxFragmentUniformComponents; |
| const GLint TestHelper::kMaxVaryingVectors; |
| const GLint TestHelper::kMaxVaryingFloats; |
| const GLint TestHelper::kMaxVertexUniformVectors; |
| const GLint TestHelper::kMaxVertexUniformComponents; |
| #endif |
| |
| std::vector<std::string> TestHelper::split_extensions_; |
| |
| void TestHelper::SetupTextureInitializationExpectations( |
| ::gfx::MockGLInterface* gl, |
| GLenum target, |
| bool use_default_textures) { |
| InSequence sequence; |
| |
| bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); |
| bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); |
| bool is_3d_or_2d_array_target = (target == GL_TEXTURE_3D || |
| target == GL_TEXTURE_2D_ARRAY); |
| |
| static GLuint texture_2d_ids[] = { |
| kServiceBlackTexture2dId, |
| kServiceDefaultTexture2dId }; |
| static GLuint texture_3d_ids[] = { |
| kServiceBlackTexture3dId, |
| kServiceDefaultTexture3dId }; |
| static GLuint texture_2d_array_ids[] = { |
| kServiceBlackTexture2dArrayId, |
| kServiceDefaultTexture2dArrayId }; |
| static GLuint texture_cube_map_ids[] = { |
| kServiceBlackTextureCubemapId, |
| kServiceDefaultTextureCubemapId }; |
| static GLuint texture_external_oes_ids[] = { |
| kServiceBlackExternalTextureId, |
| kServiceDefaultExternalTextureId }; |
| static GLuint texture_rectangle_arb_ids[] = { |
| kServiceBlackRectangleTextureId, |
| kServiceDefaultRectangleTextureId }; |
| |
| const GLuint* texture_ids = NULL; |
| switch (target) { |
| case GL_TEXTURE_2D: |
| texture_ids = &texture_2d_ids[0]; |
| break; |
| case GL_TEXTURE_3D: |
| texture_ids = &texture_3d_ids[0]; |
| break; |
| case GL_TEXTURE_2D_ARRAY: |
| texture_ids = &texture_2d_array_ids[0]; |
| break; |
| case GL_TEXTURE_CUBE_MAP: |
| texture_ids = &texture_cube_map_ids[0]; |
| break; |
| case GL_TEXTURE_EXTERNAL_OES: |
| texture_ids = &texture_external_oes_ids[0]; |
| break; |
| case GL_TEXTURE_RECTANGLE_ARB: |
| texture_ids = &texture_rectangle_arb_ids[0]; |
| break; |
| default: |
| NOTREACHED(); |
| } |
| |
| int array_size = use_default_textures ? 2 : 1; |
| |
| EXPECT_CALL(*gl, GenTextures(array_size, _)) |
| .WillOnce(SetArrayArgument<1>(texture_ids, |
| texture_ids + array_size)) |
| .RetiresOnSaturation(); |
| for (int ii = 0; ii < array_size; ++ii) { |
| EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| if (needs_initialization) { |
| if (needs_faces) { |
| static GLenum faces[] = { |
| GL_TEXTURE_CUBE_MAP_POSITIVE_X, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_X, |
| GL_TEXTURE_CUBE_MAP_POSITIVE_Y, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, |
| GL_TEXTURE_CUBE_MAP_POSITIVE_Z, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, |
| }; |
| for (size_t ii = 0; ii < arraysize(faces); ++ii) { |
| EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA, |
| GL_UNSIGNED_BYTE, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } else { |
| if (is_3d_or_2d_array_target) { |
| EXPECT_CALL(*gl, TexImage3D(target, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, |
| GL_UNSIGNED_BYTE, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, |
| GL_UNSIGNED_BYTE, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| } |
| } |
| } |
| EXPECT_CALL(*gl, BindTexture(target, 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| void TestHelper::SetupTextureManagerInitExpectations( |
| ::gfx::MockGLInterface* gl, |
| bool is_es3_enabled, |
| const char* extensions, |
| bool use_default_textures) { |
| InSequence sequence; |
| |
| SetupTextureInitializationExpectations( |
| gl, GL_TEXTURE_2D, use_default_textures); |
| SetupTextureInitializationExpectations( |
| gl, GL_TEXTURE_CUBE_MAP, use_default_textures); |
| |
| if (is_es3_enabled) { |
| SetupTextureInitializationExpectations( |
| gl, GL_TEXTURE_3D, use_default_textures); |
| SetupTextureInitializationExpectations( |
| gl, GL_TEXTURE_2D_ARRAY, use_default_textures); |
| } |
| |
| bool ext_image_external = false; |
| bool arb_texture_rectangle = false; |
| base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); |
| while (t.GetNext()) { |
| if (t.token() == "GL_OES_EGL_image_external") { |
| ext_image_external = true; |
| break; |
| } |
| if (t.token() == "GL_ARB_texture_rectangle") { |
| arb_texture_rectangle = true; |
| break; |
| } |
| } |
| |
| if (ext_image_external) { |
| SetupTextureInitializationExpectations( |
| gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); |
| } |
| if (arb_texture_rectangle) { |
| SetupTextureInitializationExpectations( |
| gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); |
| } |
| } |
| |
| void TestHelper::SetupTextureDestructionExpectations( |
| ::gfx::MockGLInterface* gl, |
| GLenum target, |
| bool use_default_textures) { |
| if (!use_default_textures) |
| return; |
| |
| GLuint texture_id = 0; |
| switch (target) { |
| case GL_TEXTURE_2D: |
| texture_id = kServiceDefaultTexture2dId; |
| break; |
| case GL_TEXTURE_3D: |
| texture_id = kServiceDefaultTexture3dId; |
| break; |
| case GL_TEXTURE_2D_ARRAY: |
| texture_id = kServiceDefaultTexture2dArrayId; |
| break; |
| case GL_TEXTURE_CUBE_MAP: |
| texture_id = kServiceDefaultTextureCubemapId; |
| break; |
| case GL_TEXTURE_EXTERNAL_OES: |
| texture_id = kServiceDefaultExternalTextureId; |
| break; |
| case GL_TEXTURE_RECTANGLE_ARB: |
| texture_id = kServiceDefaultRectangleTextureId; |
| break; |
| default: |
| NOTREACHED(); |
| } |
| |
| EXPECT_CALL(*gl, DeleteTextures(1, Pointee(texture_id))) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| void TestHelper::SetupTextureManagerDestructionExpectations( |
| ::gfx::MockGLInterface* gl, |
| bool is_es3_enabled, |
| const char* extensions, |
| bool use_default_textures) { |
| SetupTextureDestructionExpectations(gl, GL_TEXTURE_2D, use_default_textures); |
| SetupTextureDestructionExpectations( |
| gl, GL_TEXTURE_CUBE_MAP, use_default_textures); |
| |
| if (is_es3_enabled) { |
| SetupTextureDestructionExpectations( |
| gl, GL_TEXTURE_3D, use_default_textures); |
| SetupTextureDestructionExpectations( |
| gl, GL_TEXTURE_2D_ARRAY,use_default_textures); |
| } |
| |
| bool ext_image_external = false; |
| bool arb_texture_rectangle = false; |
| base::CStringTokenizer t(extensions, extensions + strlen(extensions), " "); |
| while (t.GetNext()) { |
| if (t.token() == "GL_OES_EGL_image_external") { |
| ext_image_external = true; |
| break; |
| } |
| if (t.token() == "GL_ARB_texture_rectangle") { |
| arb_texture_rectangle = true; |
| break; |
| } |
| } |
| |
| if (ext_image_external) { |
| SetupTextureDestructionExpectations( |
| gl, GL_TEXTURE_EXTERNAL_OES, use_default_textures); |
| } |
| if (arb_texture_rectangle) { |
| SetupTextureDestructionExpectations( |
| gl, GL_TEXTURE_RECTANGLE_ARB, use_default_textures); |
| } |
| |
| EXPECT_CALL(*gl, DeleteTextures(TextureManager::kNumDefaultTextures, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| |
| void TestHelper::SetupContextGroupInitExpectations( |
| ::gfx::MockGLInterface* gl, |
| const DisallowedFeatures& disallowed_features, |
| const char* extensions, |
| const char* gl_version, |
| bool bind_generates_resource) { |
| InSequence sequence; |
| |
| SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version); |
| |
| gfx::GLVersionInfo gl_info(gl_version, "", extensions); |
| |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize)) |
| .RetiresOnSaturation(); |
| if (strstr(extensions, "GL_EXT_framebuffer_multisample") || |
| strstr(extensions, "GL_EXT_multisampled_render_to_texture") || |
| gl_info.is_es3) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxSamples)) |
| .RetiresOnSaturation(); |
| } else if (strstr(extensions, "GL_IMG_multisampled_render_to_texture")) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES_IMG, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxSamples)) |
| .RetiresOnSaturation(); |
| } |
| |
| if (gl_info.IsAtLeastGL(3, 3) || |
| (gl_info.IsAtLeastGL(3, 2) && |
| strstr(extensions, "GL_ARB_blend_func_extended")) || |
| (gl_info.is_es && strstr(extensions, "GL_EXT_blend_func_extended"))) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, _)) |
| .WillOnce(SetArgumentPointee<1>(8)) |
| .RetiresOnSaturation(); |
| } |
| |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_ATTRIBS, _)) |
| .WillOnce(SetArgumentPointee<1>(kNumVertexAttribs)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, _)) |
| .WillOnce(SetArgumentPointee<1>(kNumTextureUnits)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_SIZE, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxTextureSize)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxCubeMapTextureSize)) |
| .RetiresOnSaturation(); |
| if (gl_info.IsES3Capable()) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_3D_TEXTURE_SIZE, _)) |
| .WillOnce(SetArgumentPointee<1>(kMax3DTextureSize)) |
| .RetiresOnSaturation(); |
| } |
| if (strstr(extensions, "GL_ARB_texture_rectangle")) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxRectangleTextureSize)) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxTextureImageUnits)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits)) |
| .RetiresOnSaturation(); |
| |
| if (gl_info.is_es) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformVectors)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_VECTORS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxVaryingVectors)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformVectors)) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) |
| .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) |
| .RetiresOnSaturation(); |
| } |
| |
| bool use_default_textures = bind_generates_resource; |
| SetupTextureManagerInitExpectations( |
| gl, false, extensions, use_default_textures); |
| } |
| |
| void TestHelper::SetupFeatureInfoInitExpectations( |
| ::gfx::MockGLInterface* gl, const char* extensions) { |
| SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", ""); |
| } |
| |
| void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( |
| ::gfx::MockGLInterface* gl, |
| const char* extensions, |
| const char* gl_renderer, |
| const char* gl_version) { |
| InSequence sequence; |
| |
| EXPECT_CALL(*gl, GetString(GL_VERSION)) |
| .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version))) |
| .RetiresOnSaturation(); |
| |
| // Persistent storage is needed for the split extension string. |
| split_extensions_.clear(); |
| if (extensions) { |
| split_extensions_ = base::SplitString( |
| extensions, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY); |
| } |
| |
| gfx::GLVersionInfo gl_info(gl_version, gl_renderer, extensions); |
| if (!gl_info.is_es && gl_info.major_version >= 3) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_NUM_EXTENSIONS, _)) |
| .WillOnce(SetArgumentPointee<1>(split_extensions_.size())) |
| .RetiresOnSaturation(); |
| for (size_t ii = 0; ii < split_extensions_.size(); ++ii) { |
| EXPECT_CALL(*gl, GetStringi(GL_EXTENSIONS, ii)) |
| .WillOnce(Return(reinterpret_cast<const uint8*>( |
| split_extensions_[ii].c_str()))) |
| .RetiresOnSaturation(); |
| } |
| } else { |
| EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) |
| .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) |
| .RetiresOnSaturation(); |
| } |
| |
| EXPECT_CALL(*gl, GetString(GL_VERSION)) |
| .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version))) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetString(GL_RENDERER)) |
| .WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer))) |
| .RetiresOnSaturation(); |
| |
| if ((strstr(extensions, "GL_ARB_texture_float") || |
| gl_info.is_desktop_core_profile) || |
| (gl_info.is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) { |
| static const GLuint tx_ids[] = {101, 102}; |
| static const GLuint fb_ids[] = {103, 104}; |
| const GLsizei width = 16; |
| EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _)) |
| .WillOnce(SetArgumentPointee<1>(fb_ids[0])) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) |
| .WillOnce(SetArgumentPointee<1>(tx_ids[0])) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GenTextures(1, _)) |
| .WillOnce(SetArrayArgument<1>(tx_ids + 1, tx_ids + 2)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GenFramebuffersEXT(1, _)) |
| .WillOnce(SetArrayArgument<1>(fb_ids + 1, fb_ids + 2)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, tx_ids[1])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, |
| GL_NEAREST)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, width, 0, |
| GL_RGBA, GL_FLOAT, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, fb_ids[1])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER, |
| GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tx_ids[1], 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) |
| .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, width, 0, |
| GL_RGB, GL_FLOAT, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| if (gl_info.is_es3) { |
| EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) |
| .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) |
| .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, DeleteTextures(1, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, fb_ids[0])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, tx_ids[0])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| #if DCHECK_IS_ON() |
| EXPECT_CALL(*gl, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| #endif |
| } |
| |
| if (strstr(extensions, "GL_EXT_draw_buffers") || |
| strstr(extensions, "GL_ARB_draw_buffers") || |
| (gl_info.is_es3 && strstr(extensions, "GL_NV_draw_buffers")) || |
| gl_info.is_desktop_core_profile) { |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, _)) |
| .WillOnce(SetArgumentPointee<1>(8)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_MAX_DRAW_BUFFERS_ARB, _)) |
| .WillOnce(SetArgumentPointee<1>(8)) |
| .RetiresOnSaturation(); |
| } |
| |
| if (gl_info.is_es3 || gl_info.is_desktop_core_profile || |
| strstr(extensions, "GL_EXT_texture_rg") || |
| (strstr(extensions, "GL_ARB_texture_rg"))) { |
| static const GLuint tx_ids[] = {101, 102}; |
| static const GLuint fb_ids[] = {103, 104}; |
| const GLsizei width = 1; |
| EXPECT_CALL(*gl, GetIntegerv(GL_FRAMEBUFFER_BINDING, _)) |
| .WillOnce(SetArgumentPointee<1>(fb_ids[0])) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetIntegerv(GL_TEXTURE_BINDING_2D, _)) |
| .WillOnce(SetArgumentPointee<1>(tx_ids[0])) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GenTextures(1, _)) |
| .WillOnce(SetArrayArgument<1>(tx_ids + 1, tx_ids + 2)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, tx_ids[1])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, _, width, width, 0, |
| GL_RED_EXT, GL_UNSIGNED_BYTE, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GenFramebuffersEXT(1, _)) |
| .WillOnce(SetArrayArgument<1>(fb_ids + 1, fb_ids + 2)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, fb_ids[1])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, FramebufferTexture2DEXT(GL_FRAMEBUFFER, |
| GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tx_ids[1], 0)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) |
| .WillOnce(Return(GL_FRAMEBUFFER_COMPLETE)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, DeleteFramebuffersEXT(1, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, DeleteTextures(1, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindFramebufferEXT(GL_FRAMEBUFFER, fb_ids[0])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, tx_ids[0])) |
| .Times(1) |
| .RetiresOnSaturation(); |
| #if DCHECK_IS_ON() |
| EXPECT_CALL(*gl, GetError()) |
| .WillOnce(Return(GL_NO_ERROR)) |
| .RetiresOnSaturation(); |
| #endif |
| } |
| } |
| |
| void TestHelper::SetupExpectationsForClearingUniforms( |
| ::gfx::MockGLInterface* gl, UniformInfo* uniforms, size_t num_uniforms) { |
| for (size_t ii = 0; ii < num_uniforms; ++ii) { |
| const UniformInfo& info = uniforms[ii]; |
| switch (info.type) { |
| case GL_FLOAT: |
| EXPECT_CALL(*gl, Uniform1fv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_FLOAT_VEC2: |
| EXPECT_CALL(*gl, Uniform2fv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_FLOAT_VEC3: |
| EXPECT_CALL(*gl, Uniform3fv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_FLOAT_VEC4: |
| EXPECT_CALL(*gl, Uniform4fv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_INT: |
| case GL_BOOL: |
| case GL_SAMPLER_2D: |
| case GL_SAMPLER_CUBE: |
| case GL_SAMPLER_EXTERNAL_OES: |
| case GL_SAMPLER_3D_OES: |
| case GL_SAMPLER_2D_RECT_ARB: |
| case GL_SAMPLER_2D_ARRAY: |
| EXPECT_CALL(*gl, Uniform1iv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_UNSIGNED_INT: |
| EXPECT_CALL(*gl, Uniform1uiv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_INT_VEC2: |
| case GL_BOOL_VEC2: |
| EXPECT_CALL(*gl, Uniform2iv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_UNSIGNED_INT_VEC2: |
| EXPECT_CALL(*gl, Uniform2uiv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_INT_VEC3: |
| case GL_BOOL_VEC3: |
| EXPECT_CALL(*gl, Uniform3iv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_UNSIGNED_INT_VEC3: |
| EXPECT_CALL(*gl, Uniform3uiv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_INT_VEC4: |
| case GL_BOOL_VEC4: |
| EXPECT_CALL(*gl, Uniform4iv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_UNSIGNED_INT_VEC4: |
| EXPECT_CALL(*gl, Uniform4uiv(info.real_location, info.size, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_FLOAT_MAT2: |
| EXPECT_CALL(*gl, UniformMatrix2fv( |
| info.real_location, info.size, false, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_FLOAT_MAT3: |
| EXPECT_CALL(*gl, UniformMatrix3fv( |
| info.real_location, info.size, false, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| case GL_FLOAT_MAT4: |
| EXPECT_CALL(*gl, UniformMatrix4fv( |
| info.real_location, info.size, false, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| break; |
| default: |
| NOTREACHED(); |
| break; |
| } |
| } |
| } |
| |
| void TestHelper::SetupProgramSuccessExpectations( |
| ::gfx::MockGLInterface* gl, |
| const FeatureInfo* feature_info, |
| AttribInfo* attribs, |
| size_t num_attribs, |
| UniformInfo* uniforms, |
| size_t num_uniforms, |
| VaryingInfo* varyings, |
| size_t num_varyings, |
| ProgramOutputInfo* program_outputs, |
| size_t num_program_outputs, |
| GLuint service_id) { |
| EXPECT_CALL(*gl, |
| GetProgramiv(service_id, GL_LINK_STATUS, _)) |
| .WillOnce(SetArgumentPointee<2>(1)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, |
| GetProgramiv(service_id, GL_INFO_LOG_LENGTH, _)) |
| .WillOnce(SetArgumentPointee<2>(0)) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, |
| GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTES, _)) |
| .WillOnce(SetArgumentPointee<2>(num_attribs)) |
| .RetiresOnSaturation(); |
| size_t max_attrib_len = 0; |
| for (size_t ii = 0; ii < num_attribs; ++ii) { |
| size_t len = strlen(attribs[ii].name) + 1; |
| max_attrib_len = std::max(max_attrib_len, len); |
| } |
| EXPECT_CALL(*gl, |
| GetProgramiv(service_id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, _)) |
| .WillOnce(SetArgumentPointee<2>(max_attrib_len)) |
| .RetiresOnSaturation(); |
| |
| for (size_t ii = 0; ii < num_attribs; ++ii) { |
| const AttribInfo& info = attribs[ii]; |
| EXPECT_CALL(*gl, |
| GetActiveAttrib(service_id, ii, |
| max_attrib_len, _, _, _, _)) |
| .WillOnce(DoAll( |
| SetArgumentPointee<3>(strlen(info.name)), |
| SetArgumentPointee<4>(info.size), |
| SetArgumentPointee<5>(info.type), |
| SetArrayArgument<6>(info.name, |
| info.name + strlen(info.name) + 1))) |
| .RetiresOnSaturation(); |
| if (!ProgramManager::HasBuiltInPrefix(info.name)) { |
| EXPECT_CALL(*gl, GetAttribLocation(service_id, StrEq(info.name))) |
| .WillOnce(Return(info.location)) |
| .RetiresOnSaturation(); |
| } |
| } |
| EXPECT_CALL(*gl, |
| GetProgramiv(service_id, GL_ACTIVE_UNIFORMS, _)) |
| .WillOnce(SetArgumentPointee<2>(num_uniforms)) |
| .RetiresOnSaturation(); |
| |
| if (num_uniforms > 0) { |
| size_t max_uniform_len = 0; |
| for (size_t ii = 0; ii < num_uniforms; ++ii) { |
| size_t len = strlen(uniforms[ii].name) + 1; |
| max_uniform_len = std::max(max_uniform_len, len); |
| } |
| EXPECT_CALL(*gl, GetProgramiv(service_id, GL_ACTIVE_UNIFORM_MAX_LENGTH, _)) |
| .WillOnce(SetArgumentPointee<2>(max_uniform_len)) |
| .RetiresOnSaturation(); |
| for (size_t ii = 0; ii < num_uniforms; ++ii) { |
| const UniformInfo& info = uniforms[ii]; |
| EXPECT_CALL(*gl, |
| GetActiveUniform(service_id, ii, max_uniform_len, _, _, _, _)) |
| .WillOnce(DoAll(SetArgumentPointee<3>(strlen(info.name)), |
| SetArgumentPointee<4>(info.size), |
| SetArgumentPointee<5>(info.type), |
| SetArrayArgument<6>( |
| info.name, info.name + strlen(info.name) + 1))) |
| .RetiresOnSaturation(); |
| |
| if (info.real_location != -1) { |
| EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(info.name))) |
| .WillOnce(Return(info.real_location)) |
| .RetiresOnSaturation(); |
| } |
| if (info.size > 1) { |
| std::string base_name = info.name; |
| size_t array_pos = base_name.rfind("[0]"); |
| if (base_name.size() > 3 && array_pos == base_name.size() - 3) { |
| base_name = base_name.substr(0, base_name.size() - 3); |
| } |
| for (GLsizei jj = 1; jj < info.size; ++jj) { |
| std::string element_name(std::string(base_name) + "[" + |
| base::IntToString(jj) + "]"); |
| EXPECT_CALL(*gl, GetUniformLocation(service_id, StrEq(element_name))) |
| .WillOnce(Return(info.real_location + jj * 2)) |
| .RetiresOnSaturation(); |
| } |
| } |
| } |
| } |
| |
| if (feature_info->feature_flags().chromium_path_rendering) { |
| EXPECT_CALL(*gl, GetProgramInterfaceiv(service_id, GL_FRAGMENT_INPUT_NV, |
| GL_ACTIVE_RESOURCES, _)) |
| .WillOnce(SetArgumentPointee<3>(int(num_varyings))) |
| .RetiresOnSaturation(); |
| size_t max_varying_len = 0; |
| for (size_t ii = 0; ii < num_varyings; ++ii) { |
| size_t len = strlen(varyings[ii].name) + 1; |
| max_varying_len = std::max(max_varying_len, len); |
| } |
| EXPECT_CALL(*gl, GetProgramInterfaceiv(service_id, GL_FRAGMENT_INPUT_NV, |
| GL_MAX_NAME_LENGTH, _)) |
| .WillOnce(SetArgumentPointee<3>(int(max_varying_len))) |
| .RetiresOnSaturation(); |
| for (size_t ii = 0; ii < num_varyings; ++ii) { |
| VaryingInfo& info = varyings[ii]; |
| EXPECT_CALL(*gl, GetProgramResourceName(service_id, GL_FRAGMENT_INPUT_NV, |
| ii, max_varying_len, _, _)) |
| .WillOnce(DoAll(SetArgumentPointee<4>(strlen(info.name)), |
| SetArrayArgument<5>( |
| info.name, info.name + strlen(info.name) + 1))) |
| .RetiresOnSaturation(); |
| if (ProgramManager::HasBuiltInPrefix(info.name)) |
| continue; |
| |
| static const GLenum kPropsArray[] = {GL_LOCATION, GL_TYPE, |
| GL_ARRAY_SIZE}; |
| static const size_t kPropsSize = arraysize(kPropsArray); |
| EXPECT_CALL( |
| *gl, GetProgramResourceiv( |
| service_id, GL_FRAGMENT_INPUT_NV, ii, kPropsSize, |
| _ /*testing::ElementsAreArray(kPropsArray, kPropsSize)*/, |
| kPropsSize, _, _)) |
| .WillOnce(testing::Invoke([info](GLuint, GLenum, GLuint, GLsizei, |
| const GLenum*, GLsizei, |
| GLsizei* length, GLint* params) { |
| *length = kPropsSize; |
| params[0] = info.real_location; |
| params[1] = info.type; |
| params[2] = info.size; |
| })) |
| .RetiresOnSaturation(); |
| } |
| } |
| if (feature_info->gl_version_info().IsES3Capable() && |
| !feature_info->disable_shader_translator()) { |
| for (size_t ii = 0; ii < num_program_outputs; ++ii) { |
| ProgramOutputInfo& info = program_outputs[ii]; |
| if (ProgramManager::HasBuiltInPrefix(info.name)) |
| continue; |
| |
| EXPECT_CALL(*gl, GetFragDataLocation(service_id, StrEq(info.name))) |
| .WillOnce(Return(info.color_name)) |
| .RetiresOnSaturation(); |
| if (feature_info->feature_flags().ext_blend_func_extended) { |
| EXPECT_CALL(*gl, GetFragDataIndex(service_id, StrEq(info.name))) |
| .WillOnce(Return(info.index)) |
| .RetiresOnSaturation(); |
| } else { |
| // Test case must not use indices, or the context of the testcase has to |
| // support the dual source blending. |
| DCHECK(info.index == 0); |
| } |
| } |
| } |
| } |
| |
| void TestHelper::SetupShaderExpectations(::gfx::MockGLInterface* gl, |
| const FeatureInfo* feature_info, |
| AttribInfo* attribs, |
| size_t num_attribs, |
| UniformInfo* uniforms, |
| size_t num_uniforms, |
| GLuint service_id) { |
| InSequence s; |
| |
| EXPECT_CALL(*gl, LinkProgram(service_id)).Times(1).RetiresOnSaturation(); |
| |
| SetupProgramSuccessExpectations(gl, feature_info, attribs, num_attribs, |
| uniforms, num_uniforms, nullptr, 0, nullptr, |
| 0, service_id); |
| } |
| |
| void TestHelper::SetupShaderExpectationsWithVaryings( |
| ::gfx::MockGLInterface* gl, |
| const FeatureInfo* feature_info, |
| AttribInfo* attribs, |
| size_t num_attribs, |
| UniformInfo* uniforms, |
| size_t num_uniforms, |
| VaryingInfo* varyings, |
| size_t num_varyings, |
| ProgramOutputInfo* program_outputs, |
| size_t num_program_outputs, |
| GLuint service_id) { |
| InSequence s; |
| |
| EXPECT_CALL(*gl, |
| LinkProgram(service_id)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| |
| SetupProgramSuccessExpectations( |
| gl, feature_info, attribs, num_attribs, uniforms, num_uniforms, varyings, |
| num_varyings, program_outputs, num_program_outputs, service_id); |
| } |
| |
| void TestHelper::DoBufferData( |
| ::gfx::MockGLInterface* gl, MockErrorState* error_state, |
| BufferManager* manager, Buffer* buffer, GLenum target, GLsizeiptr size, |
| GLenum usage, const GLvoid* data, GLenum error) { |
| EXPECT_CALL(*error_state, CopyRealGLErrorsToWrapper(_, _, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| if (manager->IsUsageClientSideArray(usage)) { |
| EXPECT_CALL(*gl, BufferData(target, 0, _, usage)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*gl, BufferData(target, size, _, usage)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| EXPECT_CALL(*error_state, PeekGLError(_, _, _)) |
| .WillOnce(Return(error)) |
| .RetiresOnSaturation(); |
| manager->DoBufferData(error_state, buffer, target, size, usage, data); |
| } |
| |
| void TestHelper::SetTexParameteriWithExpectations( |
| ::gfx::MockGLInterface* gl, MockErrorState* error_state, |
| TextureManager* manager, TextureRef* texture_ref, |
| GLenum pname, GLint value, GLenum error) { |
| if (error == GL_NO_ERROR) { |
| EXPECT_CALL(*gl, TexParameteri(texture_ref->texture()->target(), |
| pname, value)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else if (error == GL_INVALID_ENUM) { |
| EXPECT_CALL(*error_state, SetGLErrorInvalidEnum(_, _, _, value, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } else { |
| EXPECT_CALL(*error_state, SetGLErrorInvalidParami(_, _, error, _, _, _)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| } |
| manager->SetParameteri("", error_state, texture_ref, pname, value); |
| } |
| |
| // static |
| void TestHelper::SetShaderStates( |
| ::gfx::MockGLInterface* gl, |
| Shader* shader, |
| bool expected_valid, |
| const std::string* const expected_log_info, |
| const std::string* const expected_translated_source, |
| const int* const expected_shader_version, |
| const AttributeMap* const expected_attrib_map, |
| const UniformMap* const expected_uniform_map, |
| const VaryingMap* const expected_varying_map, |
| const InterfaceBlockMap* const expected_interface_block_map, |
| const OutputVariableList* const expected_output_variable_list, |
| const NameMap* const expected_name_map) { |
| const std::string empty_log_info; |
| const std::string* log_info = (expected_log_info && !expected_valid) ? |
| expected_log_info : &empty_log_info; |
| const std::string empty_translated_source; |
| const std::string* translated_source = |
| (expected_translated_source && expected_valid) ? |
| expected_translated_source : &empty_translated_source; |
| int default_shader_version = 100; |
| const int* shader_version = (expected_shader_version && expected_valid) ? |
| expected_shader_version : &default_shader_version; |
| const AttributeMap empty_attrib_map; |
| const AttributeMap* attrib_map = (expected_attrib_map && expected_valid) ? |
| expected_attrib_map : &empty_attrib_map; |
| const UniformMap empty_uniform_map; |
| const UniformMap* uniform_map = (expected_uniform_map && expected_valid) ? |
| expected_uniform_map : &empty_uniform_map; |
| const VaryingMap empty_varying_map; |
| const VaryingMap* varying_map = (expected_varying_map && expected_valid) ? |
| expected_varying_map : &empty_varying_map; |
| const InterfaceBlockMap empty_interface_block_map; |
| const InterfaceBlockMap* interface_block_map = |
| (expected_interface_block_map && expected_valid) ? |
| expected_interface_block_map : &empty_interface_block_map; |
| const OutputVariableList empty_output_variable_list; |
| const OutputVariableList* output_variable_list = |
| (expected_output_variable_list && expected_valid) |
| ? expected_output_variable_list |
| : &empty_output_variable_list; |
| const NameMap empty_name_map; |
| const NameMap* name_map = (expected_name_map && expected_valid) ? |
| expected_name_map : &empty_name_map; |
| |
| MockShaderTranslator* mock_translator = new MockShaderTranslator; |
| scoped_refptr<ShaderTranslatorInterface> translator(mock_translator); |
| EXPECT_CALL(*mock_translator, Translate(_, |
| NotNull(), // log_info |
| NotNull(), // translated_source |
| NotNull(), // shader_version |
| NotNull(), // attrib_map |
| NotNull(), // uniform_map |
| NotNull(), // varying_map |
| NotNull(), // interface_block_map |
| NotNull(), // output_variable_list |
| NotNull())) // name_map |
| .WillOnce(DoAll(SetArgumentPointee<1>(*log_info), |
| SetArgumentPointee<2>(*translated_source), |
| SetArgumentPointee<3>(*shader_version), |
| SetArgumentPointee<4>(*attrib_map), |
| SetArgumentPointee<5>(*uniform_map), |
| SetArgumentPointee<6>(*varying_map), |
| SetArgumentPointee<7>(*interface_block_map), |
| SetArgumentPointee<8>(*output_variable_list), |
| SetArgumentPointee<9>(*name_map), Return(expected_valid))) |
| .RetiresOnSaturation(); |
| if (expected_valid) { |
| EXPECT_CALL(*gl, ShaderSource(shader->service_id(), 1, _, NULL)) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, CompileShader(shader->service_id())) |
| .Times(1) |
| .RetiresOnSaturation(); |
| EXPECT_CALL(*gl, GetShaderiv(shader->service_id(), |
| GL_COMPILE_STATUS, |
| NotNull())) // status |
| .WillOnce(SetArgumentPointee<2>(GL_TRUE)) |
| .RetiresOnSaturation(); |
| } |
| shader->RequestCompile(translator, Shader::kGL); |
| shader->DoCompile(); |
| } |
| |
| // static |
| void TestHelper::SetShaderStates( |
| ::gfx::MockGLInterface* gl, Shader* shader, bool valid) { |
| SetShaderStates(gl, shader, valid, nullptr, nullptr, nullptr, nullptr, |
| nullptr, nullptr, nullptr, nullptr, nullptr); |
| } |
| |
| // static |
| sh::Attribute TestHelper::ConstructAttribute( |
| GLenum type, GLint array_size, GLenum precision, |
| bool static_use, const std::string& name) { |
| return ConstructShaderVariable<sh::Attribute>( |
| type, array_size, precision, static_use, name); |
| } |
| |
| // static |
| sh::Uniform TestHelper::ConstructUniform( |
| GLenum type, GLint array_size, GLenum precision, |
| bool static_use, const std::string& name) { |
| return ConstructShaderVariable<sh::Uniform>( |
| type, array_size, precision, static_use, name); |
| } |
| |
| // static |
| sh::Varying TestHelper::ConstructVarying( |
| GLenum type, GLint array_size, GLenum precision, |
| bool static_use, const std::string& name) { |
| return ConstructShaderVariable<sh::Varying>( |
| type, array_size, precision, static_use, name); |
| } |
| |
| sh::OutputVariable TestHelper::ConstructOutputVariable( |
| GLenum type, |
| GLint array_size, |
| GLenum precision, |
| bool static_use, |
| const std::string& name) { |
| return ConstructShaderVariable<sh::OutputVariable>( |
| type, array_size, precision, static_use, name); |
| } |
| |
| ScopedGLImplementationSetter::ScopedGLImplementationSetter( |
| gfx::GLImplementation implementation) |
| : old_implementation_(gfx::GetGLImplementation()) { |
| gfx::SetGLImplementation(implementation); |
| } |
| |
| ScopedGLImplementationSetter::~ScopedGLImplementationSetter() { |
| gfx::SetGLImplementation(old_implementation_); |
| } |
| |
| } // namespace gles2 |
| } // namespace gpu |
| |