1/*
2 * Copyright (C) 2000  Brian Paul   All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 */
21
22/**
23 * \file bug_3195.c
24 *
25 * Simple regression test for bug #3195.  A bug in the i180 driver caused
26 * a segfault (inside the driver) when the LOD bias is adjusted and no texture
27 * is enabled.  This test, which is based on progs/demos/lodbias.c, sets up
28 * all the texturing, disables all textures, adjusts the LOD bias, then
29 * re-enables \c GL_TEXTURE_2D.
30 *
31 * \author Brian Paul
32 * \author Ian Romanick <idr@us.ibm.com>
33 */
34
35#include <assert.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include <math.h>
39#include <GL/glew.h>
40#include "glut_wrap.h"
41
42#include "readtex.h"
43
44#define TEXTURE_FILE DEMOS_DATA_DIR "girl.rgb"
45
46static GLfloat Xrot = 0, Yrot = -30, Zrot = 0;
47static GLint Bias = 0, BiasStepSign = +1; /* ints avoid fp precision problem */
48static GLint BiasMin = -400, BiasMax = 400;
49
50
51
52static void
53PrintString(const char *s)
54{
55   while (*s) {
56      glutBitmapCharacter(GLUT_BITMAP_8_BY_13, (int) *s);
57      s++;
58   }
59}
60
61static void Idle( void )
62{
63   static int lastTime = 0;
64   int time = glutGet(GLUT_ELAPSED_TIME);
65   int step;
66
67   if (lastTime == 0)
68      lastTime = time;
69   else if (time - lastTime < 10)
70      return;
71
72   step = (time - lastTime) / 10 * BiasStepSign;
73   lastTime = time;
74
75   Bias += step;
76   if (Bias < BiasMin) {
77      exit(0);
78   }
79   else if (Bias > BiasMax) {
80      Bias = BiasMax;
81      BiasStepSign = -1;
82   }
83
84   glutPostRedisplay();
85}
86
87
88static void Display( void )
89{
90   char str[100];
91
92   glClear( GL_COLOR_BUFFER_BIT );
93
94   glMatrixMode( GL_PROJECTION );
95   glLoadIdentity();
96   glOrtho(-1, 1, -1, 1, -1, 1);
97   glMatrixMode( GL_MODELVIEW );
98   glLoadIdentity();
99
100   glDisable(GL_TEXTURE_2D);
101   glColor3f(1,1,1);
102   glRasterPos3f(-0.9, -0.9, 0.0);
103   sprintf(str, "Texture LOD Bias = %4.1f", Bias * 0.01);
104   PrintString(str);
105
106   glMatrixMode( GL_PROJECTION );
107   glLoadIdentity();
108   glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 );
109   glMatrixMode( GL_MODELVIEW );
110   glLoadIdentity();
111   glTranslatef( 0.0, 0.0, -8.0 );
112
113   glPushMatrix();
114   glRotatef(Xrot, 1, 0, 0);
115   glRotatef(Yrot, 0, 1, 0);
116   glRotatef(Zrot, 0, 0, 1);
117
118   glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT, GL_TEXTURE_LOD_BIAS_EXT, 0.01 * Bias);
119   glEnable(GL_TEXTURE_2D);
120
121   glBegin(GL_POLYGON);
122   glTexCoord2f(0, 0);  glVertex2f(-1, -1);
123   glTexCoord2f(2, 0);  glVertex2f( 1, -1);
124   glTexCoord2f(2, 2);  glVertex2f( 1,  1);
125   glTexCoord2f(0, 2);  glVertex2f(-1,  1);
126   glEnd();
127
128   glPopMatrix();
129
130   glutSwapBuffers();
131}
132
133
134static void Reshape( int width, int height )
135{
136   glViewport( 0, 0, width, height );
137}
138
139
140static void Key( unsigned char key, int x, int y )
141{
142   (void) x;
143   (void) y;
144   switch (key) {
145      case 27:
146         exit(0);
147         break;
148   }
149   glutPostRedisplay();
150}
151
152
153static void SpecialKey( int key, int x, int y )
154{
155   const GLfloat step = 3.0;
156   (void) x;
157   (void) y;
158   switch (key) {
159      case GLUT_KEY_UP:
160         Xrot -= step;
161         break;
162      case GLUT_KEY_DOWN:
163         Xrot += step;
164         break;
165      case GLUT_KEY_LEFT:
166         Yrot -= step;
167         break;
168      case GLUT_KEY_RIGHT:
169         Yrot += step;
170         break;
171   }
172   glutPostRedisplay();
173}
174
175
176static void Init( void )
177{
178   GLfloat maxBias;
179   const char * const ver_string = (const char *)
180       glGetString( GL_VERSION );
181
182   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
183   printf("GL_VERSION = %s\n", ver_string);
184
185   printf("\nThis program should function nearly identically to Mesa's lodbias demo.\n"
186	  "It should cycle through the complet LOD bias range once and exit.  If bug\n"
187	  "#3195 still exists, the demo should crash almost immediatly.\n");
188   printf("This is a regression test for bug #3195.\n");
189   printf("https://bugs.freedesktop.org/show_bug.cgi?id=3195\n");
190
191   if (!glutExtensionSupported("GL_EXT_texture_lod_bias")) {
192      printf("Sorry, GL_EXT_texture_lod_bias not supported by this renderer.\n");
193      exit(1);
194   }
195
196   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
197
198   if (glutExtensionSupported("GL_SGIS_generate_mipmap")) {
199      /* test auto mipmap generation */
200      GLint width, height, i;
201      GLenum format;
202      GLubyte *image = LoadRGBImage(TEXTURE_FILE, &width, &height, &format);
203      if (!image) {
204         printf("Error: could not load texture image %s\n", TEXTURE_FILE);
205         exit(1);
206      }
207      /* resize to 256 x 256 */
208      if (width != 256 || height != 256) {
209         GLubyte *newImage = malloc(256 * 256 * 4);
210         gluScaleImage(format, width, height, GL_UNSIGNED_BYTE, image,
211                       256, 256, GL_UNSIGNED_BYTE, newImage);
212         free(image);
213         image = newImage;
214      }
215      printf("Using GL_SGIS_generate_mipmap\n");
216      glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
217      glTexImage2D(GL_TEXTURE_2D, 0, format, 256, 256, 0,
218                   format, GL_UNSIGNED_BYTE, image);
219      free(image);
220
221      /* make sure mipmap was really generated correctly */
222      width = height = 256;
223      for (i = 0; i < 9; i++) {
224         GLint w, h;
225         glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_WIDTH, &w);
226         glGetTexLevelParameteriv(GL_TEXTURE_2D, i, GL_TEXTURE_HEIGHT, &h);
227         printf("Level %d size: %d x %d\n", i, w, h);
228         assert(w == width);
229         assert(h == height);
230         width /= 2;
231         height /= 2;
232      }
233
234   }
235   else if (!LoadRGBMipmaps(TEXTURE_FILE, GL_RGB)) {
236      printf("Error: could not load texture image %s\n", TEXTURE_FILE);
237      exit(1);
238   }
239
240   /* mipmapping required for this extension */
241   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
242   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
243   glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
244
245   glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &maxBias);
246   printf("LOD bias range: [%g, %g]\n", -maxBias, maxBias);
247   BiasMin = -100 * maxBias;
248   BiasMax =  100 * maxBias;
249
250   /* Since we have (about) 8 mipmap levels, no need to bias beyond
251    * the range [-1, +8].
252    */
253   if (BiasMin < -100)
254      BiasMin = -100;
255   if (BiasMax > 800)
256      BiasMax = 800;
257}
258
259
260int main( int argc, char *argv[] )
261{
262   glutInit( &argc, argv );
263   glutInitWindowPosition( 0, 0 );
264   glutInitWindowSize( 350, 350 );
265   glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
266   glutCreateWindow( "Bug #3195 Test" );
267   glewInit();
268   glutReshapeFunc( Reshape );
269   glutKeyboardFunc( Key );
270   glutSpecialFunc( SpecialKey );
271   glutDisplayFunc( Display );
272   glutIdleFunc(Idle);
273   Init();
274   glutMainLoop();
275   return 0;
276}
277