Merge commit 'origin/master' into gallium-0.2
[mesa.git] / progs / tests / calibrate_rast.c
1 /*
2 * Automatic primitive rasterization precision test.
3 *
4 * Draw prims at various sub-pixel offsets and examine where the quad is
5 * actually drawn.
6 * Check if the range of offsets which paint the right pixels falls within
7 * OpenGL's specification.
8 * In case of failures, report the coordinate bias needed to fix the problem.
9 *
10 * Note that even Mesa/swrast fails some line tests. This is because some
11 * window coordinates wind up as 53.9999 instead of 54, for example. Enabling
12 * the small translation factor below fixes that. Revisit someday...
13 *
14 * Brian Paul
15 * 28 Feb 2008
16 */
17
18
19 #include <assert.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <GL/glut.h>
23
24
25 static int Width = 100, Height = 100;
26 static int Win;
27 static float Step = 0.125;
28 #if 0
29 /* This tiny offset fixes errors in Mesa/Xlib */
30 static float Xtrans = 0.5 * 0.125;
31 static float Ytrans = 0.5 * 0.125;
32 #else
33 static float Xtrans = 0.0;
34 static float Ytrans = 0.0;
35 #endif
36
37
38 static void
39 PointCalibrate(int xpos, int ypos)
40 {
41 GLfloat rgba[4];
42 float x, y;
43 float xmin, ymin, xmax, ymax;
44
45 xmin = ymin = 1000.0;
46 xmax = ymax = -1000.0;
47
48 for (y = -1.0; y <= 1.0; y += Step) {
49 for (x = -1.0; x <= 1.0; x += Step) {
50 glClear(GL_COLOR_BUFFER_BIT);
51 glBegin(GL_POINTS);
52 glVertex2f(xpos + x, ypos + y);
53 glEnd();
54 glReadPixels(xpos, ypos, 1, 1, GL_RGBA, GL_FLOAT, rgba);
55 if (rgba[0] == 1.0 && rgba[1] == 1.0 && rgba[2] == 1.0) {
56 /* hit */
57 if (x < xmin)
58 xmin = x;
59 if (y < ymin)
60 ymin = y;
61 if (x > xmax)
62 xmax = x;
63 if (y > ymax)
64 ymax = y;
65 }
66 }
67 }
68
69 printf("Point at (%2d, %2d) drawn for x in [%6.3f, %6.3f] and y in [%6.3f, %6.3f]\n",
70 xpos, ypos,
71 xpos + xmin, xpos + xmax,
72 ypos + ymin, ypos + ymax);
73
74 if (xmax - xmin != 1.0 - Step) {
75 printf(" => Inconsistant X-axis rasterization!\n");
76 }
77 if (ymax - ymin != 1.0 - Step) {
78 printf(" => Inconsistant Y-axis rasterization!\n");
79 }
80 if (xmin < 0.0) {
81 printf(" => Points should be X biased by about %f\n", xmin);
82 }
83 if (ymin < 0.0) {
84 printf(" => Points should be Y biased by about %f\n", ymin);
85 }
86 if (xmax > 1.0) {
87 printf(" => Points should be X biased by about %f\n", 1.0 - xmax);
88 }
89 if (ymax > 1.0) {
90 printf(" => Points should be Y biased by about %f\n", 1.0 - ymax);
91 }
92
93 }
94
95
96 /**
97 * XXX Implement VLineCalibrate() someday
98 */
99 static void
100 HLineCalibrate(int xpos, int ypos, int len)
101 {
102 GLfloat rgba[2][4];
103 float x, y;
104 float ymin, ymax;
105 float xmin_left, xmax_left, xmin_right, xmax_right;
106
107 xmin_left = xmin_right = 1000.0;
108 xmax_left = xmax_right = -1000.0;
109 ymin = 1000;
110 ymax = -1000.0;
111
112 /*
113 * First, check vertical positioning of the horizontal line
114 */
115 for (y = -1.0; y <= 1.0; y += Step) {
116 glClear(GL_COLOR_BUFFER_BIT);
117 glBegin(GL_LINES);
118 glVertex2f(xpos, ypos + y);
119 glVertex2f(xpos + len, ypos + y);
120 glEnd();
121
122 glReadPixels(xpos + len / 2, ypos, 1, 1, GL_RGBA, GL_FLOAT, rgba);
123 if (rgba[0][0] == 1.0) {
124 /* hit */
125 if (y < ymin)
126 ymin = y;
127 if (y > ymax)
128 ymax = y;
129 }
130 }
131
132 printf("H-line at Y=%2d drawn for y in [%6.3f, %6.3f]\n",
133 ypos,
134 ypos + ymin, ypos + ymax);
135
136 if (ymax - ymin != 1.0 - Step) {
137 printf(" => Inconsistant Y-axis rasterization!\n");
138 }
139
140 if (ymin > 0.5 ) {
141 printf(" => Lines should be Y biased by about %f\n", ymin - 0.5);
142 }
143
144 if (ymax < 0.5 ) {
145 printf(" => Lines should be Y biased by about %f\n", 0.5 - ymax);
146 }
147
148 /*
149 * Second, check endpoints (for Y at 1/2 pixel)
150 */
151 for (x = -1.0; x <= 1.0; x += Step) {
152 glClear(GL_COLOR_BUFFER_BIT);
153 glBegin(GL_LINES);
154 glVertex2f(xpos + x, ypos + 0.5f);
155 glVertex2f(xpos + x + len, ypos + 0.5f);
156 glEnd();
157
158 /* left end */
159 glReadPixels(xpos - 1, ypos, 2, 1, GL_RGBA, GL_FLOAT, rgba);
160 if (rgba[0][0] == 0.0 && rgba[1][0] == 1.0) {
161 /* hit */
162 if (x < xmin_left)
163 xmin_left = x;
164 if (x > xmax_left)
165 xmax_left = x;
166 }
167
168 /* right end */
169 glReadPixels(xpos + len - 1, ypos, 2, 1, GL_RGBA, GL_FLOAT, rgba);
170 if (rgba[0][0] == 1.0 && rgba[1][0] == 0.0) {
171 /* hit */
172 if (x < xmin_right)
173 xmin_right = x;
174 if (x > xmax_right)
175 xmax_right = x;
176 }
177 }
178
179 printf("H-line [%d..%d) hit left end for x in [%6.3f, %6.3f] "
180 "hit right end for x in [%6.3f, %6.3f]\n",
181 xpos, xpos + len,
182 xpos + xmin_left, xpos + xmax_left,
183 xpos + len + xmin_right, xpos + len + xmax_right);
184
185 if (xmax_left - xmin_left > 1.0 - Step) {
186 printf(" => Inconsistant left-end rasterization!\n");
187 }
188 if (xmax_right - xmin_right > 1.0 - Step) {
189 printf(" => Inconsistant right-end rasterization!\n");
190 }
191
192 if (xmin_left != xmin_right ||
193 xmax_left != xmax_right) {
194 printf(" => Inconsistant length!\n");
195 }
196
197 if (xmin_left < 0.0) {
198 printf(" => Coords should be X biased by about %f\n", xmin_left );
199 }
200 if (xmin_right < 0.0) {
201 printf(" => Coords should be X biased by about %f\n", xmin_right );
202 }
203 if (xmax_left >= 1.0) {
204 printf(" => Coords should be X biased by about %f\n", -xmax_right + 1.0);
205 }
206 if (xmax_right >= 1.0) {
207 printf(" => Coords should be X biased by about %f\n", -xmax_right + 1.0);
208 }
209
210 }
211
212
213 static void
214 QuadCalibrate(int xpos, int ypos, int width, int height)
215 {
216 GLfloat rgba1[2][4];
217 GLfloat rgba2[2][4];
218 float x, y;
219 float xmin, ymin, xmax, ymax;
220
221 xmin = ymin = 1000.0;
222 xmax = ymax = -1000.0;
223
224 for (y = -1.0; y <= 1.0; y += Step) {
225 for (x = -1.0; x <= 1.0; x += Step) {
226 glClear(GL_COLOR_BUFFER_BIT);
227 glBegin(GL_QUADS);
228 glVertex2f(xpos + x, ypos + y);
229 glVertex2f(xpos + x + width, ypos + y);
230 glVertex2f(xpos + x + width, ypos + y + height);
231 glVertex2f(xpos + x, ypos + y + height);
232 glEnd();
233
234 /* horizontal measurement */
235 glReadPixels(xpos - 1, ypos + 2, 2, 1, GL_RGBA, GL_FLOAT, rgba1);
236 glReadPixels(xpos + width - 1, ypos + 2, 2, 1, GL_RGBA, GL_FLOAT, rgba2);
237 if (rgba1[0][0] == 0.0 && rgba1[1][0] == 1.0 &&
238 rgba2[0][0] == 1.0 && rgba2[1][0] == 0.0) {
239 if (x < xmin)
240 xmin = x;
241 if (x > xmax)
242 xmax = x;
243 }
244
245 /* vertical measurement */
246 glReadPixels(xpos + 2, ypos - 1, 1, 2, GL_RGBA, GL_FLOAT, rgba1);
247 glReadPixels(xpos + 2, ypos + height - 1, 1, 2, GL_RGBA, GL_FLOAT, rgba2);
248 if (rgba1[0][0] == 0.0 && rgba1[1][0] == 1.0 &&
249 rgba2[0][0] == 1.0 && rgba2[1][0] == 0.0) {
250 if (y < ymin)
251 ymin = y;
252 if (y > ymax)
253 ymax = y;
254 }
255 }
256 }
257
258 printf("Quad at (%2d, %2d)..(%2d, %2d) drawn"
259 " for x in [%6.3f, %6.3f] and y in [%6.3f, %6.3f]\n",
260 xpos, ypos,
261 xpos + width, ypos + height,
262 xpos + xmin, xpos + xmax,
263 ypos + ymin, ypos + ymax);
264
265 if (xmax - xmin != 1.0 - Step) {
266 printf(" => Inconsistant X-axis rasterization/size!\n");
267 }
268 if (ymax - ymin != 1.0 - Step) {
269 printf(" => Inconsistant Y-axis rasterization/size!\n");
270 }
271
272 if (xmin < -0.5) {
273 printf(" => Coords should be X biased by about %f\n", 0.5 + xmin );
274 }
275 if (ymin < -0.5) {
276 printf(" => Coords should be Y biased by about %f\n", 0.5 + ymin);
277 }
278 if (xmax > 0.5) {
279 printf(" => Coords should be X biased by about %f\n", -xmax + 0.5);
280 }
281 if (ymax > 0.5) {
282 printf(" => Coords should be Y biased by about %f\n", -ymax + 0.5);
283 }
284 }
285
286
287 /**
288 * Misc/disabled code for debugging.
289 */
290 static void
291 DebugTest(void)
292 {
293 glClear(GL_COLOR_BUFFER_BIT);
294 glEnable(GL_BLEND);
295 glBlendFunc(GL_ONE, GL_ONE);
296
297 glColor3f(.5, .5, .5);
298
299 glBegin(GL_LINES);
300 glVertex2f(30, 35.5);
301 glVertex2f(54, 35.5);
302 glVertex2f(54, 35.5);
303 glVertex2f(66, 35.5);
304 glEnd();
305
306 glDisable(GL_BLEND);
307 glColor3f(1,1,1);
308 }
309
310
311 static void
312 Draw(void)
313 {
314 glClear(GL_COLOR_BUFFER_BIT);
315
316 glPushMatrix();
317 glTranslatef(Xtrans, Ytrans, 0);
318
319 PointCalibrate(1, 1);
320 PointCalibrate(50, 50);
321 PointCalibrate(28, 17);
322 PointCalibrate(17, 18);
323 printf("\n");
324
325 HLineCalibrate(5, 10, 10);
326 HLineCalibrate(25, 22, 12);
327 HLineCalibrate(54, 33, 12);
328 HLineCalibrate(54+12, 33, 12);
329 printf("\n");
330
331 QuadCalibrate(2, 2, 10, 10);
332 QuadCalibrate(50, 50, 10, 10);
333 QuadCalibrate(28, 17, 12, 12);
334 QuadCalibrate(17, 28, 12, 12);
335
336 (void) DebugTest;
337
338 glPopMatrix();
339
340 glutSwapBuffers();
341 }
342
343
344 static void
345 Reshape(int width, int height)
346 {
347 Width = width;
348 Height = height;
349 glViewport(0, 0, width, height);
350 glMatrixMode(GL_PROJECTION);
351 glLoadIdentity();
352 glOrtho(0, width, 0, height, -1, 1);
353 glMatrixMode(GL_MODELVIEW);
354 glLoadIdentity();
355 }
356
357
358 static void
359 Key(unsigned char key, int x, int y)
360 {
361 (void) x;
362 (void) y;
363 switch (key) {
364 case 27:
365 glutDestroyWindow(Win);
366 exit(0);
367 break;
368 }
369 glutPostRedisplay();
370 }
371
372
373 static void
374 Init(void)
375 {
376 printf("Measurement/callibration for basic prim rasterization...\n");
377 printf("GL_RENDERER: %s\n", (char*) glGetString(GL_RENDERER));
378 }
379
380
381 int
382 main(int argc, char *argv[])
383 {
384 glutInit(&argc, argv);
385 glutInitWindowPosition(0, 0);
386 glutInitWindowSize(Width, Height);
387 glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
388 Win = glutCreateWindow(argv[0]);
389 glutReshapeFunc(Reshape);
390 glutKeyboardFunc(Key);
391 glutDisplayFunc(Draw);
392 Init();
393 glutMainLoop();
394 return 0;
395 }