Keith Whitwell wrote:
> Andy Ross wrote:
> > ATI blows you guys away in glxgears.  I see 38% faster frame rates
> > with their drivers.
>
> Actually what gears does most is glClear and glXSwapBuffers, with a
> small amount of glCallList.  You can speed up swapbuffers by turning
> page flipping on in the XF86Config - there are some correctness issues
> which is why it isn't always on.  ATI have proprietry hw interfaces
> for implementing glClear that we'll never have access too and this is
> a big hit

It looks like the display list optimizations would be the bigger win.
The 38% number is close to the asymptote (I saw about 32%) as the
window size approaches infinity.  Shrinking the window down to just a
handful of pixels gives a 2x advantage to ATI.

> > You also don't exhibit a texture border bug that the ATI drivers have
>
> We fallback on some texture border cases

OK, after more reading of the spec and Brian's comments and writing a
quick glut test, I think I've got a handle on what's going on.  It
turns out that outside of software Mesa and the ATI linux drivers, no
one in the free world interprets the GL_CLAMP wrap mode correctly.
Everyone else, including the DRI drivers, uses it as a synonym for
GL_CLAMP_TO_EDGE.  As it happens, FlightGear (at least) depends on
this misinterpretation.

[For those interested, this also turns out to be the source of the
 performance issue I mentioned with the ATI drivers.  In trying to be
 correct, they end up taking a slow path with GL_CLAMP that halves the
 frame rate in FlightGear when close to a runway.  Changing all the
 usage to GL_CLAMP_TO_EDGE got almost a 2x speedup.]

So technically, there is a DRI compliance issue here.  I've attached
the little test that I wrote to illustrate the problem.  It draws four
adjacent checkerboard quads and cycles between the wrap modes on key
presses. With GL_CLAMP, you should see dark stripes along the quad
edges where the black border color is sampled.  Software mesa gets
this right, but the r200 driver doesn't.

But since no one else does this correctly, and fixing it breaks
FlightGear, my vote is to ignore the issue. :)

Andy

-- 
Andrew J. Ross                NextBus Information Systems
Senior Software Engineer      Emeryville, CA
[EMAIL PROTECTED]              http://www.nextbus.com
"Men go crazy in conflagrations.  They only get better one by one."
 - Sting (misquoted)
#include <stdio.h>

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#define TSZ 32

unsigned char tex[TSZ*TSZ*3];
int state = 0;

/* Tile the texture using four exactly adjacent quads */
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glBegin(GL_QUADS);

    glTexCoord2f(0, 0);  glVertex2f(-0.5, -0.5);
    glTexCoord2f(0, 1);  glVertex2f(-0.5,  0.0);
    glTexCoord2f(1, 1);  glVertex2f( 0.0,  0.0);
    glTexCoord2f(1, 0);  glVertex2f( 0.0, -0.5);
    
    glTexCoord2f(0, 0);  glVertex2f(-0.5, 0.0);
    glTexCoord2f(0, 1);  glVertex2f(-0.5, 0.5);
    glTexCoord2f(1, 1);  glVertex2f( 0.0, 0.5);
    glTexCoord2f(1, 0);  glVertex2f( 0.0, 0.0);

    glTexCoord2f(0, 0);  glVertex2f( 0.0, 0.0);
    glTexCoord2f(0, 1);  glVertex2f( 0.0, 0.5);
    glTexCoord2f(1, 1);  glVertex2f( 0.5, 0.5);
    glTexCoord2f(1, 0);  glVertex2f( 0.5, 0.0);
    
    glTexCoord2f(0, 0);  glVertex2f( 0.0, -0.5);
    glTexCoord2f(0, 1);  glVertex2f( 0.0,  0.0);
    glTexCoord2f(1, 1);  glVertex2f( 0.5,  0.0);
    glTexCoord2f(1, 0);  glVertex2f( 0.5, -0.5);

    glEnd();
    glutSwapBuffers();
}

/* Cycle the texture border mode when the user presses a key */
void keyboard(unsigned char k, int mx, int my)
{
    if(state == 0) {
        printf("GL_CLAMP_TO_EDGE\n");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    } else if(state == 1) {
        printf("GL_CLAMP\n");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    } else if(state == 2) {
        printf("GL_REPEAT\n");
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    }
    if(++state >= 3)
        state = 0;
    glutPostRedisplay();
}

/* Generate a 33%/66% gray mipmapped checkerboard. */
void init()
{
    int i, j;
    for(i=0; i<TSZ; i++) {
        for(j=0; j<TSZ; j++) {
            unsigned char* pix = tex + 3*(i*TSZ + j);
            pix[0] = pix[1] = pix[2] = (i+j)&1 ? 170 : 85;
       }
    }

    gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, TSZ, TSZ, GL_RGB,
                      GL_UNSIGNED_BYTE, tex);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_LINEAR);

    glEnable(GL_TEXTURE_2D);
    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
}

int main(int argc, char** argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(512, 512);
    glutCreateWindow("Texture Border Test");
    glutDisplayFunc(display);
    glutKeyboardFunc(keyboard);

    init();
    
    glutMainLoop();
}

Reply via email to