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