| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file defines tests that implementations of GLImage should pass in order | 5 // This file defines tests that implementations of GLImage should pass in order |
| 6 // to be conformant. | 6 // to be conformant. |
| 7 | 7 |
| 8 #ifndef UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ | 8 #ifndef UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ |
| 9 #define UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ | 9 #define UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ |
| 10 | 10 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "ui/gl/gl_helper.h" | 21 #include "ui/gl/gl_helper.h" |
| 22 #include "ui/gl/gl_image.h" | 22 #include "ui/gl/gl_image.h" |
| 23 #include "ui/gl/gl_implementation.h" | 23 #include "ui/gl/gl_implementation.h" |
| 24 #include "ui/gl/gl_surface.h" | 24 #include "ui/gl/gl_surface.h" |
| 25 #include "ui/gl/test/gl_image_test_support.h" | 25 #include "ui/gl/test/gl_image_test_support.h" |
| 26 #include "ui/gl/test/gl_test_helper.h" | 26 #include "ui/gl/test/gl_test_helper.h" |
| 27 | 27 |
| 28 namespace gl { | 28 namespace gl { |
| 29 namespace { | 29 namespace { |
| 30 | 30 |
| 31 std::string PrependFragmentSamplerType(unsigned target, | 31 // Compiles a fragment shader for sampling out of a texture of |size| bound to |
| 32 std::string shader_string) { | 32 // |target| and checks for compilation errors. |
| 33 GLuint LoadFragmentShader(unsigned target, const gfx::Size& size) { |
| 34 // clang-format off |
| 35 const char kFragmentShader[] = STRINGIZE( |
| 36 uniform SamplerType a_texture; |
| 37 varying vec2 v_texCoord; |
| 38 void main() { |
| 39 gl_FragColor = TextureLookup(a_texture, v_texCoord * TextureScale); |
| 40 } |
| 41 ); |
| 42 const char kShaderFloatPrecision[] = STRINGIZE( |
| 43 precision mediump float; |
| 44 ); |
| 45 // clang-format on |
| 46 |
| 47 bool is_gles = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; |
| 33 switch (target) { | 48 switch (target) { |
| 34 case GL_TEXTURE_2D: | 49 case GL_TEXTURE_2D: |
| 35 DCHECK_NE(shader_string.find("SamplerType"), std::string::npos); | 50 return gfx::GLHelper::LoadShader( |
| 36 DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos); | 51 GL_FRAGMENT_SHADER, |
| 37 return "#define SamplerType sampler2D\n" | 52 base::StringPrintf("%s\n" |
| 38 "#define TextureLookup texture2D\n" + | 53 "#define SamplerType sampler2D\n" |
| 39 shader_string; | 54 "#define TextureLookup texture2D\n" |
| 55 "#define TextureScale vec2(1.0, 1.0)\n" |
| 56 "%s", |
| 57 is_gles ? kShaderFloatPrecision : "", |
| 58 kFragmentShader) |
| 59 .c_str()); |
| 40 case GL_TEXTURE_RECTANGLE_ARB: | 60 case GL_TEXTURE_RECTANGLE_ARB: |
| 41 DCHECK_NE(shader_string.find("SamplerType"), std::string::npos); | 61 return gfx::GLHelper::LoadShader( |
| 42 DCHECK_NE(shader_string.find("TextureLookup"), std::string::npos); | 62 GL_FRAGMENT_SHADER, |
| 43 return "#extension GL_ARB_texture_rectangle : require\n" | 63 base::StringPrintf("%s\n" |
| 44 "#define SamplerType sampler2DRect\n" | 64 "#extension GL_ARB_texture_rectangle : require\n" |
| 45 "#define TextureLookup texture2DRect\n" + | 65 "#define SamplerType sampler2DRect\n" |
| 46 shader_string; | 66 "#define TextureLookup texture2DRect\n" |
| 67 "#define TextureScale vec2(%f, %f)\n" |
| 68 "%s", |
| 69 is_gles ? kShaderFloatPrecision : "", |
| 70 static_cast<double>(size.width()), |
| 71 static_cast<double>(size.height()), |
| 72 kFragmentShader) |
| 73 .c_str()); |
| 47 default: | 74 default: |
| 48 NOTREACHED(); | 75 NOTREACHED(); |
| 49 break; | 76 return 0; |
| 50 } | 77 } |
| 51 return shader_string; | |
| 52 } | 78 } |
| 53 | 79 |
| 54 struct ProgramAndShaders { | 80 // Draws texture bound to |target| of texture unit 0 to the currently bound |
| 55 GLuint program; | 81 // frame buffer. |
| 56 GLuint vertex_shader; | 82 void DrawTextureQuad(GLenum target, const gfx::Size& size) { |
| 57 GLuint fragment_shader; | |
| 58 }; | |
| 59 | |
| 60 // Creates a shader that reads from a texture. | |
| 61 // Returns the newly created programs and shaders. | |
| 62 void SetUpVertexAndFragmentShader(GLenum target, ProgramAndShaders* pas) { | |
| 63 // clang-format off | 83 // clang-format off |
| 64 const char kVertexShader[] = STRINGIZE( | 84 const char kVertexShader[] = STRINGIZE( |
| 65 attribute vec2 a_position; | 85 attribute vec2 a_position; |
| 66 varying vec2 v_texCoord; | 86 varying vec2 v_texCoord; |
| 67 void main() { | 87 void main() { |
| 68 gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); | 88 gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0); |
| 69 v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5; | 89 v_texCoord = (a_position + vec2(1.0, 1.0)) * 0.5; |
| 70 } | 90 } |
| 71 ); | 91 ); |
| 72 const char kFragmentShader[] = STRINGIZE( | |
| 73 uniform SamplerType a_texture; | |
| 74 varying vec2 v_texCoord; | |
| 75 void main() { | |
| 76 gl_FragColor = TextureLookup(a_texture, v_texCoord); | |
| 77 } | |
| 78 ); | |
| 79 const char kShaderFloatPrecision[] = STRINGIZE( | |
| 80 precision mediump float; | |
| 81 ); | |
| 82 // clang-format on | 92 // clang-format on |
| 83 | 93 |
| 84 GLuint vertex_shader = | 94 GLuint vertex_shader = |
| 85 gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader); | 95 gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader); |
| 86 bool is_gles = gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2; | 96 GLuint fragment_shader = LoadFragmentShader(target, size); |
| 87 GLuint fragment_shader = gfx::GLHelper::LoadShader( | |
| 88 GL_FRAGMENT_SHADER, | |
| 89 base::StringPrintf( | |
| 90 "%s\n%s", is_gles ? kShaderFloatPrecision : "", | |
| 91 PrependFragmentSamplerType(target, kFragmentShader).c_str()) | |
| 92 .c_str()); | |
| 93 GLuint program = gfx::GLHelper::SetupProgram(vertex_shader, fragment_shader); | 97 GLuint program = gfx::GLHelper::SetupProgram(vertex_shader, fragment_shader); |
| 94 EXPECT_NE(program, 0u); | 98 EXPECT_NE(program, 0u); |
| 95 glUseProgram(program); | 99 glUseProgram(program); |
| 96 | 100 |
| 97 GLint sampler_location = glGetUniformLocation(program, "a_texture"); | 101 GLint sampler_location = glGetUniformLocation(program, "a_texture"); |
| 98 ASSERT_NE(sampler_location, -1); | 102 ASSERT_NE(sampler_location, -1); |
| 99 glUniform1i(sampler_location, 0); | 103 glUniform1i(sampler_location, 0); |
| 100 | 104 |
| 101 pas->program = program; | 105 GLuint vertex_buffer = gfx::GLHelper::SetupQuadVertexBuffer(); |
| 102 pas->vertex_shader = vertex_shader; | 106 gfx::GLHelper::DrawQuad(vertex_buffer); |
| 103 pas->fragment_shader = fragment_shader; | 107 |
| 108 glDeleteShader(vertex_shader); |
| 109 glDeleteShader(fragment_shader); |
| 110 glDeleteProgram(program); |
| 111 glDeleteBuffersARB(1, &vertex_buffer); |
| 104 } | 112 } |
| 105 | 113 |
| 106 } // namespace | 114 } // namespace |
| 107 | 115 |
| 108 template <typename GLImageTestDelegate> | 116 template <typename GLImageTestDelegate> |
| 109 class GLImageTest : public testing::Test { | 117 class GLImageTest : public testing::Test { |
| 110 protected: | 118 protected: |
| 111 // Overridden from testing::Test: | 119 // Overridden from testing::Test: |
| 112 void SetUp() override { | 120 void SetUp() override { |
| 113 GLImageTestSupport::InitializeGL(); | 121 GLImageTestSupport::InitializeGL(); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 class GLImageZeroInitializeTest : public GLImageTest<GLImageTestDelegate> {}; | 174 class GLImageZeroInitializeTest : public GLImageTest<GLImageTestDelegate> {}; |
| 167 | 175 |
| 168 // This test verifies that if an uninitialized image is bound to a texture, the | 176 // This test verifies that if an uninitialized image is bound to a texture, the |
| 169 // result is zero-initialized. | 177 // result is zero-initialized. |
| 170 TYPED_TEST_CASE_P(GLImageZeroInitializeTest); | 178 TYPED_TEST_CASE_P(GLImageZeroInitializeTest); |
| 171 | 179 |
| 172 // TODO(erikchen): Enable this test when it actually passes on Mac. | 180 // TODO(erikchen): Enable this test when it actually passes on Mac. |
| 173 // https://crbug.com/584760. | 181 // https://crbug.com/584760. |
| 174 TYPED_TEST_P(GLImageZeroInitializeTest, DISABLED_ZeroInitialize) { | 182 TYPED_TEST_P(GLImageZeroInitializeTest, DISABLED_ZeroInitialize) { |
| 175 const gfx::Size image_size(256, 256); | 183 const gfx::Size image_size(256, 256); |
| 176 scoped_refptr<gl::GLImage> image = this->delegate_.CreateImage(image_size); | |
| 177 GLenum target = this->delegate_.GetTextureTarget(); | |
| 178 GLuint uninitialized_texture = GLTestHelper::CreateTexture(target); | |
| 179 | 184 |
| 180 glBindTexture(target, uninitialized_texture); | |
| 181 ASSERT_TRUE(image->BindTexImage(target)); | |
| 182 GLuint framebuffer = | 185 GLuint framebuffer = |
| 183 GLTestHelper::SetupFramebuffer(image_size.width(), image_size.height()); | 186 GLTestHelper::SetupFramebuffer(image_size.width(), image_size.height()); |
| 184 ASSERT_TRUE(framebuffer); | 187 ASSERT_TRUE(framebuffer); |
| 185 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer); | 188 glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer); |
| 186 glViewport(0, 0, image_size.width(), image_size.height()); | 189 glViewport(0, 0, image_size.width(), image_size.height()); |
| 187 GLuint vertex_buffer = gfx::GLHelper::SetupQuadVertexBuffer(); | |
| 188 | 190 |
| 189 ProgramAndShaders pas; | 191 // Create an uninitialized image of preferred format. |
| 190 SetUpVertexAndFragmentShader(target, &pas); | 192 scoped_refptr<gl::GLImage> image = this->delegate_.CreateImage(image_size); |
| 191 gfx::GLHelper::DrawQuad(vertex_buffer); | |
| 192 | 193 |
| 194 // Create a texture that |image| will be bound to. |
| 195 GLenum target = this->delegate_.GetTextureTarget(); |
| 196 GLuint texture = GLTestHelper::CreateTexture(target); |
| 197 glBindTexture(target, texture); |
| 198 |
| 199 // Bind |image| to |texture|. |
| 200 bool rv = image->BindTexImage(target); |
| 201 EXPECT_TRUE(rv); |
| 202 |
| 203 // Draw |texture| to viewport. |
| 204 DrawTextureQuad(target, image_size); |
| 205 |
| 206 // Release |image| from |texture|. |
| 207 image->ReleaseTexImage(target); |
| 208 |
| 209 // Read back pixels to check expectations. |
| 193 const uint8_t zero_color[] = {0, 0, 0, 0}; | 210 const uint8_t zero_color[] = {0, 0, 0, 0}; |
| 194 GLTestHelper::CheckPixels(0, 0, image_size.width(), image_size.height(), | 211 GLTestHelper::CheckPixels(0, 0, image_size.width(), image_size.height(), |
| 195 zero_color); | 212 zero_color); |
| 196 | 213 |
| 197 glDeleteProgram(pas.program); | 214 // Clean up. |
| 198 glDeleteShader(pas.vertex_shader); | 215 glDeleteTextures(1, &texture); |
| 199 glDeleteShader(pas.fragment_shader); | |
| 200 glDeleteBuffersARB(1, &vertex_buffer); | |
| 201 glDeleteFramebuffersEXT(1, &framebuffer); | 216 glDeleteFramebuffersEXT(1, &framebuffer); |
| 202 | 217 image->Destroy(true /* have_context */); |
| 203 image->ReleaseTexImage(target); | |
| 204 image->Destroy(true); | |
| 205 glDeleteTextures(1, &uninitialized_texture); | |
| 206 } | 218 } |
| 207 | 219 |
| 208 REGISTER_TYPED_TEST_CASE_P(GLImageZeroInitializeTest, DISABLED_ZeroInitialize); | 220 REGISTER_TYPED_TEST_CASE_P(GLImageZeroInitializeTest, DISABLED_ZeroInitialize); |
| 209 | 221 |
| 210 template <typename GLImageTestDelegate> | 222 template <typename GLImageTestDelegate> |
| 211 class GLImageCopyTest : public GLImageTest<GLImageTestDelegate> {}; | 223 class GLImageCopyTest : public GLImageTest<GLImageTestDelegate> {}; |
| 212 | 224 |
| 213 TYPED_TEST_CASE_P(GLImageCopyTest); | 225 TYPED_TEST_CASE_P(GLImageCopyTest); |
| 214 | 226 |
| 215 TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { | 227 TYPED_TEST_P(GLImageCopyTest, CopyTexImage) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 241 image_size.width(), image_size.height(), | 253 image_size.width(), image_size.height(), |
| 242 static_cast<int>(RowSizeForBufferFormat(image_size.width(), | 254 static_cast<int>(RowSizeForBufferFormat(image_size.width(), |
| 243 gfx::BufferFormat::RGBA_8888, 0)), | 255 gfx::BufferFormat::RGBA_8888, 0)), |
| 244 0, gfx::BufferFormat::RGBA_8888, texture_color, pixels.get()); | 256 0, gfx::BufferFormat::RGBA_8888, texture_color, pixels.get()); |
| 245 glBindTexture(target, texture); | 257 glBindTexture(target, texture); |
| 246 glTexImage2D(target, 0, GL_RGBA, image_size.width(), image_size.height(), 0, | 258 glTexImage2D(target, 0, GL_RGBA, image_size.width(), image_size.height(), 0, |
| 247 GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); | 259 GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()); |
| 248 | 260 |
| 249 // Copy |image| to |texture|. | 261 // Copy |image| to |texture|. |
| 250 bool rv = image->CopyTexImage(target); | 262 bool rv = image->CopyTexImage(target); |
| 251 | |
| 252 EXPECT_TRUE(rv); | 263 EXPECT_TRUE(rv); |
| 253 | 264 |
| 254 ProgramAndShaders pas; | 265 // Draw |texture| to viewport. |
| 255 SetUpVertexAndFragmentShader(target, &pas); | 266 DrawTextureQuad(target, image_size); |
| 256 | 267 |
| 257 GLuint vertex_buffer = gfx::GLHelper::SetupQuadVertexBuffer(); | 268 // Read back pixels to check expectations. |
| 258 // Draw |texture| to viewport and read back pixels to check expectations. | |
| 259 gfx::GLHelper::DrawQuad(vertex_buffer); | |
| 260 | |
| 261 GLTestHelper::CheckPixels(0, 0, image_size.width(), image_size.height(), | 269 GLTestHelper::CheckPixels(0, 0, image_size.width(), image_size.height(), |
| 262 image_color); | 270 image_color); |
| 263 | 271 |
| 264 // Clean up. | 272 // Clean up. |
| 265 glDeleteProgram(pas.program); | |
| 266 glDeleteShader(pas.vertex_shader); | |
| 267 glDeleteShader(pas.fragment_shader); | |
| 268 glDeleteBuffersARB(1, &vertex_buffer); | |
| 269 glDeleteTextures(1, &texture); | 273 glDeleteTextures(1, &texture); |
| 270 glDeleteFramebuffersEXT(1, &framebuffer); | 274 glDeleteFramebuffersEXT(1, &framebuffer); |
| 271 image->Destroy(true); | 275 image->Destroy(true /* have_context */); |
| 272 } | 276 } |
| 273 | 277 |
| 274 // The GLImageCopyTest test case verifies that the GLImage implementation | 278 // The GLImageCopyTest test case verifies that the GLImage implementation |
| 275 // handles CopyTexImage correctly. | 279 // handles CopyTexImage correctly. |
| 276 REGISTER_TYPED_TEST_CASE_P(GLImageCopyTest, CopyTexImage); | 280 REGISTER_TYPED_TEST_CASE_P(GLImageCopyTest, CopyTexImage); |
| 277 | 281 |
| 278 } // namespace gl | 282 } // namespace gl |
| 279 | 283 |
| 280 #endif // UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ | 284 #endif // UI_GL_TEST_GL_IMAGE_TEST_TEMPLATE_H_ |
| OLD | NEW |