I’ve found what I assume to be a bug in the OpenGL driver or underlying hardware.
hardware/software version concerned:
The issue concerns the original Radeon series of chips (pre 8500) and has only been verified on this earlier series (Radeon 32 DDR to be exact), using the officialy released 4.13.9009 driverset on Windows 98SE.
description of issue:
When the third texture environment is configured to perform a DOT3 operation, the results of this operation are wrong. More specifically, the output of the DOT3 operation is not even a scalar but a full ‘funky’ color result. This happens only on the third texture environment.
reproduction of issue:
I have attached C source code for a minimal application, using the glut library, that can visually demonstrate the issue.
The application activates GL_COMBINE_ARB for all three texture units.
The application then configures the texture environment pipeline to perform decal texturing on the first environment, passthrough on the second and the DOT3 operation on the third texture environment. The same texture referenced on the first environment is used as a dummy texture for the second and third environments.
With the space bar the user can cycle the position of the dot3 operation in the pipeline through the environments to observe the results of different configurations.
These configs should all yield the same result, but they don’t
configurations that can be cycled through:
Dot3 on tex env 2 (default configuration):
env0 does replace operation with source=texture, operand=source_color
env1 does replace operation with source=previous, operand=source_color
env2 does DOT3_RGB_ARB operation with sources=previous,previous, operands=source_color,source_color
Dot3 on tex env 0:
env0 does DOT3_RGB_ARB operation with sources=texture,texture, operands=source_color,source_color
env1 does replace operation with source=previous, operand=source_color
env2 does replace operation with source=previous, operand=source_color
Dot3 on tex env 1:
env0 does replace operation with source=texture, operand=source_color
env1 does DOT3_RGB_ARB operation with sources=texture,texture, operands=source_color,source_color
env2 does replace operation with source=previous, operand=source_color
I still hope I’m wrong
//Demonstrates a flaw in Dot3 operations on the ATI Radeon's (original) third texture environment //Flaw can be reproduced on Win98SE systems with the official driver set 4.13.9009 //version number of ATIICDXX.DLL is 6.13.10.6014 //reported GL version is 1.3.2454 //Make sure to link with glut #include <windows.h> #include <gl/gl.h> #include <gl/glati.h> #include <gl/glu.h> #include <gl/glut.h> #include <stdio.h> #include <malloc.h> char description[64]; PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; static unsigned char* texture_data=NULL; static GLuint tex_obj=0; static int dot_unit=2; void init_gl_stuff() { glActiveTextureARB=(PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB"); glClearColor(0.0f,0.0f,0.0f,0.0f); glGenTextures(1,&tex_obj); texture_data=(unsigned char*)malloc(64*64*3); //generate nice texture for (int x=0;x<64;++x) { for (int y=0;y<64;++y) { texture_data[(x+64*y)*3]=(unsigned char)4*x; texture_data[(x+64*y)*3+1]=(unsigned char)4*y; texture_data[(x+64*y)*3+2]=(unsigned char)255-x-y; } } glBindTexture(GL_TEXTURE_2D,tex_obj); glTexImage2D(GL_TEXTURE_2D,0,GL_RGB,64,64,0,GL_RGB,GL_UNSIGNED_BYTE,texture_data); free(texture_data); texture_data=NULL; //mipmaps not required for this demonstration glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE_EXT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE_EXT); //whip up a minimum projection glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0,640,480,0); //set all three texture environments to COMBINE_ARB operation, select same sources and operands //tex environment0 will do decal texturing glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SRC_COLOR); //tex environment1 will pass through glActiveTextureARB(GL_TEXTURE1_ARB); glBindTexture(GL_TEXTURE_2D,tex_obj); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SRC_COLOR); //tex environment2 will perform the dot3 operation glActiveTextureARB(GL_TEXTURE2_ARB); glBindTexture(GL_TEXTURE_2D,tex_obj); glEnable(GL_TEXTURE_2D); glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT3_RGB_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PREVIOUS_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SRC_COLOR); } int cleanup() { if (tex_obj) { glDeleteTextures(1,&tex_obj); tex_obj=0; } return(0); } void display() { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glBegin(GL_QUADS); glTexCoord2f(0.0f,0.0f); glVertex2f(0.0f,0.0f); glTexCoord2f(1.0f,0.0f); glVertex2f(320.0f,0.0f); glTexCoord2f(1.0f,1.0f); glVertex2f(320.0f,320.0f); glTexCoord2f(0.0f,1.0f); glVertex2f(0.0f,320.0f); glEnd(); glutSwapBuffers(); return; } void keyboard(unsigned char key,int x,int y) { //check for spacebar if (key!=0x20) return; //flip the switch ++dot_unit; if (dot_unit==3) dot_unit=0; //reassign texture environments switch (dot_unit) { default: case(0): glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT3_RGB_ARB); glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); glActiveTextureARB(GL_TEXTURE2_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); break; case(1): glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT3_RGB_ARB); glActiveTextureARB(GL_TEXTURE2_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); break; case(2): glActiveTextureARB(GL_TEXTURE0_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); glActiveTextureARB(GL_TEXTURE1_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REPLACE); glActiveTextureARB(GL_TEXTURE2_ARB); glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT3_RGB_ARB); break; } //update description sprintf(description,"Dot3 operation on texture environment%u",dot_unit); glutSetWindowTitle(description); glutPostRedisplay(); } int main(int argc,char** argv) { sprintf(description,"Press space to reassign texture environments"); glutInit(&argc,argv); glutInitWindowSize(640,480); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE); glutCreateWindow(description); init_gl_stuff(); glutDisplayFunc(display); glutKeyboardFunc(keyboard); onexit(cleanup); glutMainLoop(); return(0); }
Oh, and I’d like to see verification or … err … the opposite of verification from Radeon8500 users
[This message has been edited by zeckensack (edited 03-02-2002).]