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 <GLES2/gl2.h> 6 #include <GLES2/gl2ext.h> 7 8 #include "gpu/command_buffer/tests/gl_manager.h" 9 #include "gpu/command_buffer/tests/gl_test_utils.h" 10 #include "testing/gmock/include/gmock/gmock.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 #define SHADER(Src) #Src 14 15 namespace gpu { 16 17 class DepthTextureTest : public testing::Test { 18 protected: 19 static const GLsizei kResolution = 64; 20 virtual void SetUp() { 21 GLManager::Options options; 22 options.size = gfx::Size(kResolution, kResolution); 23 gl_.Initialize(options); 24 } 25 26 virtual void TearDown() { 27 gl_.Destroy(); 28 } 29 30 GLuint SetupUnitQuad(GLint position_location); 31 32 GLManager gl_; 33 }; 34 35 GLuint DepthTextureTest::SetupUnitQuad(GLint position_location) { 36 GLuint vbo = 0; 37 glGenBuffers(1, &vbo); 38 glBindBuffer(GL_ARRAY_BUFFER, vbo); 39 static float vertices[] = { 40 1.0f, 1.0f, 1.0f, 41 -1.0f, 1.0f, 0.0f, 42 -1.0f, -1.0f, -1.0f, 43 1.0f, 1.0f, 1.0f, 44 -1.0f, -1.0f, -1.0f, 45 1.0f, -1.0f, 0.0f, 46 }; 47 glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 48 glEnableVertexAttribArray(position_location); 49 glVertexAttribPointer(position_location, 3, GL_FLOAT, GL_FALSE, 0, 0); 50 51 return vbo; 52 } 53 54 namespace { 55 56 struct FormatType { 57 GLenum format; 58 GLenum type; 59 }; 60 61 } // anonymous namespace 62 63 // crbug.com/135229 64 // Fails on all Windows platforms and on Linux Intel. 65 #if defined(OS_WIN) || (defined(OS_LINUX) && defined(NDEBUG)) 66 #define MAYBE_RenderTo DISABLED_RenderTo 67 #else 68 #define MAYBE_RenderTo RenderTo 69 #endif 70 71 TEST_F(DepthTextureTest, MAYBE_RenderTo) { 72 if (!GLTestHelper::HasExtension("GL_CHROMIUM_depth_texture")) { 73 return; 74 } 75 76 bool have_depth_stencil = GLTestHelper::HasExtension( 77 "GL_OES_packed_depth_stencil"); 78 79 static const char* v_shader_str = SHADER( 80 attribute vec4 v_position; 81 void main() 82 { 83 gl_Position = v_position; 84 } 85 ); 86 static const char* f_shader_str = SHADER( 87 precision mediump float; 88 uniform sampler2D u_texture; 89 uniform vec2 u_resolution; 90 void main() 91 { 92 vec2 texcoord = gl_FragCoord.xy / u_resolution; 93 gl_FragColor = texture2D(u_texture, texcoord); 94 } 95 ); 96 97 GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str); 98 99 GLint position_loc = glGetAttribLocation(program, "v_position"); 100 GLint resolution_loc = glGetUniformLocation(program, "u_resolution"); 101 102 SetupUnitQuad(position_loc); 103 104 // Depth test needs to be on for the depth buffer to be updated. 105 glEnable(GL_DEPTH_TEST); 106 107 // create an fbo 108 GLuint fbo = 0; 109 glGenFramebuffers(1, &fbo); 110 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 111 112 // create a depth texture. 113 GLuint color_texture = 0; 114 GLuint depth_texture = 0; 115 116 glGenTextures(1, &color_texture); 117 glBindTexture(GL_TEXTURE_2D, color_texture); 118 glTexImage2D( 119 GL_TEXTURE_2D, 0, GL_RGBA, kResolution, kResolution, 120 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 121 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 125 glFramebufferTexture2D( 126 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture, 0); 127 128 glGenTextures(1, &depth_texture); 129 glBindTexture(GL_TEXTURE_2D, depth_texture); 130 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 134 glFramebufferTexture2D( 135 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0); 136 137 glUseProgram(program); 138 glUniform2f(resolution_loc, kResolution, kResolution); 139 140 static const FormatType format_types[] = { 141 { GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, 142 { GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, 143 { GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES }, 144 }; 145 for (size_t ii = 0; ii < arraysize(format_types); ++ii) { 146 const FormatType& format_type = format_types[ii]; 147 GLenum format = format_type.format; 148 GLenum type = format_type.type; 149 150 if (format == GL_DEPTH_STENCIL_OES && !have_depth_stencil) { 151 continue; 152 } 153 154 glBindTexture(GL_TEXTURE_2D, depth_texture); 155 glTexImage2D( 156 GL_TEXTURE_2D, 0, format, kResolution, kResolution, 157 0, format, type, NULL); 158 159 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 160 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 161 EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), status) 162 << "iteration: " << ii; 163 if (status != GL_FRAMEBUFFER_COMPLETE) { 164 continue; 165 } 166 167 if (!GLTestHelper::CheckGLError("no errors after setup", __LINE__)) { 168 continue; 169 } 170 171 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 172 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 173 174 // Disconnect the texture so we'll render with the default texture. 175 glBindTexture(GL_TEXTURE_2D, 0); 176 177 // Render to the fbo. 178 glDrawArrays(GL_TRIANGLES, 0, 6); 179 180 if (!GLTestHelper::CheckGLError("no errors after depth draw", __LINE__)) { 181 continue; 182 } 183 184 // Render with the depth texture. 185 glBindFramebuffer(GL_FRAMEBUFFER, 0); 186 glBindTexture(GL_TEXTURE_2D, depth_texture); 187 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 188 glDrawArrays(GL_TRIANGLES, 0, 6); 189 190 if (!GLTestHelper::CheckGLError("no errors after texture draw", __LINE__)) { 191 continue; 192 } 193 194 uint8 actual_pixels[kResolution * kResolution * 4] = { 0, }; 195 glReadPixels( 196 0, 0, kResolution, kResolution, GL_RGBA, GL_UNSIGNED_BYTE, 197 actual_pixels); 198 199 if (!GLTestHelper::CheckGLError("no errors after readpixels", __LINE__)) { 200 continue; 201 } 202 203 // Check that each pixel's RGB are the same and that it's value is less 204 // than the previous pixel in either direction. Basically verify we have a 205 // gradient. 206 int bad_count = 0; // used to not spam the log with too many messages. 207 for (GLint yy = 0; bad_count < 16 && yy < kResolution; ++yy) { 208 for (GLint xx = 0; bad_count < 16 && xx < kResolution; ++xx) { 209 const uint8* actual = &actual_pixels[(yy * kResolution + xx) * 4]; 210 const uint8* left = actual - 4; 211 const uint8* down = actual - kResolution * 4; 212 213 EXPECT_EQ(actual[0], actual[1]) << "pixel at " << xx << ", " << yy; 214 EXPECT_EQ(actual[1], actual[2]) << "pixel at " << xx << ", " << yy; 215 bad_count += (actual[0] == actual[1] ? 0 : 1); 216 217 // NOTE: Qualcomm on Nexus 4 the right most column has the same 218 // values as the next to right most column. (bad interpolator?) 219 if (xx > 0 && xx < kResolution - 1) { 220 EXPECT_GT(actual[0], left[0]) 221 << "pixel at " << xx << ", " << yy 222 << " actual[0] =" << static_cast<unsigned>(actual[0]) 223 << " left[0] =" << static_cast<unsigned>(left[0]) 224 << " actual =" << reinterpret_cast<const void*>(actual) 225 << " left =" << reinterpret_cast<const void*>(left); 226 bad_count += (actual[0] > left[0] ? 0 : 1); 227 } 228 229 if (yy > 0 && yy < kResolution - 1) { 230 EXPECT_GT(actual[0], down[0]) << "pixel at " << xx << ", " << yy; 231 bad_count += (actual[0] > down[0] ? 0 : 1); 232 } 233 234 EXPECT_TRUE(actual[3] == actual[0] || actual[3] == 0xFF) 235 << "pixel at " << xx << ", " << yy; 236 bad_count += ((actual[3] == actual[0] || actual[3] == 0xFF) ? 0 : 1); 237 } 238 } 239 240 // Check that bottom left corner is vastly different thatn top right. 241 EXPECT_GT( 242 actual_pixels[(kResolution * kResolution - 1) * 4] - actual_pixels[0], 243 0xC0); 244 245 GLTestHelper::CheckGLError("no errors after everything", __LINE__); 246 } 247 } 248 249 } // namespace gpu 250 251 252 253 254