132001f49Smrg/*
232001f49Smrg * (C) Copyright IBM Corporation 2007
332001f49Smrg * All Rights Reserved.
432001f49Smrg *
532001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
632001f49Smrg * copy of this software and associated documentation files (the "Software"),
732001f49Smrg * to deal in the Software without restriction, including without limitation
832001f49Smrg * on the rights to use, copy, modify, merge, publish, distribute, sub
932001f49Smrg * license, and/or sell copies of the Software, and to permit persons to whom
1032001f49Smrg * the Software is furnished to do so, subject to the following conditions:
1132001f49Smrg *
1232001f49Smrg * The above copyright notice and this permission notice (including the next
1332001f49Smrg * paragraph) shall be included in all copies or substantial portions of the
1432001f49Smrg * Software.
1532001f49Smrg *
1632001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1732001f49Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1832001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
1932001f49Smrg * IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2032001f49Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2132001f49Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2232001f49Smrg * IN THE SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg/**
2632001f49Smrg * \file arraytexture.c
2732001f49Smrg *
2832001f49Smrg *
2932001f49Smrg * \author Ian Romanick <idr@us.ibm.com>
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg#include <assert.h>
3332001f49Smrg#include <stdlib.h>
3432001f49Smrg#include <stdio.h>
3532001f49Smrg#include <string.h>
3632001f49Smrg#include <math.h>
3732001f49Smrg#include <GL/glew.h>
3832001f49Smrg#include "glut_wrap.h"
3932001f49Smrg
4032001f49Smrg#if !defined(GL_EXT_texture_array) && !defined(GL_MESA_texture_array)
4132001f49Smrg# error "This demo requires enums for either GL_EXT_texture_array or GL_MESA_texture_array to build."
4232001f49Smrg#endif
4332001f49Smrg
4432001f49Smrg#include "readtex.h"
4532001f49Smrg
4632001f49Smrg#define GL_CHECK_ERROR() \
4732001f49Smrg    do { \
4832001f49Smrg       GLenum err = glGetError(); \
4932001f49Smrg       if (err) { \
5032001f49Smrg          printf("%s:%u: %s (0x%04x)\n", __FILE__, __LINE__, \
5132001f49Smrg                    gluErrorString(err), err); \
5232001f49Smrg       } \
5332001f49Smrg    } while (0)
5432001f49Smrg
5532001f49Smrgstatic const char *const textures[] = {
5632001f49Smrg   DEMOS_DATA_DIR "girl.rgb",
5732001f49Smrg   DEMOS_DATA_DIR "girl2.rgb",
5832001f49Smrg   DEMOS_DATA_DIR "arch.rgb",
5932001f49Smrg   DEMOS_DATA_DIR "s128.rgb",
6032001f49Smrg
6132001f49Smrg   DEMOS_DATA_DIR "tree3.rgb",
6232001f49Smrg   DEMOS_DATA_DIR "bw.rgb",
6332001f49Smrg   DEMOS_DATA_DIR "reflect.rgb",
6432001f49Smrg   DEMOS_DATA_DIR "wrs_logo.rgb",
6532001f49Smrg   NULL
6632001f49Smrg};
6732001f49Smrg
6832001f49Smrgstatic const char frag_prog[] =
6932001f49Smrg  "!!ARBfp1.0\n"
7032001f49Smrg  "OPTION MESA_texture_array;\n"
7132001f49Smrg  "TEX    result.color, fragment.texcoord[0], texture[0], ARRAY2D;\n"
7232001f49Smrg  "END\n";
7332001f49Smrg
7432001f49Smrgstatic GLfloat Xrot = 0, Yrot = -30, Zrot = 0;
7532001f49Smrgstatic GLfloat texZ = 0.0;
7632001f49Smrgstatic GLfloat texZ_dir = 0.01;
7732001f49Smrgstatic GLint num_layers;
7832001f49Smrg
7932001f49Smrg
8032001f49Smrgstatic void
8132001f49SmrgPrintString(const char *s)
8232001f49Smrg{
8332001f49Smrg   while (*s) {
8432001f49Smrg      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
8532001f49Smrg      s++;
8632001f49Smrg   }
8732001f49Smrg}
8832001f49Smrg
8932001f49Smrg
9032001f49Smrgstatic void Idle(void)
9132001f49Smrg{
9232001f49Smrg   static int lastTime = 0;
9332001f49Smrg   int t = glutGet(GLUT_ELAPSED_TIME);
9432001f49Smrg
9532001f49Smrg   if (lastTime == 0)
9632001f49Smrg      lastTime = t;
9732001f49Smrg   else if (t - lastTime < 10)
9832001f49Smrg      return;
9932001f49Smrg
10032001f49Smrg   lastTime = t;
10132001f49Smrg
10232001f49Smrg   texZ += texZ_dir;
10332001f49Smrg   if ((texZ < 0.0) || ((GLint) texZ > num_layers)) {
10432001f49Smrg      texZ_dir = -texZ_dir;
10532001f49Smrg   }
10632001f49Smrg
10732001f49Smrg   glutPostRedisplay();
10832001f49Smrg}
10932001f49Smrg
11032001f49Smrg
11132001f49Smrgstatic void Display(void)
11232001f49Smrg{
11332001f49Smrg   char str[100];
11432001f49Smrg
11532001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
11632001f49Smrg
11732001f49Smrg   glMatrixMode(GL_PROJECTION);
11832001f49Smrg   glLoadIdentity();
11932001f49Smrg   glOrtho(-1, 1, -1, 1, -1, 1);
12032001f49Smrg   glMatrixMode(GL_MODELVIEW);
12132001f49Smrg   glLoadIdentity();
12232001f49Smrg
12332001f49Smrg   glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
12432001f49Smrg   glColor3f(1,1,1);
12532001f49Smrg   glRasterPos3f(-0.9, -0.9, 0.0);
12632001f49Smrg   sprintf(str, "Texture Z coordinate = %4.1f", texZ);
12732001f49Smrg   PrintString(str);
12832001f49Smrg
12932001f49Smrg   glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 1);
13032001f49Smrg   GL_CHECK_ERROR();
13132001f49Smrg   glEnable(GL_TEXTURE_2D_ARRAY_EXT);
13232001f49Smrg   GL_CHECK_ERROR();
13332001f49Smrg
13432001f49Smrg   glMatrixMode(GL_PROJECTION);
13532001f49Smrg   glLoadIdentity();
13632001f49Smrg   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 25.0);
13732001f49Smrg   glMatrixMode(GL_MODELVIEW);
13832001f49Smrg   glLoadIdentity();
13932001f49Smrg   glTranslatef(0.0, 0.0, -8.0);
14032001f49Smrg
14132001f49Smrg   glPushMatrix();
14232001f49Smrg   glRotatef(Xrot, 1, 0, 0);
14332001f49Smrg   glRotatef(Yrot, 0, 1, 0);
14432001f49Smrg   glRotatef(Zrot, 0, 0, 1);
14532001f49Smrg
14632001f49Smrg   glBegin(GL_QUADS);
14732001f49Smrg   glTexCoord3f(0.0, 0.0, texZ);  glVertex2f(-1.0, -1.0);
14832001f49Smrg   glTexCoord3f(2.0, 0.0, texZ);  glVertex2f(1.0, -1.0);
14932001f49Smrg   glTexCoord3f(2.0, 2.0, texZ);  glVertex2f(1.0,  1.0);
15032001f49Smrg   glTexCoord3f(0.0, 2.0, texZ);  glVertex2f(-1.0,  1.0);
15132001f49Smrg   glEnd();
15232001f49Smrg
15332001f49Smrg   glPopMatrix();
15432001f49Smrg
15532001f49Smrg   glDisable(GL_TEXTURE_2D_ARRAY_EXT);
15632001f49Smrg   GL_CHECK_ERROR();
15732001f49Smrg   glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0);
15832001f49Smrg   GL_CHECK_ERROR();
15932001f49Smrg
16032001f49Smrg   glutSwapBuffers();
16132001f49Smrg}
16232001f49Smrg
16332001f49Smrg
16432001f49Smrgstatic void Reshape(int width, int height)
16532001f49Smrg{
16632001f49Smrg   glViewport(0, 0, width, height);
16732001f49Smrg}
16832001f49Smrg
16932001f49Smrg
17032001f49Smrgstatic void Key(unsigned char key, int x, int y)
17132001f49Smrg{
17232001f49Smrg   (void) x;
17332001f49Smrg   (void) y;
17432001f49Smrg   switch (key) {
17532001f49Smrg      case 27:
17632001f49Smrg         exit(0);
17732001f49Smrg         break;
17832001f49Smrg   }
17932001f49Smrg   glutPostRedisplay();
18032001f49Smrg}
18132001f49Smrg
18232001f49Smrg
18332001f49Smrgstatic void SpecialKey(int key, int x, int y)
18432001f49Smrg{
18532001f49Smrg   const GLfloat step = 3.0;
18632001f49Smrg   (void) x;
18732001f49Smrg   (void) y;
18832001f49Smrg   switch (key) {
18932001f49Smrg      case GLUT_KEY_UP:
19032001f49Smrg         Xrot -= step;
19132001f49Smrg         break;
19232001f49Smrg      case GLUT_KEY_DOWN:
19332001f49Smrg         Xrot += step;
19432001f49Smrg         break;
19532001f49Smrg      case GLUT_KEY_LEFT:
19632001f49Smrg         Yrot -= step;
19732001f49Smrg         break;
19832001f49Smrg      case GLUT_KEY_RIGHT:
19932001f49Smrg         Yrot += step;
20032001f49Smrg         break;
20132001f49Smrg   }
20232001f49Smrg   glutPostRedisplay();
20332001f49Smrg}
20432001f49Smrg
20532001f49Smrg
20632001f49Smrgstatic int FindLine(const char *program, int position)
20732001f49Smrg{
20832001f49Smrg   int i, line = 1;
20932001f49Smrg   for (i = 0; i < position; i++) {
21032001f49Smrg      if (program[i] == '\n')
21132001f49Smrg          line++;
21232001f49Smrg   }
21332001f49Smrg   return line;
21432001f49Smrg}
21532001f49Smrg
21632001f49Smrg
21732001f49Smrgstatic void
21832001f49Smrgcompile_fragment_program(GLuint id, const char *prog)
21932001f49Smrg{
22032001f49Smrg   int errorPos;
22132001f49Smrg   int err;
22232001f49Smrg
22332001f49Smrg   err = glGetError();
22432001f49Smrg   glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, id);
22532001f49Smrg   glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
22632001f49Smrg                     strlen(prog), (const GLubyte *) prog);
22732001f49Smrg
22832001f49Smrg   glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
22932001f49Smrg   err = glGetError();
23032001f49Smrg   if (err != GL_NO_ERROR || errorPos != -1) {
23132001f49Smrg      int l = FindLine(prog, errorPos);
23232001f49Smrg
23332001f49Smrg      printf("Fragment Program Error (err=%d, pos=%d line=%d): %s\n",
23432001f49Smrg             err, errorPos, l,
23532001f49Smrg             (char *) glGetString(GL_PROGRAM_ERROR_STRING_ARB));
23632001f49Smrg      exit(0);
23732001f49Smrg   }
23832001f49Smrg}
23932001f49Smrg
24032001f49Smrg
24132001f49Smrgstatic void require_extension(const char *ext)
24232001f49Smrg{
24332001f49Smrg   if (!glutExtensionSupported(ext)) {
24432001f49Smrg      printf("Sorry, %s not supported by this renderer.\n", ext);
24532001f49Smrg      exit(1);
24632001f49Smrg   }
24732001f49Smrg}
24832001f49Smrg
24932001f49Smrg
25032001f49Smrgstatic void Init(void)
25132001f49Smrg{
25232001f49Smrg   const char *const ver_string = (const char *) glGetString(GL_VERSION);
25332001f49Smrg   unsigned i;
25432001f49Smrg
25532001f49Smrg   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
25632001f49Smrg   printf("GL_VERSION = %s\n", ver_string);
25732001f49Smrg
25832001f49Smrg   require_extension("GL_ARB_fragment_program");
25932001f49Smrg   require_extension("GL_MESA_texture_array");
26032001f49Smrg   require_extension("GL_SGIS_generate_mipmap");
26132001f49Smrg
26232001f49Smrg   for (num_layers = 0; textures[num_layers] != NULL; num_layers++)
26332001f49Smrg      /* empty */ ;
26432001f49Smrg
26532001f49Smrg   glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 1);
26632001f49Smrg   glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGB8,
26732001f49Smrg                256, 256, num_layers, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
26832001f49Smrg   GL_CHECK_ERROR();
26932001f49Smrg
27032001f49Smrg   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_GENERATE_MIPMAP_SGIS,
27132001f49Smrg                   GL_TRUE);
27232001f49Smrg
27332001f49Smrg   for (i = 0; textures[i] != NULL; i++) {
27432001f49Smrg      GLint width, height;
27532001f49Smrg      GLenum format;
27632001f49Smrg
27732001f49Smrg      GLubyte *image = LoadRGBImage(textures[i], &width, &height, &format);
27832001f49Smrg      if (!image) {
27932001f49Smrg         printf("Error: could not load texture image %s\n", textures[i]);
28032001f49Smrg         exit(1);
28132001f49Smrg      }
28232001f49Smrg
28332001f49Smrg      /* resize to 256 x 256 */
28432001f49Smrg      if (width != 256 || height != 256) {
28532001f49Smrg         GLubyte *newImage = malloc(256 * 256 * 4);
28632001f49Smrg         gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image,
28732001f49Smrg                       256, 256, GL_UNSIGNED_BYTE, newImage);
28832001f49Smrg         free(image);
28932001f49Smrg         image = newImage;
29032001f49Smrg      }
29132001f49Smrg
29232001f49Smrg      glTexSubImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0,
29332001f49Smrg                      0, 0, i, 256, 256, 1,
29432001f49Smrg                      format, GL_UNSIGNED_BYTE, image);
29532001f49Smrg      free(image);
29632001f49Smrg   }
29732001f49Smrg   GL_CHECK_ERROR();
29832001f49Smrg
29932001f49Smrg   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_S, GL_REPEAT);
30032001f49Smrg   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_T, GL_REPEAT);
30132001f49Smrg   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
30232001f49Smrg
30332001f49Smrg   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
30432001f49Smrg   GL_CHECK_ERROR();
30532001f49Smrg   glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
30632001f49Smrg   GL_CHECK_ERROR();
30732001f49Smrg
30832001f49Smrg   compile_fragment_program(1, frag_prog);
30932001f49Smrg   GL_CHECK_ERROR();
31032001f49Smrg}
31132001f49Smrg
31232001f49Smrg
31332001f49Smrgint main(int argc, char *argv[])
31432001f49Smrg{
31532001f49Smrg   glutInit(&argc, argv);
31632001f49Smrg   glutInitWindowPosition(0, 0);
31732001f49Smrg   glutInitWindowSize(350, 350);
31832001f49Smrg   glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
31932001f49Smrg   glutCreateWindow("Array texture test");
32032001f49Smrg   glewInit();
32132001f49Smrg   glutReshapeFunc(Reshape);
32232001f49Smrg   glutKeyboardFunc(Key);
32332001f49Smrg   glutSpecialFunc(SpecialKey);
32432001f49Smrg   glutDisplayFunc(Display);
32532001f49Smrg   glutIdleFunc(Idle);
32632001f49Smrg   Init();
32732001f49Smrg   glutMainLoop();
32832001f49Smrg   return 0;
32932001f49Smrg}
330