PDA

View Full Version : Slow gluBuild2DMipmap(...)



MickeyMouse
10-30-2003, 08:05 AM
Why it's so damn slow?
I know it works in software but sometimes it takes almost a whole second on my AMD 2600 (with card Radeon 9600 Pro, but it's said to be of no importance).

Thanks.

NitroGL
10-30-2003, 09:55 AM
Originally posted by MickeyMouse:
Why it's so damn slow?
I know it works in software but sometimes it takes almost a whole second on my AMD 2600 (with card Radeon 9600 Pro, but it's said to be of no importance).

Thanks.

What kind of texture data, and how big of a texture?

cass
10-30-2003, 10:48 AM
You should use glTexParameteri( <target>, GL_GENERATE_MIPMAP, GL_TRUE );

This is core functionality as of OpenGL 1.4, and it's usually *much* faster than the glu routine.

Thanks -
Cass

MickeyMouse
11-03-2003, 04:07 AM
Thanks.

I was talking about 512 x 512.
It was surprising since even not so optimized C routines should be much faster.

M/\dm/\n
11-03-2003, 04:11 AM
As far as I remember gluBMM was slow allways, it's just an unoptimized box filter, that hasn't been touched for years. Stick with gen_mipmaps for GF+ R7xxx+

AdrianD
11-03-2003, 07:26 AM
try this:




/*================================================= ==========================*/
/* This function is a special version of the GLU function. This version of */
/* the function uses the graphic adapters filtering to generate the different*/
/* levels. This should make for better quality mipmaps and might even be */
/* faster, although speed isn't the point. */
/* The function works the same except for a couple of things. First the call*/
/* will trash your back buffer so this function shouldn't be used during a */
/* frame. Also it is unsure as to how a alpha texture will work out since */
/* most drivers still don't do destination alpha. */
/* So caller beware... */
/*================================================= ==========================*/
/* RETURN: 0 is success, non-zero is a GL error type. */
/*================================================= ==========================*/
GLint __gluBuild2DMipMaps( GLenum target,
GLint component,
GLsizei width,
GLsizei height,
GLenum format,
GLenum type,
const void *data )
{
GLint maxsize,
viewport[4],
w, h,
level,
error;
GLuint pow2;
void *image;

/* Sanity check. */
if ( width < 1 &amp;#0124; &amp;#0124; height < 1 )
return GLU_INVALID_VALUE;

/* Round the width to the next lower pow2 if not already a pow2. */
for( pow2 = 1; pow2 < width; pow2 = pow2 << 1 );
w = (pow2 == width) ? width : (pow2 << 1);

/* Round the height to the next lower pow2 if not already a pow2. */
for( pow2 = 1; pow2 < height; pow2 = pow2 << 1 );
h = (pow2 == height) ? height : (pow2 << 1);

/* Clamp to the largest texture size the driver supports. */
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &amp;maxsize );
w = min( w, maxsize );
h = min( h, maxsize );


/*================================================= =============================*/
/* If the original image doesn't have pow2 dimensions then we need to scale it. */
/*================================================= =============================*/
if ( w != width &amp;#0124; &amp;#0124; h != height )
{
/* Allocate memory for the new scaled image. Note that I allocate the worst*/
/* case size just to be simple. This routine shouldn't be used to scale */
/* textures really... I also could have allocated a larger texture and then */
/* modify the (s,t) and use this texture to generate the others. People */
/* should be scaling to pow2 long before run-time. */
image = malloc( (w+4) * h * (sizeof(GLfloat)*4) );
if ( image == NULL )
return GLU_OUT_OF_MEMORY;

/* Use the OpenGL API to scale it. */
error = gluScaleImage( format, width, height, type, data, w, h,type, image );
if ( error )
return error;
}
else
{
/* Use the supplied data. */
image = (void *)data;
}

/*================================================= ==============*/
/* Save the current OpenGL state machine to be restored on exit. */
/*================================================= ==============*/
glPushAttrib( GL_ALL_ATTRIB_BITS );

/* Save the both matrix before we modify. */
glMatrixMode( GL_MODELVIEW );
glPushMatrix();

glMatrixMode( GL_MODELVIEW );
glLoadIdentity();

glMatrixMode( GL_PROJECTION );
glPushMatrix();

/* Make sure the texture gets drawn without effects. */
glDisable( GL_ALPHA_TEST );
glDisable( GL_BLEND );
glDisable( GL_CULL_FACE );
glDisable( GL_DEPTH_TEST );
glDisable( GL_FOG );
glDisable( GL_LIGHTING );

glEnable( GL_TEXTURE_2D );
glReadBuffer( GL_BACK );


/*================================================= ======================*/
/* Create a texture using the valid image. This texture is used to draw */
/* all the other texture levels. */
/*================================================= ======================*/
glTexImage2D( target, 0, component, w, h, 0, format, type, image );

/* Set the texture to do linear filtering. */
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE );

/* If we had to scale the original image then we need to free */
/* the memory that we allocated to hold it. */
if ( image != data )
free( image );

/* Setup the transformation pipeline for 2D. */
glLoadIdentity();
glGetIntegerv( GL_VIEWPORT, v );
glOrtho( (float)viewport[0], (float)viewport[2],
(float)viewport[1], (float)viewport[3],
0.0, 1.0 );


/**================================================ ============================*/
/* Continue to create a new mipmap level until both of the dimensionsequal 1. */
/**================================================ ============================*/
for( level = 1; (w != 1) &amp;&amp; (h != 1 ); level++ )
{
/* Shift the dimensions to the next level. */
w = w >> 1;
h = h >> 1;

/* As mipmap filtering is off... we can use the level 0 texture to */
/* draw this level for us so that the cards filtering gets used. */
glBegin( GL_QUADS );
glTexCoord2f( 0.0, 0.0 );
glVertex2i( 0, 0 );

glTexCoord2f( 1.0, 0.0 );
glVertex2i( w, 0 );

glTexCoord2f( 1.0, 1.0 );
glVertex2i( w, h );

glTexCoord2f( 0.0, 1.0 );
glVertex2i( 0, h );
glEnd();

/* Read the pixels back into this texture level. */
glCopyTexImage2D( target, level, component, 0, 0, w, h, 0 );
}

/*===================================*/
/* Restore the OpenGL state machine. */
/*===================================*/
glMatrixMode( GL_PROJECTION );
glPopMatrix();

glMatrixMode( GL_MODELVIEW );
glPopMatrix();

glPopAttrib();

return 0;
}