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 void SetUp() override
{
152 GLManager::Options options
;
153 options
.size
= gfx::Size(kTextureWidth
, kTextureHeight
);
154 gl_
.Initialize(options
);
157 void TearDown() override
{ gl_
.Destroy(); }
159 GLuint
LoadProgram() {
160 const char* v_shader_src
= SHADER(
161 attribute vec2 a_position
;
162 varying vec2 v_texcoord
;
164 gl_Position
= vec4(a_position
, 0.0, 1.0);
165 v_texcoord
= (a_position
+ 1.0) * 0.5;
168 const char* f_shader_src
= SHADER(
169 precision mediump
float;
170 uniform sampler2D u_texture
;
171 varying vec2 v_texcoord
;
173 gl_FragColor
= texture2D(u_texture
, v_texcoord
);
176 return GLTestHelper::LoadProgram(v_shader_src
, f_shader_src
);
179 GLuint
LoadTexture(GLenum format
) {
181 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
: return LoadTextureDXT1(false);
182 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
: return LoadTextureDXT1(true);
183 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
: return LoadTextureDXT3();
184 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
: return LoadTextureDXT5();
185 default: NOTREACHED();
194 // The test draws a texture in the given format and verifies that the drawn
195 // pixels are of the same color as the texture.
196 // The texture consists of 4x4 blocks of texels (same as DXT), one for each
197 // color defined in kPalette.
198 TEST_P(CompressedTextureTest
, Draw
) {
199 GLenum format
= GetParam();
201 // This test is only valid if compressed texture extension is supported.
202 const char* ext
= extension(format
);
203 if (!GLTestHelper::HasExtension(ext
))
206 // Load shader program.
207 GLuint program
= LoadProgram();
208 ASSERT_NE(program
, 0u);
209 GLint position_loc
= glGetAttribLocation(program
, "a_position");
210 GLint texture_loc
= glGetUniformLocation(program
, "u_texture");
211 ASSERT_NE(position_loc
, -1);
212 ASSERT_NE(texture_loc
, -1);
213 glUseProgram(program
);
216 GLuint vbo
= GLTestHelper::SetupUnitQuad(position_loc
);
220 GLuint texture
= LoadTexture(format
);
221 ASSERT_NE(texture
, 0u);
222 glActiveTexture(GL_TEXTURE0
);
223 glBindTexture(GL_TEXTURE_2D
, texture
);
224 glUniform1i(texture_loc
, 0);
227 glDrawArrays(GL_TRIANGLES
, 0, 6);
231 int origin
[] = {0, 0};
232 uint8 expected_rgba
[] = {0, 0, 0, 255};
233 for (unsigned i
= 0; i
< kPaletteSize
; ++i
) {
234 origin
[0] = kBlockSize
* i
;
235 ToRGB888(kPalette
[i
], expected_rgba
);
236 EXPECT_TRUE(GLTestHelper::CheckPixels(origin
[0], origin
[1],
237 kBlockSize
, kBlockSize
,
240 GLTestHelper::CheckGLError("CompressedTextureTest.Draw", __LINE__
);
243 static const GLenum kFormats
[] = {
244 GL_COMPRESSED_RGB_S3TC_DXT1_EXT
,
245 GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
,
246 GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
,
247 GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
249 INSTANTIATE_TEST_CASE_P(Format
,
250 CompressedTextureTest
,
251 ::testing::ValuesIn(kFormats
));