Merge commit 'origin/gallium-0.1' into gallium-tex-surfaces
[mesa.git] / progs / tests / manytex.c
1 /* $Id: manytex.c,v 1.5 2005/09/15 01:58:39 brianp Exp $ */
2
3 /*
4 * test handling of many texture maps
5 * Also tests texture priority and residency.
6 *
7 * Brian Paul
8 * August 2, 2000
9 */
10
11
12 #include <assert.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <math.h>
17 #include <GL/glut.h>
18
19
20 static GLint NumTextures = 20;
21 static GLuint *TextureID = NULL;
22 static GLint *TextureWidth = NULL, *TextureHeight = NULL;
23 static GLboolean *TextureResidency = NULL;
24 static GLint TexWidth = 128, TexHeight = 128;
25 static GLfloat Zrot = 0;
26 static GLboolean Anim = GL_TRUE;
27 static GLint WinWidth = 500, WinHeight = 400;
28 static GLboolean MipMap = GL_FALSE;
29 static GLboolean LinearFilter = GL_FALSE;
30 static GLboolean RandomSize = GL_FALSE;
31 static GLint Rows, Columns;
32 static GLint LowPriorityCount = 0;
33 static GLint Win;
34
35
36 static void Idle( void )
37 {
38 Zrot += 1.0;
39 glutPostRedisplay();
40 }
41
42
43 static void Display( void )
44 {
45 GLfloat spacing = WinWidth / Columns;
46 GLfloat size = spacing * 0.4;
47 GLint i;
48
49 /* test residency */
50 if (0)
51 {
52 GLboolean b;
53 GLint i, resident;
54 b = glAreTexturesResident(NumTextures, TextureID, TextureResidency);
55 if (b) {
56 printf("all resident\n");
57 }
58 else {
59 resident = 0;
60 for (i = 0; i < NumTextures; i++) {
61 if (TextureResidency[i]) {
62 resident++;
63 }
64 }
65 printf("%d of %d texture resident\n", resident, NumTextures);
66 }
67 }
68
69 /* render the textured quads */
70 glClear( GL_COLOR_BUFFER_BIT );
71 for (i = 0; i < NumTextures; i++) {
72 GLint row = i / Columns;
73 GLint col = i % Columns;
74 GLfloat x = col * spacing + spacing * 0.5;
75 GLfloat y = row * spacing + spacing * 0.5;
76
77 GLfloat maxDim = (TextureWidth[i] > TextureHeight[i])
78 ? TextureWidth[i] : TextureHeight[i];
79 GLfloat w = TextureWidth[i] / maxDim;
80 GLfloat h = TextureHeight[i] / maxDim;
81
82 glPushMatrix();
83 glTranslatef(x, y, 0.0);
84 glRotatef(Zrot, 0, 0, 1);
85 glScalef(size, size, 1);
86
87 glBindTexture(GL_TEXTURE_2D, TextureID[i]);
88 glBegin(GL_POLYGON);
89 #if 0
90 glTexCoord2f(0, 0); glVertex2f(-1, -1);
91 glTexCoord2f(1, 0); glVertex2f( 1, -1);
92 glTexCoord2f(1, 1); glVertex2f( 1, 1);
93 glTexCoord2f(0, 1); glVertex2f(-1, 1);
94 #else
95 glTexCoord2f(0, 0); glVertex2f(-w, -h);
96 glTexCoord2f(1, 0); glVertex2f( w, -h);
97 glTexCoord2f(1, 1); glVertex2f( w, h);
98 glTexCoord2f(0, 1); glVertex2f(-w, h);
99 #endif
100 glEnd();
101 glPopMatrix();
102 }
103
104 glutSwapBuffers();
105 }
106
107
108 static void Reshape( int width, int height )
109 {
110 WinWidth = width;
111 WinHeight = height;
112 glViewport( 0, 0, width, height );
113 glMatrixMode( GL_PROJECTION );
114 glLoadIdentity();
115 glOrtho(0, width, 0, height, -1, 1);
116 glMatrixMode( GL_MODELVIEW );
117 glLoadIdentity();
118 }
119
120
121 /*
122 * Return a random int in [min, max].
123 */
124 static int RandomInt(int min, int max)
125 {
126 int i = rand();
127 int j = i % (max - min + 1);
128 return min + j;
129 }
130
131
132 static void DeleteTextures(void)
133 {
134 glDeleteTextures(NumTextures, TextureID);
135 free(TextureID);
136 TextureID = NULL;
137 }
138
139
140
141 static void Init( void )
142 {
143 GLint i;
144
145 if (RandomSize) {
146 printf("Creating %d %s random-size textures, ", NumTextures,
147 MipMap ? "Mipmapped" : "non-Mipmapped");
148 }
149 else {
150 printf("Creating %d %s %d x %d textures, ", NumTextures,
151 MipMap ? "Mipmapped" : "non-Mipmapped",
152 TexWidth, TexHeight);
153 }
154
155 if (LinearFilter) {
156 printf("bilinear filtering\n");
157 }
158 else {
159 printf("nearest filtering\n");
160 }
161
162
163 /* compute number of rows and columns of rects */
164 {
165 GLfloat area = (GLfloat) (WinWidth * WinHeight) / (GLfloat) NumTextures;
166 GLfloat edgeLen = sqrt(area);
167
168 Columns = WinWidth / edgeLen;
169 Rows = (NumTextures + Columns - 1) / Columns;
170 printf("Rows: %d Cols: %d\n", Rows, Columns);
171 }
172
173
174 if (!TextureID) {
175 TextureID = (GLuint *) malloc(sizeof(GLuint) * NumTextures);
176 assert(TextureID);
177 glGenTextures(NumTextures, TextureID);
178 }
179
180 if (!TextureResidency) {
181 TextureResidency = (GLboolean *) malloc(sizeof(GLboolean) * NumTextures);
182 assert(TextureResidency);
183 }
184
185 if (!TextureWidth) {
186 TextureWidth = (GLint *) malloc(sizeof(GLint) * NumTextures);
187 assert(TextureWidth);
188 }
189 if (!TextureHeight) {
190 TextureHeight = (GLint *) malloc(sizeof(GLint) * NumTextures);
191 assert(TextureHeight);
192 }
193
194 for (i = 0; i < NumTextures; i++) {
195 GLubyte color[4];
196 GLubyte *texImage;
197 GLint j, row, col;
198
199 row = i / Columns;
200 col = i % Columns;
201
202 glBindTexture(GL_TEXTURE_2D, TextureID[i]);
203
204 if (i < LowPriorityCount)
205 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5F);
206
207 if (RandomSize) {
208 #if 0
209 int k = (glutGet(GLUT_ELAPSED_TIME) % 7) + 2;
210 TexWidth = 1 << k;
211 TexHeight = 1 << k;
212 #else
213 TexWidth = 1 << RandomInt(2, 7);
214 TexHeight = 1 << RandomInt(2, 7);
215 printf("Random size of %3d: %d x %d\n", i, TexWidth, TexHeight);
216 #endif
217 }
218
219 TextureWidth[i] = TexWidth;
220 TextureHeight[i] = TexHeight;
221
222 texImage = (GLubyte*) malloc(4 * TexWidth * TexHeight * sizeof(GLubyte));
223 assert(texImage);
224
225 /* determine texture color */
226 color[0] = (GLint) (255.0 * ((float) col / (Columns - 1)));
227 color[1] = 127;
228 color[2] = (GLint) (255.0 * ((float) row / (Rows - 1)));
229 color[3] = 255;
230
231 /* fill in solid-colored teximage */
232 for (j = 0; j < TexWidth * TexHeight; j++) {
233 texImage[j*4+0] = color[0];
234 texImage[j*4+1] = color[1];
235 texImage[j*4+2] = color[2];
236 texImage[j*4+3] = color[3];
237 }
238
239 if (MipMap) {
240 GLint level = 0;
241 GLint w = TexWidth, h = TexHeight;
242 while (1) {
243 glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0,
244 GL_RGBA, GL_UNSIGNED_BYTE, texImage);
245 if (w == 1 && h == 1)
246 break;
247 if (w > 1)
248 w /= 2;
249 if (h > 1)
250 h /= 2;
251 level++;
252 /*printf("%d: %d x %d\n", level, w, h);*/
253 }
254 if (LinearFilter) {
255 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
256 GL_LINEAR_MIPMAP_LINEAR);
257 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
258 }
259 else {
260 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
261 GL_NEAREST_MIPMAP_NEAREST);
262 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
263 }
264 }
265 else {
266 /* Set corners to white */
267 int k = 0;
268 texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
269 k = (TexWidth - 1) * 4;
270 texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
271 k = (TexWidth * TexHeight - TexWidth) * 4;
272 texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
273 k = (TexWidth * TexHeight - 1) * 4;
274 texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
275
276 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
277 GL_RGBA, GL_UNSIGNED_BYTE, texImage);
278 if (LinearFilter) {
279 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
280 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
281 }
282 else {
283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285 }
286 }
287
288 free(texImage);
289 }
290
291 glEnable(GL_TEXTURE_2D);
292 }
293
294
295 static void Key( unsigned char key, int x, int y )
296 {
297 const GLfloat step = 3.0;
298 (void) x;
299 (void) y;
300 switch (key) {
301 case 'a':
302 Anim = !Anim;
303 if (Anim)
304 glutIdleFunc(Idle);
305 else
306 glutIdleFunc(NULL);
307 break;
308 case 's':
309 Idle();
310 break;
311 case 'z':
312 Zrot -= step;
313 break;
314 case 'Z':
315 Zrot += step;
316 break;
317 case ' ':
318 DeleteTextures();
319 Init();
320 break;
321 case 27:
322 DeleteTextures();
323 glutDestroyWindow(Win);
324 exit(0);
325 break;
326 }
327 glutPostRedisplay();
328 }
329
330
331 int main( int argc, char *argv[] )
332 {
333 GLint i;
334
335 glutInit( &argc, argv );
336 glutInitWindowPosition( 0, 0 );
337 glutInitWindowSize( WinWidth, WinHeight );
338 glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
339 Win = glutCreateWindow(argv[0]);
340 glutReshapeFunc( Reshape );
341 glutKeyboardFunc( Key );
342 glutDisplayFunc( Display );
343 if (Anim)
344 glutIdleFunc(Idle);
345
346 for (i = 1; i < argc; i++) {
347 if (strcmp(argv[i], "-n") == 0) {
348 NumTextures = atoi(argv[i+1]);
349 if (NumTextures <= 0) {
350 printf("Error, bad number of textures\n");
351 return 1;
352 }
353 i++;
354 }
355 else if (strcmp(argv[i], "-mipmap") == 0) {
356 MipMap = GL_TRUE;
357 }
358 else if (strcmp(argv[i], "-linear") == 0) {
359 LinearFilter = GL_TRUE;
360 }
361 else if (strcmp(argv[i], "-size") == 0) {
362 TexWidth = atoi(argv[i+1]);
363 TexHeight = atoi(argv[i+2]);
364 assert(TexWidth >= 1);
365 assert(TexHeight >= 1);
366 i += 2;
367 }
368 else if (strcmp(argv[i], "-randomsize") == 0) {
369 RandomSize = GL_TRUE;
370 }
371 else if (strcmp(argv[i], "-lowpri") == 0) {
372 LowPriorityCount = atoi(argv[i+1]);
373 i++;
374 }
375 else {
376 printf("Usage:\n");
377 printf(" manytex [options]\n");
378 printf("Options:\n");
379 printf(" -n <number of texture objects>\n");
380 printf(" -size <width> <height> - specify texture size\n");
381 printf(" -randomsize - use random size textures\n");
382 printf(" -mipmap - generate mipmaps\n");
383 printf(" -linear - use linear filtering instead of nearest\n");
384 printf(" -lowpri <n> - Set lower priority on <n> textures\n");
385 return 0;
386 }
387 }
388
389 Init();
390
391 glutMainLoop();
392
393 return 0;
394 }