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