compressed_texture_test.cc 8.4 KB

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