1 /**
2  * Test for exact point/line/polygon rasterization, or at least rasterization
3  * that fits the tolerance of the OpenGL spec.
4  *
5  * Brian Paul
6  * 9 Nov 2007
7  */
8 
9 /*
10  * Notes:
11  * - 'm' to cycle through point, hline, vline and quad drawing
12  * - Use cursor keys to translate coordinates (z to reset)
13  * - Resize window to check for proper rasterization
14  * - Make sure your LCD is running in its native resolution
15  *
16  * If translation is (0,0):
17  *  a point will be drawn where x%2==0 and y%2==0,
18  *  a horizontal line will be drawn where x%2==0,
19  *  a vertical line will be drawn where y%2==0,
20  *  for quads, pixels will be set where (x%4)!=3 and (y%4)!=3
21  *
22  * XXX todo: do glReadPixels and test that the results are what's expected.
23  * Upon failure, iterate over sub-pixel translations to find the ideal offset.
24  */
25 
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <GL/glew.h>
30 #include "glut_wrap.h"
31 
32 static int Width = 400, Height = 400;
33 static int Win;
34 static float Xtrans = 0, Ytrans = 0;
35 static float Step = 0.125;
36 
37 enum {
38    MODE_POINTS,
39    MODE_HLINES,
40    MODE_VLINES,
41    MODE_QUADS,
42    NUM_MODES
43 };
44 
45 static int Mode = MODE_POINTS;
46 
47 
48 static void
Draw(void)49 Draw(void)
50 {
51    /* See the OpenGL Programming Guide, Appendix H, "OpenGL Correctness Tips"
52     * for information about the 0.375 translation factor.
53     */
54    float tx = 0.375, ty = 0.375;
55    int i, j;
56 
57    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
58 
59    glPushMatrix();
60    glTranslatef(tx + Xtrans, ty + Ytrans, 0);
61 
62    if (Mode == MODE_POINTS) {
63       glBegin(GL_POINTS);
64       for (j = 0; j < Height; j += 2) {
65          for (i = 0; i < Width; i += 2) {
66             glVertex2f(i, j);
67          }
68       }
69       glEnd();
70    }
71    else if (Mode == MODE_HLINES) {
72       glBegin(GL_LINES);
73       for (i = 0; i < Height; i += 2) {
74          glVertex2f(0,     i);
75          glVertex2f(Width, i);
76       }
77       glEnd();
78    }
79    else if (Mode == MODE_VLINES) {
80       glBegin(GL_LINES);
81       for (i = 0; i < Width; i += 2) {
82          glVertex2f(i, 0     );
83          glVertex2f(i, Height);
84       }
85       glEnd();
86    }
87    else if (Mode == MODE_QUADS) {
88       glBegin(GL_QUADS);
89       for (j = 0; j < Height; j += 4) {
90          for (i = 0; i < Width; i += 4) {
91             glVertex2f(i,     j    );
92             glVertex2f(i + 3, j    );
93             glVertex2f(i + 3, j + 3);
94             glVertex2f(i,     j + 3);
95          }
96       }
97       glEnd();
98    }
99 
100    glPopMatrix();
101 
102    glutSwapBuffers();
103 }
104 
105 
106 static void
Reshape(int width,int height)107 Reshape(int width, int height)
108 {
109    Width = width;
110    Height = height;
111    glViewport(0, 0, width, height);
112    glMatrixMode(GL_PROJECTION);
113    glLoadIdentity();
114    glOrtho(0, width, 0, height, -1, 1);
115    glMatrixMode(GL_MODELVIEW);
116    glLoadIdentity();
117 }
118 
119 
120 static void
Key(unsigned char key,int x,int y)121 Key(unsigned char key, int x, int y)
122 {
123    (void) x;
124    (void) y;
125    switch (key) {
126    case 'm':
127    case 'M':
128       Mode = (Mode + 1) % NUM_MODES;
129       break;
130    case 'z':
131    case 'Z':
132       Xtrans = Ytrans = 0;
133       printf("Translation: %f, %f\n", Xtrans, Ytrans);
134       break;
135    case 27:
136       glutDestroyWindow(Win);
137       exit(0);
138       break;
139    }
140    glutPostRedisplay();
141 }
142 
143 
144 static void
SpecialKey(int key,int x,int y)145 SpecialKey(int key, int x, int y)
146 {
147    (void) x;
148    (void) y;
149    switch (key) {
150    case GLUT_KEY_UP:
151       Ytrans += Step;
152       break;
153    case GLUT_KEY_DOWN:
154       Ytrans -= Step;
155       break;
156    case GLUT_KEY_LEFT:
157       Xtrans -= Step;
158       break;
159    case GLUT_KEY_RIGHT:
160       Xtrans += Step;
161       break;
162    }
163    glutPostRedisplay();
164    printf("Translation: %f, %f\n", Xtrans, Ytrans);
165 }
166 
167 
168 static void
Init(void)169 Init(void)
170 {
171 }
172 
173 
174 static void
Usage(void)175 Usage(void)
176 {
177    printf("Keys:\n");
178    printf("  up/down/left/right - translate by %f\n", Step);
179    printf("  z - reset translation to zero\n");
180    printf("  m - change rendering mode (points, hlines, vlines, quads)\n");
181    printf("  Esc - exit\n");
182 }
183 
184 
185 int
main(int argc,char * argv[])186 main(int argc, char *argv[])
187 {
188    glutInit(&argc, argv);
189    glutInitWindowPosition(0, 0);
190    glutInitWindowSize(Width, Height);
191    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
192    Win = glutCreateWindow(argv[0]);
193    glewInit();
194    glutReshapeFunc(Reshape);
195    glutKeyboardFunc(Key);
196    glutSpecialFunc(SpecialKey);
197    glutDisplayFunc(Draw);
198    Init();
199    Usage();
200    glutMainLoop();
201    return 0;
202 }
203