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