zeckensack
03-02-2002, 10:03 AM
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 http://www.opengl.org/discussion_boards/ubb/smile.gif
//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)wglG etProcAddress("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_FILTE R,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,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_CO MBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_TEX TURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEX TURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_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_CO MBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_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_CO MBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT 3_RGB_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_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_DOT 3_RGB_ARB);
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
break;
case(1):
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT 3_RGB_ARB);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
break;
case(2):
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT 3_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 http://www.opengl.org/discussion_boards/ubb/smile.gif
[This message has been edited by zeckensack (edited 03-02-2002).]
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 http://www.opengl.org/discussion_boards/ubb/smile.gif
//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)wglG etProcAddress("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_FILTE R,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTE R,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_CO MBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_TEX TURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_TEX TURE);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_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_CO MBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_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_CO MBINE_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT 3_RGB_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE0_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND0_RGB_ARB,GL_SR C_COLOR);
glTexEnvi(GL_TEXTURE_ENV,GL_SOURCE1_RGB_ARB,GL_PRE VIOUS_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_OPERAND1_RGB_ARB,GL_SR C_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_DOT 3_RGB_ARB);
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
break;
case(1):
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT 3_RGB_ARB);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
break;
case(2):
glActiveTextureARB(GL_TEXTURE0_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE1_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_REP LACE);
glActiveTextureARB(GL_TEXTURE2_ARB);
glTexEnvi(GL_TEXTURE_ENV,GL_COMBINE_RGB_ARB,GL_DOT 3_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 http://www.opengl.org/discussion_boards/ubb/smile.gif
[This message has been edited by zeckensack (edited 03-02-2002).]