mesa: added new linux-gallium and linux-gallium-debug configs
[mesa.git] / progs / xdemos / offset.c
1 /****************************************************************************
2 Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
3
4 All Rights Reserved
5
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of Silicon Graphics not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
13
14 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
18 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 PERFORMANCE OF THIS SOFTWARE.
21
22 ****************************************************************************/
23
24 /*
25 * Derived from code written by Kurt Akeley, November 1992
26 *
27 * Uses PolygonOffset to draw hidden-line images. PolygonOffset
28 * shifts the z values of polygons an amount that is
29 * proportional to their slope in screen z. This keeps
30 * the lines, which are drawn without displacement, from
31 * interacting with their respective polygons, and
32 * thus eliminates line dropouts.
33 *
34 * The left image shows an ordinary antialiased wireframe image.
35 * The center image shows an antialiased hidden-line image without
36 * PolygonOffset.
37 * The right image shows an antialiased hidden-line image using
38 * PolygonOffset to reduce artifacts.
39 *
40 * Drag with a mouse button pressed to rotate the models.
41 * Press the escape key to exit.
42 */
43
44 /*
45 * Modified for OpenGL 1.1 glPolygonOffset() conventions
46 */
47
48
49 #include <GL/glx.h>
50 #include <X11/keysym.h>
51 #include <stdlib.h>
52 #include <stdio.h>
53 #include <string.h>
54
55 #undef GL_EXT_polygon_offset /* use GL 1.1 version instead of extension */
56
57
58 #ifndef EXIT_FAILURE
59 # define EXIT_FAILURE 1
60 #endif
61 #ifndef EXIT_SUCCESS
62 # define EXIT_SUCCESS 0
63 #endif
64
65 #define MAXQUAD 6
66
67 typedef float Vertex[3];
68
69 typedef Vertex Quad[4];
70
71 /* data to define the six faces of a unit cube */
72 Quad quads[MAXQUAD] = {
73 { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */
74 { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */
75 { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */
76 { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */
77 { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */
78 { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} } /* z = 1 */
79 };
80
81 #define WIREFRAME 0
82 #define HIDDEN_LINE 1
83
84 static void error(const char* prog, const char* msg);
85 static void cubes(int mx, int my, int mode);
86 static void fill(Quad quad);
87 static void outline(Quad quad);
88 static void draw_hidden(Quad quad, int mode, int face);
89 static void process_input(Display *dpy, Window win);
90 static int query_extension(char* extName);
91
92 static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1,
93 GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None };
94
95 static int dimension = 3;
96
97 int main(int argc, char** argv) {
98 Display *dpy;
99 XVisualInfo *vi;
100 XSetWindowAttributes swa;
101 Window win;
102 GLXContext cx;
103 GLint z;
104
105 dpy = XOpenDisplay(0);
106 if (!dpy) error(argv[0], "can't open display");
107
108 vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
109 if (!vi) error(argv[0], "no suitable visual");
110
111 cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
112
113 swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
114 vi->visual, AllocNone);
115
116 swa.border_pixel = 0;
117 swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
118 ButtonPressMask | ButtonMotionMask;
119 win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300,
120 0, vi->depth, InputOutput, vi->visual,
121 CWBorderPixel|CWColormap|CWEventMask, &swa);
122 XStoreName(dpy, win, "hiddenline");
123 XMapWindow(dpy, win);
124
125 glXMakeCurrent(dpy, win, cx);
126
127 /* check for the polygon offset extension */
128 #ifndef GL_VERSION_1_1
129 if (!query_extension("GL_EXT_polygon_offset"))
130 error(argv[0], "polygon_offset extension is not available");
131 #else
132 (void) query_extension;
133 #endif
134
135 /* set up viewing parameters */
136 glMatrixMode(GL_PROJECTION);
137 glFrustum(-1, 1, -1, 1, 6, 20);
138 glMatrixMode(GL_MODELVIEW);
139 glTranslatef(0, 0, -15);
140
141 /* set other relevant state information */
142 glEnable(GL_DEPTH_TEST);
143
144 glGetIntegerv(GL_DEPTH_BITS, &z);
145 printf("GL_DEPTH_BITS = %d\n", z);
146
147 #ifdef GL_EXT_polygon_offset
148 printf("using 1.0 offset extension\n");
149 glPolygonOffsetEXT( 1.0, 0.00001 );
150 #else
151 printf("using 1.1 offset\n");
152 glPolygonOffset( 1.0, 0.5 );
153 #endif
154
155 glShadeModel( GL_FLAT );
156 glDisable( GL_DITHER );
157
158 /* process events until the user presses ESC */
159 while (1) process_input(dpy, win);
160
161 return 0;
162 }
163
164 static void
165 draw_scene(int mx, int my) {
166 glClearColor(0.25, 0.25, 0.25, 0);
167 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
168
169 glPushMatrix();
170 glTranslatef(-1.7, 0.0, 0.0);
171 cubes(mx, my, WIREFRAME);
172 glPopMatrix();
173
174 glPushMatrix();
175 cubes(mx, my, HIDDEN_LINE);
176 glPopMatrix();
177
178 glPushMatrix();
179 glTranslatef(1.7, 0.0, 0.0);
180 #ifdef GL_EXT_polygon_offset
181 glEnable(GL_POLYGON_OFFSET_EXT);
182 #else
183 glEnable(GL_POLYGON_OFFSET_FILL);
184 #endif
185 cubes(mx, my, HIDDEN_LINE);
186 #ifdef GL_EXT_polygon_offset
187 glDisable(GL_POLYGON_OFFSET_EXT);
188 #else
189 glDisable(GL_POLYGON_OFFSET_FILL);
190 #endif
191 glPopMatrix();
192 }
193
194
195 static void
196 cubes(int mx, int my, int mode) {
197 int x, y, z, i;
198
199 /* track the mouse */
200 glRotatef(mx / 2.0, 0, 1, 0);
201 glRotatef(my / 2.0, 1, 0, 0);
202
203 /* draw the lines as hidden polygons */
204 glTranslatef(-0.5, -0.5, -0.5);
205 glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
206 for (z = 0; z < dimension; z++) {
207 for (y = 0; y < dimension; y++) {
208 for (x = 0; x < dimension; x++) {
209 glPushMatrix();
210 glTranslatef(x, y, z);
211 glScalef(0.8, 0.8, 0.8);
212 for (i = 0; i < MAXQUAD; i++)
213 draw_hidden(quads[i], mode, i);
214 glPopMatrix();
215 }
216 }
217 }
218 }
219
220 static void
221 fill(Quad quad) {
222 /* draw a filled polygon */
223 glBegin(GL_QUADS);
224 glVertex3fv(quad[0]);
225 glVertex3fv(quad[1]);
226 glVertex3fv(quad[2]);
227 glVertex3fv(quad[3]);
228 glEnd();
229 }
230
231 static void
232 outline(Quad quad) {
233 /* draw an outlined polygon */
234 glBegin(GL_LINE_LOOP);
235 glVertex3fv(quad[0]);
236 glVertex3fv(quad[1]);
237 glVertex3fv(quad[2]);
238 glVertex3fv(quad[3]);
239 glEnd();
240 }
241
242 static void
243 draw_hidden(Quad quad, int mode, int face) {
244 static const GLfloat colors[3][3] = {
245 {0.5, 0.5, 0.0},
246 {0.8, 0.5, 0.0},
247 {0.0, 0.5, 0.8}
248 };
249 if (mode == HIDDEN_LINE) {
250 glColor3fv(colors[face % 3]);
251 fill(quad);
252 }
253
254 /* draw the outline using white */
255 glColor3f(1, 1, 1);
256 outline(quad);
257 }
258
259 static void
260 process_input(Display *dpy, Window win) {
261 XEvent event;
262 static int prevx, prevy;
263 static int deltax = 90, deltay = 40;
264
265 do {
266 char buf[31];
267 KeySym keysym;
268
269 XNextEvent(dpy, &event);
270 switch(event.type) {
271 case Expose:
272 break;
273 case ConfigureNotify: {
274 /* this approach preserves a 1:1 viewport aspect ratio */
275 int vX, vY, vW, vH;
276 int eW = event.xconfigure.width, eH = event.xconfigure.height;
277 if (eW >= eH) {
278 vX = 0;
279 vY = (eH - eW) >> 1;
280 vW = vH = eW;
281 } else {
282 vX = (eW - eH) >> 1;
283 vY = 0;
284 vW = vH = eH;
285 }
286 glViewport(vX, vY, vW, vH);
287 }
288 break;
289 case KeyPress:
290 (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
291 switch (keysym) {
292 case XK_Escape:
293 exit(EXIT_SUCCESS);
294 default:
295 break;
296 }
297 case ButtonPress:
298 prevx = event.xbutton.x;
299 prevy = event.xbutton.y;
300 break;
301 case MotionNotify:
302 deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x;
303 deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y;
304 break;
305 default:
306 break;
307 }
308 } while (XPending(dpy));
309
310 draw_scene(deltax, deltay);
311 glXSwapBuffers(dpy, win);
312 }
313
314 static void
315 error(const char *prog, const char *msg) {
316 fprintf(stderr, "%s: %s\n", prog, msg);
317 exit(EXIT_FAILURE);
318 }
319
320 static int
321 query_extension(char* extName) {
322 char *p = (char *) glGetString(GL_EXTENSIONS);
323 char *end = p + strlen(p);
324 while (p < end) {
325 int n = strcspn(p, " ");
326 if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0))
327 return GL_TRUE;
328 p += (n + 1);
329 }
330 return GL_FALSE;
331 }
332