1 // Copyright (c) 2011 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.
5 #include <GLES2/gl2ext.h>
10 // Some tests for compressed textures.
11 #include "gpu/demos/framework/demo_factory.h"
12 #include "gpu/demos/gles2_book/example.h"
20 int g_textureIndex
= 0;
21 int g_numTextures
= 1;
23 int g_textureLoc
= -1;
24 GLuint g_programObject
= 0;
25 GLuint g_worldMatrixLoc
= 0;
27 GLsizei g_texCoordOffset
= 0;
30 void CheckGLError(const char* func_name
, int line_no
) {
32 GLenum error
= GL_NO_ERROR
;
33 while ((error
= glGetError()) != GL_NO_ERROR
) {
34 fprintf(stderr
, "GL ERROR in %s at line %d : 0x%04x\n",
35 func_name
, line_no
, error
);
40 GLuint
LoadShader(GLenum type
, const char* shaderSrc
) {
41 CheckGLError("LoadShader", __LINE__
);
42 GLuint shader
= glCreateShader(type
);
46 // Load the shader source
47 glShaderSource(shader
, 1, &shaderSrc
, NULL
);
49 glCompileShader(shader
);
50 // Check the compile status
52 glGetShaderiv(shader
, GL_COMPILE_STATUS
, &value
);
56 glGetShaderInfoLog(shader
, sizeof(buffer
), &length
, buffer
);
57 std::string
log(buffer
, length
);
58 fprintf(stderr
, "Error compiling shader: %s\n", log
.c_str());
59 glDeleteShader(shader
);
66 static const char* vShaderStr
=
67 "uniform mat4 worldMatrix;\n"
68 "attribute vec3 g_Position;\n"
69 "attribute vec2 g_TexCoord0;\n"
70 "varying vec2 texCoord;\n"
73 " gl_Position = worldMatrix *\n"
74 " vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n"
75 " texCoord = g_TexCoord0;\n"
77 static const char* fShaderStr
=
78 "precision mediump float;"
79 "uniform sampler2D tex;\n"
80 "varying vec2 texCoord;\n"
83 " gl_FragColor = texture2D(tex, texCoord);\n"
86 CheckGLError("InitShaders", __LINE__
);
87 GLuint vertexShader
= LoadShader(GL_VERTEX_SHADER
, vShaderStr
);
88 GLuint fragmentShader
= LoadShader(GL_FRAGMENT_SHADER
, fShaderStr
);
89 // Create the program object
90 GLuint programObject
= glCreateProgram();
91 if (programObject
== 0) {
92 fprintf(stderr
, "Creating program failed\n");
95 glAttachShader(programObject
, vertexShader
);
96 glAttachShader(programObject
, fragmentShader
);
97 // Bind g_Position to attribute 0
98 // Bind g_TexCoord0 to attribute 1
99 glBindAttribLocation(programObject
, 0, "g_Position");
100 glBindAttribLocation(programObject
, 1, "g_TexCoord0");
102 glLinkProgram(programObject
);
103 // Check the link status
105 glGetProgramiv(programObject
, GL_LINK_STATUS
, &linked
);
109 glGetProgramInfoLog(programObject
, sizeof(buffer
), &length
, buffer
);
110 std::string
log(buffer
, length
);
111 fprintf(stderr
, "Error linking program: %s\n", log
.c_str());
112 glDeleteProgram(programObject
);
115 g_programObject
= programObject
;
116 g_worldMatrixLoc
= glGetUniformLocation(g_programObject
, "worldMatrix");
117 g_textureLoc
= glGetUniformLocation(g_programObject
, "tex");
118 glGenBuffers(1, &g_vbo
);
119 glBindBuffer(GL_ARRAY_BUFFER
, g_vbo
);
120 static float vertices
[] = {
128 static float texCoords
[] = {
136 g_texCoordOffset
= sizeof(vertices
);
137 glBufferData(GL_ARRAY_BUFFER
,
138 sizeof(vertices
) + sizeof(texCoords
),
141 glBufferSubData(GL_ARRAY_BUFFER
, 0, sizeof(vertices
), vertices
);
142 glBufferSubData(GL_ARRAY_BUFFER
, g_texCoordOffset
,
143 sizeof(texCoords
), texCoords
);
144 CheckGLError("InitShaders", __LINE__
);
147 GLuint
CreateCheckerboardTexture() {
148 CheckGLError("CreateCheckerboardTexture", __LINE__
);
149 static unsigned char pixels
[] = {
156 glGenTextures(1, &texture
);
157 glBindTexture(GL_TEXTURE_2D
, texture
);
158 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
159 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
160 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
161 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
162 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
163 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, 2, 2, 0, GL_RGB
, GL_UNSIGNED_BYTE
,
165 CheckGLError("CreateCheckerboardTexture", __LINE__
);
169 GLuint
CreateCompressedTexture(
176 glGenTextures(1, &texture
);
177 glBindTexture(GL_TEXTURE_2D
, texture
);
178 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
179 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
180 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
181 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
182 glCompressedTexImage2D(
183 GL_TEXTURE_2D
, 0, format
, width
, height
, 0, size
, data
);
184 CheckGLError("CreateCompressedTxture", __LINE__
);
188 GLuint
LoadDXT1RGBTexture() {
189 static unsigned char data
[] = {
190 0x00, 0xd0, 0x00, 0xef, 0x00, 0xaa, 0x95, 0xd5,
191 0x00, 0x90, 0x57, 0xff, 0x00, 0xaa, 0xff, 0x55,
192 0x00, 0x88, 0x99, 0xff, 0x00, 0xaa, 0xff, 0x55,
193 0x20, 0xb8, 0xe4, 0xf6, 0x00, 0xaa, 0x5b, 0x5d,
194 0x21, 0x09, 0xe6, 0x27, 0x15, 0x15, 0x15, 0x15,
195 0xd7, 0xbd, 0xff, 0xff, 0x56, 0x16, 0x16, 0x56,
196 0x00, 0x00, 0xff, 0xff, 0x55, 0x00, 0x00, 0x55,
197 0xe0, 0x08, 0xa9, 0x2f, 0x51, 0x58, 0x56, 0x54,
198 0xff, 0x07, 0x15, 0x09, 0x40, 0x6a, 0xd5, 0xd5,
199 0xd7, 0xbd, 0xff, 0xff, 0x56, 0x16, 0x16, 0x16,
200 0x91, 0x08, 0xff, 0xff, 0x55, 0xff, 0x00, 0x03,
201 0xfe, 0x07, 0x5b, 0x09, 0x01, 0xa9, 0x55, 0xff,
202 0x0d, 0x10, 0x18, 0xe8, 0xea, 0x15, 0x95, 0x55,
203 0x08, 0x88, 0x3c, 0xe7, 0x55, 0x55, 0xff, 0x00,
204 0x10, 0x20, 0x18, 0xe8, 0xa8, 0x54, 0x56, 0x55,
205 0x1f, 0x78, 0x15, 0xf8, 0x00, 0xaa, 0x55, 0x55,
207 return CreateCompressedTexture(
208 data
, sizeof(data
), GL_COMPRESSED_RGB_S3TC_DXT1_EXT
, 16, 16);
211 GLuint
LoadDXT1RGBATexture() {
212 static unsigned char data
[] = {
213 0xff, 0xff, 0x90, 0xee, 0x00, 0xaa, 0xff, 0x55,
214 0x53, 0xde, 0xdd, 0xff, 0x55, 0x55, 0x00, 0xff,
215 0xc9, 0xb4, 0xdd, 0xff, 0x55, 0x55, 0xaa, 0xff,
216 0x6f, 0xee, 0xdd, 0xff, 0x55, 0x55, 0xa8, 0x03,
217 0x60, 0xa3, 0xa5, 0xe5, 0x55, 0x55, 0xaa, 0x00,
218 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
219 0x80, 0xab, 0xc2, 0xc4, 0xff, 0x55, 0xaa, 0xff,
220 0x60, 0x9b, 0xa5, 0xe5, 0x57, 0x56, 0xaa, 0x00,
221 0x1f, 0xbf, 0xff, 0xf7, 0x55, 0x55, 0xaa, 0x00,
222 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff,
223 0xfe, 0xbe, 0x7e, 0xdf, 0xff, 0xaa, 0x55, 0x00,
224 0xfe, 0xbe, 0xff, 0xf7, 0x54, 0x56, 0xaa, 0x00,
225 0xfa, 0x4c, 0x7e, 0x9e, 0x55, 0xaa, 0x00, 0x00,
226 0xbb, 0x2c, 0x98, 0x54, 0xff, 0xff, 0x55, 0xaa,
227 0xfa, 0x4c, 0x7e, 0x9e, 0x55, 0xaa, 0x00, 0x00,
228 0xfa, 0x4c, 0x7e, 0x9e, 0x55, 0xaa, 0x00, 0x00,
230 return CreateCompressedTexture(
231 data
, sizeof(data
), GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
, 16, 16);
234 GLuint
LoadDXT3RGBATexture() {
235 static unsigned char data
[] = {
236 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
237 0xa3, 0x22, 0x03, 0x03, 0x55, 0xff, 0xaa, 0x00,
238 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
239 0xcf, 0x7c, 0xc3, 0x12, 0x55, 0x55, 0x55, 0x54,
240 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
241 0x83, 0x1a, 0x03, 0x03, 0x55, 0xff, 0x00, 0x00,
242 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff,
243 0xcf, 0x7c, 0xc3, 0x12, 0x55, 0x55, 0x55, 0x54,
244 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
245 0xc3, 0x59, 0x63, 0x32, 0x55, 0xff, 0xaa, 0x00,
246 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00,
247 0x8f, 0x94, 0x03, 0x4a, 0x54, 0x94, 0x94, 0x54,
248 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
249 0xa3, 0x59, 0x43, 0x2a, 0x55, 0xff, 0xaa, 0x00,
250 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff,
251 0xaf, 0x84, 0x03, 0x42, 0x54, 0x55, 0x55, 0x55,
252 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
253 0xc3, 0xa0, 0x83, 0x71, 0x55, 0xff, 0xaa, 0x00,
254 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40,
255 0x0f, 0xb4, 0x43, 0x81, 0x54, 0x94, 0x94, 0x94,
256 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
257 0xc3, 0xa0, 0x83, 0x69, 0x55, 0xff, 0xaa, 0x00,
258 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
259 0xc3, 0xa0, 0x83, 0x69, 0x55, 0xfd, 0xaa, 0x00,
260 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
261 0x23, 0xd0, 0xa3, 0xb0, 0x55, 0xff, 0xaa, 0x00,
262 0x00, 0x40, 0x00, 0x40, 0xff, 0xff, 0xff, 0xff,
263 0xf0, 0xc3, 0x43, 0xc0, 0x94, 0x94, 0x55, 0x55,
264 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
265 0x23, 0xd0, 0xa3, 0xb0, 0x55, 0xff, 0xaa, 0x00,
266 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
267 0x23, 0xd0, 0xa3, 0xb0, 0x55, 0xff, 0xaa, 0x00,
269 return CreateCompressedTexture(
270 data
, sizeof(data
), GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
, 16, 16);
273 GLuint
LoadDXT5RGBATexture() {
274 static unsigned char data
[] = {
275 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x72, 0xdd, 0x03, 0x92, 0x2d, 0x2d, 0x2d, 0x2d,
277 0x04, 0xfb, 0xff, 0xff, 0xff, 0x49, 0x02, 0xdb,
278 0x97, 0xf6, 0x32, 0xcd, 0xc0, 0xc0, 0x7b, 0xc0,
279 0xfb, 0xff, 0x49, 0x92, 0x24, 0x00, 0x60, 0xdb,
280 0x11, 0xcd, 0x67, 0x82, 0x78, 0x78, 0x5e, 0x78,
281 0x04, 0xfb, 0xff, 0xff, 0xff, 0xf9, 0x8f, 0xff,
282 0x2e, 0xac, 0xc4, 0x71, 0x15, 0x15, 0x15, 0x14,
283 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
284 0x72, 0xdd, 0x03, 0x92, 0x2d, 0x2d, 0x2d, 0x2d,
285 0x04, 0x43, 0xb0, 0x0d, 0x3b, 0xb0, 0x03, 0xdb,
286 0xb8, 0xf6, 0xd5, 0xd5, 0x60, 0x60, 0x60, 0x60,
287 0xfb, 0x00, 0x49, 0x02, 0x00, 0x00, 0x90, 0x24,
288 0xb0, 0xbc, 0x26, 0x7a, 0x78, 0x78, 0x78, 0x78,
289 0x04, 0xf7, 0xf8, 0x9f, 0xff, 0xf9, 0x9f, 0xff,
290 0x0e, 0xac, 0x83, 0x69, 0x34, 0x35, 0x35, 0x35,
291 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
292 0x72, 0xdd, 0x03, 0x92, 0x2d, 0x2d, 0x2d, 0x2d,
293 0x04, 0x43, 0xb0, 0x0d, 0x3b, 0xb0, 0x03, 0x3b,
294 0xb8, 0xf6, 0xd5, 0xd5, 0x60, 0x60, 0x60, 0x60,
295 0xfb, 0xff, 0xb6, 0x0d, 0x00, 0x49, 0x92, 0x24,
296 0x11, 0xcd, 0x67, 0x82, 0x78, 0x5e, 0x78, 0x78,
297 0xea, 0xff, 0x4a, 0xd2, 0x24, 0x49, 0x92, 0x24,
298 0x0e, 0xac, 0xc4, 0x71, 0x15, 0x15, 0x15, 0x15,
299 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x72, 0xdd, 0x03, 0x92, 0x2d, 0x2d, 0x2d, 0x2d,
301 0xfd, 0x00, 0x49, 0x9c, 0xc4, 0x00, 0x00, 0x00,
302 0xb8, 0xf6, 0x53, 0xcd, 0xe0, 0xe0, 0x7f, 0xe0,
303 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0xf1, 0xcc, 0x46, 0x82, 0x78, 0x78, 0x78, 0x78,
305 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 0x0e, 0xac, 0xc4, 0x71, 0x15, 0x15, 0x15, 0x15,
308 return CreateCompressedTexture(
309 data
, sizeof(data
), GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
, 16, 16);
312 } // anonymous namespace.
314 static int stInit(ESContext
*esContext
) {
315 CheckGLError("GLFromCPPInit", __LINE__
);
316 g_textures
[0] = CreateCheckerboardTexture();
317 glClearColor(0.f
, 0.f
, .7f
, 1.f
);
318 const char* extensions
=
319 reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS
));
320 if (strstr(extensions
, "GL_EXT_texture_compression_dxt1")) {
321 g_textures
[g_numTextures
++] = LoadDXT1RGBTexture();
322 g_textures
[g_numTextures
++] = LoadDXT1RGBATexture();
324 if (strstr(extensions
, "GL_CHROMIUM_texture_compression_dxt3")) {
325 g_textures
[g_numTextures
++] = LoadDXT3RGBATexture();
327 if (strstr(extensions
, "GL_CHROMIUM_texture_compression_dxt5")) {
328 g_textures
[g_numTextures
++] = LoadDXT5RGBATexture();
331 CheckGLError("GLFromCPPInit", __LINE__
);
335 static void stDraw (ESContext
*esContext
) {
336 const float kPi
= 3.1415926535897932384626433832795f
;
338 CheckGLError("GLFromCPPDraw", __LINE__
);
339 // TODO(kbr): base the angle on time rather than on ticks
340 g_angle
= (g_angle
+ 1) % 360;
341 // Rotate about the Z axis
342 GLfloat rot_matrix
[16];
343 GLfloat cos_angle
= cosf(static_cast<GLfloat
>(g_angle
) * kPi
/ 180.0f
);
344 GLfloat sin_angle
= sinf(static_cast<GLfloat
>(g_angle
) * kPi
/ 180.0f
);
345 // OpenGL matrices are column-major
346 rot_matrix
[0] = cos_angle
;
347 rot_matrix
[1] = sin_angle
;
348 rot_matrix
[2] = 0.0f
;
349 rot_matrix
[3] = 0.0f
;
351 rot_matrix
[4] = -sin_angle
;
352 rot_matrix
[5] = cos_angle
;
353 rot_matrix
[6] = 0.0f
;
354 rot_matrix
[7] = 0.0f
;
356 rot_matrix
[8] = 0.0f
;
357 rot_matrix
[9] = 0.0f
;
358 rot_matrix
[10] = 1.0f
;
359 rot_matrix
[11] = 0.0f
;
361 rot_matrix
[12] = 0.0f
;
362 rot_matrix
[13] = 0.0f
;
363 rot_matrix
[14] = 0.0f
;
364 rot_matrix
[15] = 1.0f
;
367 if (g_frameCount
> 60)
370 g_textureIndex
= (g_textureIndex
+ 1) % g_numTextures
;
373 // Note: the viewport is automatically set up to cover the entire Canvas.
374 // Clear the color buffer
375 glClear(GL_COLOR_BUFFER_BIT
);
377 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
378 CheckGLError("GLFromCPPDraw", __LINE__
);
379 // Use the program object
380 glUseProgram(g_programObject
);
381 CheckGLError("GLFromCPPDraw", __LINE__
);
382 // Set up the model matrix
383 glUniformMatrix4fv(g_worldMatrixLoc
, 1, GL_FALSE
, rot_matrix
);
385 // Load the vertex data
386 glBindBuffer(GL_ARRAY_BUFFER
, g_vbo
);
387 glEnableVertexAttribArray(0);
388 glVertexAttribPointer(0, 3, GL_FLOAT
, GL_FALSE
, 0, 0);
389 glEnableVertexAttribArray(1);
390 glVertexAttribPointer(1, 2, GL_FLOAT
, GL_FALSE
, 0,
391 reinterpret_cast<const void*>(g_texCoordOffset
));
392 CheckGLError("GLFromCPPDraw", __LINE__
);
393 // Bind the texture to texture unit 0
394 glBindTexture(GL_TEXTURE_2D
, g_textures
[g_textureIndex
]);
395 CheckGLError("GLFromCPPDraw", __LINE__
);
396 // Point the uniform sampler to texture unit 0
397 glUniform1i(g_textureLoc
, 0);
398 CheckGLError("GLFromCPPDraw", __LINE__
);
399 glDrawArrays(GL_TRIANGLES
, 0, 6);
400 CheckGLError("GLFromCPPDraw", __LINE__
);
404 static void stShutDown (ESContext
*esContext
) {
411 class CompressedTextureTest
: public gles2_book::Example
<STUserData
> {
413 CompressedTextureTest() {
414 RegisterCallbacks(stInit
, NULL
, stDraw
, stShutDown
);
417 const wchar_t* Title() const {
418 return L
"Compressed Texture Test";
427 return new CompressedTextureTest();