Home | History | Annotate | Download | only in tests
      1 // Copyright 2013 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 #include <GLES2/gl2extchromium.h>
      8 
      9 #include "base/basictypes.h"
     10 #include "gpu/command_buffer/tests/gl_manager.h"
     11 #include "gpu/command_buffer/tests/gl_test_utils.h"
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 
     14 #define SHADER(src) #src
     15 
     16 namespace gpu {
     17 
     18 static const uint16 kRedMask = 0xF800;
     19 static const uint16 kGreenMask = 0x07E0;
     20 static const uint16 kBlueMask = 0x001F;
     21 
     22 // Color palette in 565 format.
     23 static const uint16 kPalette[] = {
     24   kGreenMask | kBlueMask,   // Cyan.
     25   kBlueMask  | kRedMask,    // Magenta.
     26   kRedMask   | kGreenMask,  // Yellow.
     27   0x0000,                   // Black.
     28   kRedMask,                 // Red.
     29   kGreenMask,               // Green.
     30   kBlueMask,                // Blue.
     31   0xFFFF,                   // White.
     32 };
     33 static const unsigned kBlockSize = 4;
     34 static const unsigned kPaletteSize = sizeof(kPalette) / sizeof(kPalette[0]);
     35 static const unsigned kTextureWidth = kBlockSize * kPaletteSize;
     36 static const unsigned kTextureHeight = kBlockSize;
     37 
     38 static const char* extension(GLenum format) {
     39   switch(format) {
     40     case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
     41     case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
     42       return "GL_EXT_texture_compression_dxt1";
     43     case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
     44       return "GL_CHROMIUM_texture_compression_dxt3";
     45     case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
     46       return "GL_CHROMIUM_texture_compression_dxt5";
     47     default:
     48       NOTREACHED();
     49   }
     50   return NULL;
     51 }
     52 
     53 // Index that chooses the given colors (color_0 and color_1),
     54 // not the interpolated colors (color_2 and color_3).
     55 static const uint16 kColor0 = 0x0000;
     56 static const uint16 kColor1 = 0x5555;
     57 
     58 static GLuint LoadCompressedTexture(const void* data,
     59                                     GLsizeiptr size,
     60                                     GLenum format,
     61                                     GLsizei width,
     62                                     GLsizei height) {
     63   GLuint texture;
     64   glGenTextures(1, &texture);
     65   glBindTexture(GL_TEXTURE_2D, texture);
     66   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
     67   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
     68   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
     69   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
     70   glCompressedTexImage2D(
     71       GL_TEXTURE_2D, 0, format, width, height, 0, size, data);
     72   return texture;
     73 }
     74 
     75 GLuint LoadTextureDXT1(bool alpha) {
     76   const unsigned kStride = 4;
     77   uint16 data[kStride * kPaletteSize];
     78   for (unsigned i = 0; i < kPaletteSize; ++i) {
     79     // Each iteration defines a 4x4 block of texture.
     80     unsigned j = kStride * i;
     81     data[j++] = kPalette[i];  // color_0.
     82     data[j++] = kPalette[i];  // color_1.
     83     data[j++] = kColor0;  // color index.
     84     data[j++] = kColor1;  // color index.
     85   }
     86   GLenum format = alpha ?
     87       GL_COMPRESSED_RGBA_S3TC_DXT1_EXT : GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
     88   return LoadCompressedTexture(
     89       data, sizeof(data), format, kTextureWidth, kTextureHeight);
     90 }
     91 
     92 GLuint LoadTextureDXT3() {
     93   const unsigned kStride = 8;
     94   const uint16 kOpaque = 0xFFFF;
     95   uint16 data[kStride * kPaletteSize];
     96   for (unsigned i = 0; i < kPaletteSize; ++i) {
     97     // Each iteration defines a 4x4 block of texture.
     98     unsigned j = kStride * i;
     99     data[j++] = kOpaque;  // alpha row 0.
    100     data[j++] = kOpaque;  // alpha row 1.
    101     data[j++] = kOpaque;  // alpha row 2.
    102     data[j++] = kOpaque;  // alpha row 3.
    103     data[j++] = kPalette[i];  // color_0.
    104     data[j++] = kPalette[i];  // color_1.
    105     data[j++] = kColor0;  // color index.
    106     data[j++] = kColor1;  // color index.
    107   }
    108   return LoadCompressedTexture(data,
    109                                sizeof(data),
    110                                GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
    111                                kTextureWidth,
    112                                kTextureHeight);
    113 }
    114 
    115 GLuint LoadTextureDXT5() {
    116   const unsigned kStride = 8;
    117   const uint16 kClear = 0x0000;
    118   const uint16 kAlpha7 = 0xFFFF;  // Opaque alpha index.
    119   uint16 data[kStride * kPaletteSize];
    120   for (unsigned i = 0; i < kPaletteSize; ++i) {
    121     // Each iteration defines a 4x4 block of texture.
    122     unsigned j = kStride * i;
    123     data[j++] = kClear;  // alpha_0 | alpha_1.
    124     data[j++] = kAlpha7;  // alpha index.
    125     data[j++] = kAlpha7;  // alpha index.
    126     data[j++] = kAlpha7;  // alpha index.
    127     data[j++] = kPalette[i];  // color_0.
    128     data[j++] = kPalette[i];  // color_1.
    129     data[j++] = kColor0;  // color index.
    130     data[j++] = kColor1;  // color index.
    131   }
    132   return LoadCompressedTexture(data,
    133                                sizeof(data),
    134                                GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
    135                                kTextureWidth,
    136                                kTextureHeight);
    137 }
    138 
    139 static void ToRGB888(uint16 rgb565, uint8 rgb888[]) {
    140   uint8 r5 = (rgb565 & kRedMask)   >> 11;
    141   uint8 g6 = (rgb565 & kGreenMask) >> 5;
    142   uint8 b5 = (rgb565 & kBlueMask);
    143   // Replicate upper bits to lower empty bits.
    144   rgb888[0] = (r5 << 3) | (r5 >> 2);
    145   rgb888[1] = (g6 << 2) | (g6 >> 4);
    146   rgb888[2] = (b5 << 3) | (b5 >> 2);
    147 }
    148 
    149 class CompressedTextureTest : public ::testing::TestWithParam<GLenum> {
    150  protected:
    151   virtual void SetUp() {
    152     GLManager::Options options;
    153     options.size = gfx::Size(kTextureWidth, kTextureHeight);
    154     gl_.Initialize(options);
    155   }
    156 
    157   virtual void TearDown() {
    158     gl_.Destroy();
    159   }
    160 
    161   GLuint LoadProgram() {
    162     const char* v_shader_src = SHADER(
    163         attribute vec2 a_position;
    164         varying vec2 v_texcoord;
    165         void main() {
    166           gl_Position = vec4(a_position, 0.0, 1.0);
    167           v_texcoord = (a_position + 1.0) * 0.5;
    168         }
    169     );
    170     const char* f_shader_src = SHADER(
    171         precision mediump float;
    172         uniform sampler2D u_texture;
    173         varying vec2 v_texcoord;
    174         void main() {
    175           gl_FragColor = texture2D(u_texture, v_texcoord);
    176         }
    177     );
    178     return GLTestHelper::LoadProgram(v_shader_src, f_shader_src);
    179   }
    180 
    181   GLuint LoadTexture(GLenum format) {
    182     switch (format) {
    183       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return LoadTextureDXT1(false);
    184       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return LoadTextureDXT1(true);
    185       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: return LoadTextureDXT3();
    186       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: return LoadTextureDXT5();
    187       default: NOTREACHED();
    188     }
    189     return 0;
    190   }
    191 
    192  private:
    193   GLManager gl_;
    194 };
    195 
    196 // The test draws a texture in the given format and verifies that the drawn
    197 // pixels are of the same color as the texture.
    198 // The texture consists of 4x4 blocks of texels (same as DXT), one for each
    199 // color defined in kPalette.
    200 TEST_P(CompressedTextureTest, Draw) {
    201   GLenum format = GetParam();
    202 
    203   // This test is only valid if compressed texture extension is supported.
    204   const char* ext = extension(format);
    205   if (!GLTestHelper::HasExtension(ext))
    206     return;
    207 
    208   // Load shader program.
    209   GLuint program = LoadProgram();
    210   ASSERT_NE(program, 0u);
    211   GLint position_loc = glGetAttribLocation(program, "a_position");
    212   GLint texture_loc = glGetUniformLocation(program, "u_texture");
    213   ASSERT_NE(position_loc, -1);
    214   ASSERT_NE(texture_loc, -1);
    215   glUseProgram(program);
    216 
    217   // Load geometry.
    218   GLuint vbo = GLTestHelper::SetupUnitQuad(position_loc);
    219   ASSERT_NE(vbo, 0u);
    220 
    221   // Load texture.
    222   GLuint texture = LoadTexture(format);
    223   ASSERT_NE(texture, 0u);
    224   glActiveTexture(GL_TEXTURE0);
    225   glBindTexture(GL_TEXTURE_2D, texture);
    226   glUniform1i(texture_loc, 0);
    227 
    228   // Draw.
    229   glDrawArrays(GL_TRIANGLES, 0, 6);
    230   glFlush();
    231 
    232   // Verify results.
    233   int origin[] = {0, 0};
    234   uint8 expected_rgba[] = {0, 0, 0, 255};
    235   for (unsigned i = 0; i < kPaletteSize; ++i) {
    236     origin[0] = kBlockSize * i;
    237     ToRGB888(kPalette[i], expected_rgba);
    238     EXPECT_TRUE(GLTestHelper::CheckPixels(origin[0], origin[1],
    239                                           kBlockSize, kBlockSize,
    240                                           0, expected_rgba));
    241   }
    242   GLTestHelper::CheckGLError("CompressedTextureTest.Draw", __LINE__);
    243 }
    244 
    245 static const GLenum kFormats[] = {
    246   GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
    247   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
    248   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
    249   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
    250 };
    251 INSTANTIATE_TEST_CASE_P(Format,
    252                         CompressedTextureTest,
    253                         ::testing::ValuesIn(kFormats));
    254 
    255 }  // namespace gpu
    256