132001f49Smrg
232001f49Smrg/*
332001f49Smrg * test handling of many texture maps
432001f49Smrg * Also tests texture priority and residency.
532001f49Smrg *
632001f49Smrg * Brian Paul
732001f49Smrg * August 2, 2000
832001f49Smrg */
932001f49Smrg
1032001f49Smrg
1132001f49Smrg#include <assert.h>
1232001f49Smrg#include <stdio.h>
1332001f49Smrg#include <stdlib.h>
1432001f49Smrg#include <string.h>
1532001f49Smrg#include <math.h>
1632001f49Smrg#include <GL/glew.h>
1732001f49Smrg#include "glut_wrap.h"
1832001f49Smrg
1932001f49Smrg
2032001f49Smrgstatic GLint NumTextures = 20;
2132001f49Smrgstatic GLuint *TextureID = NULL;
2232001f49Smrgstatic GLint *TextureWidth = NULL, *TextureHeight = NULL;
2332001f49Smrgstatic GLboolean *TextureResidency = NULL;
2432001f49Smrgstatic GLint TexWidth = 128, TexHeight = 128;
2532001f49Smrgstatic GLfloat Zrot = 0;
2632001f49Smrgstatic GLboolean Anim = GL_TRUE;
2732001f49Smrgstatic GLint WinWidth = 500, WinHeight = 400;
2832001f49Smrgstatic GLboolean MipMap = GL_FALSE;
2932001f49Smrgstatic GLboolean LinearFilter = GL_FALSE;
3032001f49Smrgstatic GLboolean RandomSize = GL_FALSE;
3132001f49Smrgstatic GLint Rows, Columns;
3232001f49Smrgstatic GLint LowPriorityCount = 0;
3332001f49Smrgstatic GLint Win;
3432001f49Smrg
3532001f49Smrg
3632001f49Smrgstatic void Idle( void )
3732001f49Smrg{
3832001f49Smrg   Zrot += 1.0;
3932001f49Smrg   glutPostRedisplay();
4032001f49Smrg}
4132001f49Smrg
4232001f49Smrg
4332001f49Smrgstatic void Display( void )
4432001f49Smrg{
4532001f49Smrg   GLfloat spacing = WinWidth / Columns;
4632001f49Smrg   GLfloat size = spacing * 0.4;
4732001f49Smrg   GLint i;
4832001f49Smrg
4932001f49Smrg   /* test residency */
5032001f49Smrg   if (0)
5132001f49Smrg   {
5232001f49Smrg      GLboolean b;
5332001f49Smrg      GLint i, resident;
5432001f49Smrg      b = glAreTexturesResident(NumTextures, TextureID, TextureResidency);
5532001f49Smrg      if (b) {
5632001f49Smrg         printf("all resident\n");
5732001f49Smrg      }
5832001f49Smrg      else {
5932001f49Smrg         resident = 0;
6032001f49Smrg         for (i = 0; i < NumTextures; i++) {
6132001f49Smrg            if (TextureResidency[i]) {
6232001f49Smrg               resident++;
6332001f49Smrg            }
6432001f49Smrg         }
6532001f49Smrg         printf("%d of %d texture resident\n", resident, NumTextures);
6632001f49Smrg      }
6732001f49Smrg   }
6832001f49Smrg
6932001f49Smrg   /* render the textured quads */
7032001f49Smrg   glClear( GL_COLOR_BUFFER_BIT );
7132001f49Smrg   for (i = 0; i < NumTextures; i++) {
7232001f49Smrg      GLint row = i / Columns;
7332001f49Smrg      GLint col = i % Columns;
7432001f49Smrg      GLfloat x = col * spacing + spacing * 0.5;
7532001f49Smrg      GLfloat y = row * spacing + spacing * 0.5;
7632001f49Smrg
7732001f49Smrg      GLfloat maxDim = (TextureWidth[i] > TextureHeight[i])
7832001f49Smrg         ? TextureWidth[i] : TextureHeight[i];
7932001f49Smrg      GLfloat w = TextureWidth[i] / maxDim;
8032001f49Smrg      GLfloat h = TextureHeight[i] / maxDim;
8132001f49Smrg
8232001f49Smrg      glPushMatrix();
8332001f49Smrg         glTranslatef(x, y, 0.0);
8432001f49Smrg         glRotatef(Zrot, 0, 0, 1);
8532001f49Smrg         glScalef(size, size, 1);
8632001f49Smrg
8732001f49Smrg         glBindTexture(GL_TEXTURE_2D, TextureID[i]);
8832001f49Smrg         glBegin(GL_POLYGON);
8932001f49Smrg#if 0
9032001f49Smrg         glTexCoord2f(0, 0);  glVertex2f(-1, -1);
9132001f49Smrg         glTexCoord2f(1, 0);  glVertex2f( 1, -1);
9232001f49Smrg         glTexCoord2f(1, 1);  glVertex2f( 1,  1);
9332001f49Smrg         glTexCoord2f(0, 1);  glVertex2f(-1,  1);
9432001f49Smrg#else
9532001f49Smrg         glTexCoord2f(0, 0);  glVertex2f(-w, -h);
9632001f49Smrg         glTexCoord2f(1, 0);  glVertex2f( w, -h);
9732001f49Smrg         glTexCoord2f(1, 1);  glVertex2f( w,  h);
9832001f49Smrg         glTexCoord2f(0, 1);  glVertex2f(-w,  h);
9932001f49Smrg#endif
10032001f49Smrg         glEnd();
10132001f49Smrg      glPopMatrix();
10232001f49Smrg   }
10332001f49Smrg
10432001f49Smrg   glutSwapBuffers();
10532001f49Smrg}
10632001f49Smrg
10732001f49Smrg
10832001f49Smrgstatic void Reshape( int width, int height )
10932001f49Smrg{
11032001f49Smrg   WinWidth = width;
11132001f49Smrg   WinHeight = height;
11232001f49Smrg   glViewport( 0, 0, width, height );
11332001f49Smrg   glMatrixMode( GL_PROJECTION );
11432001f49Smrg   glLoadIdentity();
11532001f49Smrg   glOrtho(0, width, 0, height, -1, 1);
11632001f49Smrg   glMatrixMode( GL_MODELVIEW );
11732001f49Smrg   glLoadIdentity();
11832001f49Smrg}
11932001f49Smrg
12032001f49Smrg
12132001f49Smrg/*
12232001f49Smrg * Return a random int in [min, max].
12332001f49Smrg */
12432001f49Smrgstatic int RandomInt(int min, int max)
12532001f49Smrg{
12632001f49Smrg   int i = rand();
12732001f49Smrg   int j = i % (max - min + 1);
12832001f49Smrg   return min + j;
12932001f49Smrg}
13032001f49Smrg
13132001f49Smrg
13232001f49Smrgstatic void DeleteTextures(void)
13332001f49Smrg{
13432001f49Smrg   glDeleteTextures(NumTextures, TextureID);
13532001f49Smrg   free(TextureID);
13632001f49Smrg   TextureID = NULL;
13732001f49Smrg}
13832001f49Smrg
13932001f49Smrg
14032001f49Smrg
14132001f49Smrgstatic void Init( void )
14232001f49Smrg{
14332001f49Smrg   GLint i;
14432001f49Smrg
14532001f49Smrg   if (RandomSize) {
14632001f49Smrg      printf("Creating %d %s random-size textures, ", NumTextures,
14732001f49Smrg             MipMap ? "Mipmapped" : "non-Mipmapped");
14832001f49Smrg   }
14932001f49Smrg   else {
15032001f49Smrg      printf("Creating %d %s %d x %d textures, ", NumTextures,
15132001f49Smrg             MipMap ? "Mipmapped" : "non-Mipmapped",
15232001f49Smrg             TexWidth, TexHeight);
15332001f49Smrg   }
15432001f49Smrg
15532001f49Smrg   if (LinearFilter) {
15632001f49Smrg      printf("bilinear filtering\n");
15732001f49Smrg   }
15832001f49Smrg   else {
15932001f49Smrg      printf("nearest filtering\n");
16032001f49Smrg   }
16132001f49Smrg
16232001f49Smrg
16332001f49Smrg   /* compute number of rows and columns of rects */
16432001f49Smrg   {
16532001f49Smrg      GLfloat area = (GLfloat) (WinWidth * WinHeight) / (GLfloat) NumTextures;
16632001f49Smrg      GLfloat edgeLen = sqrt(area);
16732001f49Smrg
16832001f49Smrg      Columns = WinWidth / edgeLen;
16932001f49Smrg      Rows = (NumTextures + Columns - 1) / Columns;
17032001f49Smrg      printf("Rows: %d  Cols: %d\n", Rows, Columns);
17132001f49Smrg   }
17232001f49Smrg
17332001f49Smrg
17432001f49Smrg   if (!TextureID) {
17532001f49Smrg      TextureID = (GLuint *) malloc(sizeof(GLuint) * NumTextures);
17632001f49Smrg      assert(TextureID);
17732001f49Smrg      glGenTextures(NumTextures, TextureID);
17832001f49Smrg   }
17932001f49Smrg
18032001f49Smrg   if (!TextureResidency) {
18132001f49Smrg      TextureResidency = (GLboolean *) malloc(sizeof(GLboolean) * NumTextures);
18232001f49Smrg      assert(TextureResidency);
18332001f49Smrg   }
18432001f49Smrg
18532001f49Smrg   if (!TextureWidth) {
18632001f49Smrg      TextureWidth = (GLint *) malloc(sizeof(GLint) * NumTextures);
18732001f49Smrg      assert(TextureWidth);
18832001f49Smrg   }
18932001f49Smrg   if (!TextureHeight) {
19032001f49Smrg      TextureHeight = (GLint *) malloc(sizeof(GLint) * NumTextures);
19132001f49Smrg      assert(TextureHeight);
19232001f49Smrg   }
19332001f49Smrg
19432001f49Smrg   for (i = 0; i < NumTextures; i++) {
19532001f49Smrg      GLubyte color[4];
19632001f49Smrg      GLubyte *texImage;
19732001f49Smrg      GLint j, row, col;
19832001f49Smrg
19932001f49Smrg      row = i / Columns;
20032001f49Smrg      col = i % Columns;
20132001f49Smrg
20232001f49Smrg      glBindTexture(GL_TEXTURE_2D, TextureID[i]);
20332001f49Smrg
20432001f49Smrg      if (i < LowPriorityCount)
20532001f49Smrg         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_PRIORITY, 0.5F);
20632001f49Smrg
20732001f49Smrg      if (RandomSize) {
20832001f49Smrg#if 0
20932001f49Smrg         int k = (glutGet(GLUT_ELAPSED_TIME) % 7) + 2;
21032001f49Smrg         TexWidth  = 1 << k;
21132001f49Smrg         TexHeight = 1 << k;
21232001f49Smrg#else
21332001f49Smrg         TexWidth = 1 << RandomInt(2, 7);
21432001f49Smrg         TexHeight = 1 << RandomInt(2, 7);
21532001f49Smrg         printf("Random size of %3d: %d x %d\n", i, TexWidth, TexHeight);
21632001f49Smrg#endif
21732001f49Smrg      }
21832001f49Smrg
21932001f49Smrg      TextureWidth[i] = TexWidth;
22032001f49Smrg      TextureHeight[i] = TexHeight;
22132001f49Smrg
22232001f49Smrg      texImage = (GLubyte*) malloc(4 * TexWidth * TexHeight * sizeof(GLubyte));
22332001f49Smrg      assert(texImage);
22432001f49Smrg
22532001f49Smrg      /* determine texture color */
22632001f49Smrg      color[0] = (GLint) (255.0 * ((float) col / (Columns - 1)));
22732001f49Smrg      color[1] = 127;
22832001f49Smrg      color[2] = (GLint) (255.0 * ((float) row / (Rows - 1)));
22932001f49Smrg      color[3] = 255;
23032001f49Smrg
23132001f49Smrg      /* fill in solid-colored teximage */
23232001f49Smrg      for (j = 0; j < TexWidth * TexHeight; j++) {
23332001f49Smrg         texImage[j*4+0] = color[0];
23432001f49Smrg         texImage[j*4+1] = color[1];
23532001f49Smrg         texImage[j*4+2] = color[2];
23632001f49Smrg         texImage[j*4+3] = color[3];
23732001f49Smrg     }
23832001f49Smrg
23932001f49Smrg      if (MipMap) {
24032001f49Smrg         GLint level = 0;
24132001f49Smrg         GLint w = TexWidth, h = TexHeight;
24232001f49Smrg         while (1) {
24332001f49Smrg            glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, w, h, 0,
24432001f49Smrg                         GL_RGBA, GL_UNSIGNED_BYTE, texImage);
24532001f49Smrg            if (w == 1 && h == 1)
24632001f49Smrg               break;
24732001f49Smrg            if (w > 1)
24832001f49Smrg               w /= 2;
24932001f49Smrg            if (h > 1)
25032001f49Smrg               h /= 2;
25132001f49Smrg            level++;
25232001f49Smrg            /*printf("%d: %d x %d\n", level, w, h);*/
25332001f49Smrg         }
25432001f49Smrg         if (LinearFilter) {
25532001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
25632001f49Smrg                            GL_LINEAR_MIPMAP_LINEAR);
25732001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
25832001f49Smrg         }
25932001f49Smrg         else {
26032001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
26132001f49Smrg                            GL_NEAREST_MIPMAP_NEAREST);
26232001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
26332001f49Smrg         }
26432001f49Smrg      }
26532001f49Smrg      else {
26632001f49Smrg         /* Set corners to white */
26732001f49Smrg         int k = 0;
26832001f49Smrg         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
26932001f49Smrg         k = (TexWidth - 1) * 4;
27032001f49Smrg         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
27132001f49Smrg         k = (TexWidth * TexHeight - TexWidth) * 4;
27232001f49Smrg         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
27332001f49Smrg         k = (TexWidth * TexHeight - 1) * 4;
27432001f49Smrg         texImage[k+0] = texImage[k+1] = texImage[k+2] = texImage[k+3] = 255;
27532001f49Smrg
27632001f49Smrg         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0,
27732001f49Smrg                      GL_RGBA, GL_UNSIGNED_BYTE, texImage);
27832001f49Smrg         if (LinearFilter) {
27932001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
28032001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
28132001f49Smrg         }
28232001f49Smrg         else {
28332001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
28432001f49Smrg            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
28532001f49Smrg         }
28632001f49Smrg      }
28732001f49Smrg
28832001f49Smrg      free(texImage);
28932001f49Smrg   }
29032001f49Smrg
29132001f49Smrg   glEnable(GL_TEXTURE_2D);
29232001f49Smrg}
29332001f49Smrg
29432001f49Smrg
29532001f49Smrgstatic void Key( unsigned char key, int x, int y )
29632001f49Smrg{
29732001f49Smrg   const GLfloat step = 3.0;
29832001f49Smrg   (void) x;
29932001f49Smrg   (void) y;
30032001f49Smrg   switch (key) {
30132001f49Smrg      case 'a':
30232001f49Smrg         Anim = !Anim;
30332001f49Smrg         if (Anim)
30432001f49Smrg            glutIdleFunc(Idle);
30532001f49Smrg         else
30632001f49Smrg            glutIdleFunc(NULL);
30732001f49Smrg         break;
30832001f49Smrg      case 's':
30932001f49Smrg         Idle();
31032001f49Smrg         break;
31132001f49Smrg      case 'z':
31232001f49Smrg         Zrot -= step;
31332001f49Smrg         break;
31432001f49Smrg      case 'Z':
31532001f49Smrg         Zrot += step;
31632001f49Smrg         break;
31732001f49Smrg      case ' ':
31832001f49Smrg         DeleteTextures();
31932001f49Smrg         Init();
32032001f49Smrg         break;
32132001f49Smrg      case 27:
32232001f49Smrg         DeleteTextures();
32332001f49Smrg         glutDestroyWindow(Win);
32432001f49Smrg         exit(0);
32532001f49Smrg         break;
32632001f49Smrg   }
32732001f49Smrg   glutPostRedisplay();
32832001f49Smrg}
32932001f49Smrg
33032001f49Smrg
33132001f49Smrgint main( int argc, char *argv[] )
33232001f49Smrg{
33332001f49Smrg   GLint i;
33432001f49Smrg
33532001f49Smrg   glutInit( &argc, argv );
33632001f49Smrg   glutInitWindowPosition( 0, 0 );
33732001f49Smrg   glutInitWindowSize( WinWidth, WinHeight );
33832001f49Smrg   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
33932001f49Smrg   Win = glutCreateWindow(argv[0]);
34032001f49Smrg   glewInit();
34132001f49Smrg   glutReshapeFunc( Reshape );
34232001f49Smrg   glutKeyboardFunc( Key );
34332001f49Smrg   glutDisplayFunc( Display );
34432001f49Smrg   if (Anim)
34532001f49Smrg      glutIdleFunc(Idle);
34632001f49Smrg
34732001f49Smrg   for (i = 1; i < argc; i++) {
34832001f49Smrg      if (strcmp(argv[i], "-n") == 0) {
34932001f49Smrg         NumTextures = atoi(argv[i+1]);
35032001f49Smrg         if (NumTextures <= 0) {
35132001f49Smrg            printf("Error, bad number of textures\n");
35232001f49Smrg            return 1;
35332001f49Smrg         }
35432001f49Smrg         i++;
35532001f49Smrg      }
35632001f49Smrg      else if (strcmp(argv[i], "-mipmap") == 0) {
35732001f49Smrg         MipMap = GL_TRUE;
35832001f49Smrg      }
35932001f49Smrg      else if (strcmp(argv[i], "-linear") == 0) {
36032001f49Smrg         LinearFilter = GL_TRUE;
36132001f49Smrg      }
36232001f49Smrg      else if (strcmp(argv[i], "-size") == 0) {
36332001f49Smrg         TexWidth = atoi(argv[i+1]);
36432001f49Smrg         TexHeight = atoi(argv[i+2]);
36532001f49Smrg         assert(TexWidth >= 1);
36632001f49Smrg         assert(TexHeight >= 1);
36732001f49Smrg         i += 2;
36832001f49Smrg      }
36932001f49Smrg      else if (strcmp(argv[i], "-randomsize") == 0) {
37032001f49Smrg         RandomSize = GL_TRUE;
37132001f49Smrg      }
37232001f49Smrg      else if (strcmp(argv[i], "-lowpri") == 0) {
37332001f49Smrg         LowPriorityCount = atoi(argv[i+1]);
37432001f49Smrg         i++;
37532001f49Smrg      }
37632001f49Smrg      else {
37732001f49Smrg         printf("Usage:\n");
37832001f49Smrg         printf("  manytex [options]\n");
37932001f49Smrg         printf("Options:\n");
38032001f49Smrg         printf("  -n <number of texture objects>\n");
38132001f49Smrg         printf("  -size <width> <height>  - specify texture size\n");
38232001f49Smrg         printf("  -randomsize  - use random size textures\n");
38332001f49Smrg         printf("  -mipmap      - generate mipmaps\n");
38432001f49Smrg         printf("  -linear      - use linear filtering instead of nearest\n");
38532001f49Smrg         printf("  -lowpri <n>  - Set lower priority on <n> textures\n");
38632001f49Smrg         return 0;
38732001f49Smrg      }
38832001f49Smrg   }
38932001f49Smrg
39032001f49Smrg   Init();
39132001f49Smrg
39232001f49Smrg   glutMainLoop();
39332001f49Smrg
39432001f49Smrg   return 0;
39532001f49Smrg}
396