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 15namespace gpu { 16 17class 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 35GLuint 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 54namespace { 55 56struct FormatType { 57 GLenum format; 58 GLenum type; 59}; 60 61} // anonymous namespace 62 63TEST_F(DepthTextureTest, RenderTo) { 64 if (!GLTestHelper::HasExtension("GL_CHROMIUM_depth_texture")) { 65 return; 66 } 67 68 bool have_depth_stencil = GLTestHelper::HasExtension( 69 "GL_OES_packed_depth_stencil"); 70 71 static const char* v_shader_str = SHADER( 72 attribute vec4 v_position; 73 void main() 74 { 75 gl_Position = v_position; 76 } 77 ); 78 static const char* f_shader_str = SHADER( 79 precision mediump float; 80 uniform sampler2D u_texture; 81 uniform vec2 u_resolution; 82 void main() 83 { 84 vec2 texcoord = gl_FragCoord.xy / u_resolution; 85 gl_FragColor = texture2D(u_texture, texcoord); 86 } 87 ); 88 89 GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str); 90 91 GLint position_loc = glGetAttribLocation(program, "v_position"); 92 GLint resolution_loc = glGetUniformLocation(program, "u_resolution"); 93 94 SetupUnitQuad(position_loc); 95 96 // Depth test needs to be on for the depth buffer to be updated. 97 glEnable(GL_DEPTH_TEST); 98 99 // create an fbo 100 GLuint fbo = 0; 101 glGenFramebuffers(1, &fbo); 102 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 103 104 // create a depth texture. 105 GLuint color_texture = 0; 106 GLuint depth_texture = 0; 107 108 glGenTextures(1, &color_texture); 109 glBindTexture(GL_TEXTURE_2D, color_texture); 110 glTexImage2D( 111 GL_TEXTURE_2D, 0, GL_RGBA, kResolution, kResolution, 112 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 113 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 114 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 115 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 117 glFramebufferTexture2D( 118 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_texture, 0); 119 120 glGenTextures(1, &depth_texture); 121 glBindTexture(GL_TEXTURE_2D, depth_texture); 122 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 123 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 124 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 125 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 126 glFramebufferTexture2D( 127 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth_texture, 0); 128 129 glUseProgram(program); 130 glUniform2f(resolution_loc, kResolution, kResolution); 131 132 static const FormatType format_types[] = { 133 { GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT }, 134 { GL_DEPTH_COMPONENT, GL_UNSIGNED_INT }, 135 { GL_DEPTH_STENCIL_OES, GL_UNSIGNED_INT_24_8_OES }, 136 }; 137 for (size_t ii = 0; ii < arraysize(format_types); ++ii) { 138 const FormatType& format_type = format_types[ii]; 139 GLenum format = format_type.format; 140 GLenum type = format_type.type; 141 142 if (format == GL_DEPTH_STENCIL_OES && !have_depth_stencil) { 143 continue; 144 } 145 146 glBindTexture(GL_TEXTURE_2D, depth_texture); 147 glTexImage2D( 148 GL_TEXTURE_2D, 0, format, kResolution, kResolution, 149 0, format, type, NULL); 150 151 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 152 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 153 EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), status) 154 << "iteration: " << ii; 155 if (status != GL_FRAMEBUFFER_COMPLETE) { 156 continue; 157 } 158 159 if (!GLTestHelper::CheckGLError("no errors after setup", __LINE__)) { 160 continue; 161 } 162 163 glClearColor(1.0f, 1.0f, 1.0f, 1.0f); 164 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 165 166 // Disconnect the texture so we'll render with the default texture. 167 glBindTexture(GL_TEXTURE_2D, 0); 168 169 // Render to the fbo. 170 glDrawArrays(GL_TRIANGLES, 0, 6); 171 172 if (!GLTestHelper::CheckGLError("no errors after depth draw", __LINE__)) { 173 continue; 174 } 175 176 // Render with the depth texture. 177 glBindFramebuffer(GL_FRAMEBUFFER, 0); 178 glBindTexture(GL_TEXTURE_2D, depth_texture); 179 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 180 glDrawArrays(GL_TRIANGLES, 0, 6); 181 182 if (!GLTestHelper::CheckGLError("no errors after texture draw", __LINE__)) { 183 continue; 184 } 185 186 uint8 actual_pixels[kResolution * kResolution * 4] = { 0, }; 187 glReadPixels( 188 0, 0, kResolution, kResolution, GL_RGBA, GL_UNSIGNED_BYTE, 189 actual_pixels); 190 191 if (!GLTestHelper::CheckGLError("no errors after readpixels", __LINE__)) { 192 continue; 193 } 194 195 // Check that each pixel's red value is less than the previous pixel in 196 // either direction. Basically verify we have a gradient. No assumption is 197 // made about the other channels green, blue and alpha since, according to 198 // the GL_CHROMIUM_depth_texture spec, they have undefined values for 199 // depth textures. 200 int bad_count = 0; // used to not spam the log with too many messages. 201 for (GLint yy = 0; bad_count < 16 && yy < kResolution; ++yy) { 202 for (GLint xx = 0; bad_count < 16 && xx < kResolution; ++xx) { 203 const uint8* actual = &actual_pixels[(yy * kResolution + xx) * 4]; 204 const uint8* left = actual - 4; 205 const uint8* down = actual - kResolution * 4; 206 207 // NOTE: Qualcomm on Nexus 4 the right most column has the same 208 // values as the next to right most column. (bad interpolator?) 209 if (xx > 0 && xx < kResolution - 1) { 210 EXPECT_GT(actual[0], left[0]) 211 << "pixel at " << xx << ", " << yy 212 << " actual[0] =" << static_cast<unsigned>(actual[0]) 213 << " left[0] =" << static_cast<unsigned>(left[0]) 214 << " actual =" << reinterpret_cast<const void*>(actual) 215 << " left =" << reinterpret_cast<const void*>(left); 216 bad_count += (actual[0] > left[0] ? 0 : 1); 217 } 218 219 if (yy > 0 && yy < kResolution - 1) { 220 EXPECT_GT(actual[0], down[0]) << "pixel at " << xx << ", " << yy; 221 bad_count += (actual[0] > down[0] ? 0 : 1); 222 } 223 } 224 } 225 226 // Check that bottom left corner is vastly different thatn top right. 227 EXPECT_GT( 228 actual_pixels[(kResolution * kResolution - 1) * 4] - actual_pixels[0], 229 0xC0); 230 231 GLTestHelper::CheckGLError("no errors after everything", __LINE__); 232 } 233} 234 235} // namespace gpu 236 237 238 239 240