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.
6 #include <GLES2/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
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"
14 #define SHADER(src) #src
18 static const uint16 kRedMask
= 0xF800;
19 static const uint16 kGreenMask
= 0x07E0;
20 static const uint16 kBlueMask
= 0x001F;
22 // Color palette in 565 format.
23 static const uint16 kPalette
[] = {
24 kGreenMask
| kBlueMask
, // Cyan.
25 kBlueMask
| kRedMask
, // Magenta.
26 kRedMask
| kGreenMask
, // Yellow.
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
;
38 static const char* extension(GLenum 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";
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;
58 static GLuint
LoadCompressedTexture(const void* data
,
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
);
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.
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
);
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.
108 return LoadCompressedTexture(data
,
110 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
,
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.
132 return LoadCompressedTexture(data
,
134 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
,
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);
149 class CompressedTextureTest
: public ::testing::TestWithParam
<GLenum
> {
151 virtual void SetUp() {
152 GLManager::Options options
;
153 options
.size
= gfx::Size(kTextureWidth
, kTextureHeight
);
154 gl_
.Initialize(options
);
157 virtual void TearDown() {
161 GLuint
LoadProgram() {
162 const char* v_shader_src
= SHADER(
163 attribute vec2 a_position
;
164 varying vec2 v_texcoord
;
166 gl_Position
= vec4(a_position
, 0.0, 1.0);
167 v_texcoord
= (a_position
+ 1.0) * 0.5;
170 const char* f_shader_src
= SHADER(
171 precision mediump
float;
172 uniform sampler2D u_texture
;
173 varying vec2 v_texcoord
;
175 gl_FragColor
= texture2D(u_texture
, v_texcoord
);
178 return GLTestHelper::LoadProgram(v_shader_src
, f_shader_src
);
181 GLuint
LoadTexture(GLenum 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();
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();
203 // This test is only valid if compressed texture extension is supported.
204 const char* ext
= extension(format
);
205 if (!GLTestHelper::HasExtension(ext
))
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
);
218 GLuint vbo
= GLTestHelper::SetupUnitQuad(position_loc
);
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);
229 glDrawArrays(GL_TRIANGLES
, 0, 6);
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
,
242 GLTestHelper::CheckGLError("CompressedTextureTest.Draw", __LINE__
);
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
251 INSTANTIATE_TEST_CASE_P(Format
,
252 CompressedTextureTest
,
253 ::testing::ValuesIn(kFormats
));