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