Home | History | Annotate | Download | only in tests
      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 TEST_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