renumber ARB_shader_objects and ARB_vertex_shader offsets
[mesa.git] / progs / xdemos / shape.c
1
2 /*
3 * Example of using the X "shape" extension with OpenGL: render a spinning
4 * cube inside of a non-rectangular window.
5 *
6 * Press ESC to exit. Press up/down to change window shape.
7 *
8 * To compile add "shape" to the PROGS list in Makefile.
9 *
10 * Brian Paul
11 * June 16, 1997
12 *
13 * This program is in the public domain.
14 */
15
16
17 #include <math.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <X11/Xlib.h>
21 #include <X11/Xutil.h>
22 #include <X11/keysym.h>
23 #include <X11/extensions/shape.h>
24 #include <GL/glx.h>
25
26 #ifndef PI
27 #define PI 3.1415926
28 #endif
29
30
31 static int Width=500, Height=500;
32
33 static float Xangle = 0.0, Yangle = 0.0;
34 static int Redraw = 0;
35 static int Sides = 5;
36 static int MinSides = 3;
37 static int MaxSides = 20;
38
39
40 /*
41 * Draw the OpenGL stuff and do a SwapBuffers.
42 */
43 static void display(Display *dpy, Window win)
44 {
45 float scale = 1.7;
46
47 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
48
49 glPushMatrix();
50
51 glScalef(scale, scale, scale);
52 glRotatef(Xangle, 1.0, 0.0, 0.0);
53 glRotatef(Yangle, 0.0, 1.0, 0.0);
54
55 /*
56 * wireframe box
57 */
58 glColor3f(1.0, 1.0, 1.0);
59 glBegin(GL_LINE_LOOP);
60 glVertex3f(-1.0, -1.0, -1.0);
61 glVertex3f( 1.0, -1.0, -1.0);
62 glVertex3f( 1.0, 1.0, -1.0);
63 glVertex3f(-1.0, 1.0, -1.0);
64 glEnd();
65
66 glBegin(GL_LINE_LOOP);
67 glVertex3f(-1.0, -1.0, 1.0);
68 glVertex3f( 1.0, -1.0, 1.0);
69 glVertex3f( 1.0, 1.0, 1.0);
70 glVertex3f(-1.0, 1.0, 1.0);
71 glEnd();
72
73 glBegin(GL_LINES);
74 glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0);
75 glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, 1.0);
76 glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, 1.0, 1.0);
77 glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
78 glEnd();
79
80 /*
81 * Solid box
82 */
83 glPushMatrix();
84 glScalef(0.75, 0.75, 0.75);
85
86 glColor3f(1, 0, 0);
87 glBegin(GL_POLYGON);
88 glVertex3f(1, -1, -1);
89 glVertex3f(1, 1, -1);
90 glVertex3f(1, 1, 1);
91 glVertex3f(1, -1, 1);
92 glEnd();
93
94 glColor3f(0, 1, 1);
95 glBegin(GL_POLYGON);
96 glVertex3f(-1, -1, -1);
97 glVertex3f(-1, 1, -1);
98 glVertex3f(-1, 1, 1);
99 glVertex3f(-1, -1, 1);
100 glEnd();
101
102 glColor3f(0, 1, 0);
103 glBegin(GL_POLYGON);
104 glVertex3f(-1, 1, -1);
105 glVertex3f( 1, 1, -1);
106 glVertex3f( 1, 1, 1);
107 glVertex3f(-1, 1, 1);
108 glEnd();
109
110 glColor3f(1, 0, 1);
111 glBegin(GL_POLYGON);
112 glVertex3f(-1, -1, -1);
113 glVertex3f( 1, -1, -1);
114 glVertex3f( 1, -1, 1);
115 glVertex3f(-1, -1, 1);
116 glEnd();
117
118 glColor3f(0, 0, 1);
119 glBegin(GL_POLYGON);
120 glVertex3f(-1, -1, 1);
121 glVertex3f( 1, -1, 1);
122 glVertex3f( 1, 1, 1);
123 glVertex3f(-1, 1, 1);
124 glEnd();
125
126 glColor3f(1, 1, 0);
127 glBegin(GL_POLYGON);
128 glVertex3f(-1, -1, -1);
129 glVertex3f( 1, -1, -1);
130 glVertex3f( 1, 1, -1);
131 glVertex3f(-1, 1, -1);
132 glEnd();
133 glPopMatrix();
134
135
136 glPopMatrix();
137
138 glXSwapBuffers(dpy, win);
139 }
140
141
142 /*
143 * Called when no events are pending.
144 */
145 static void idle(void)
146 {
147 Xangle += 2.0;
148 Yangle += 3.3;
149 Redraw = 1;
150 }
151
152
153 /*
154 * This is called when we have to recompute the window shape bitmask.
155 * We just generate an n-sided regular polygon here but any other shape
156 * would be possible.
157 */
158 static void make_shape_mask(Display *dpy, Window win, int width, int height,
159 int sides)
160 {
161 Pixmap shapeMask;
162 XGCValues xgcv;
163 GC gc;
164
165 /* allocate 1-bit deep pixmap and a GC */
166 shapeMask = XCreatePixmap(dpy, win, width, height, 1);
167 gc = XCreateGC(dpy, shapeMask, 0, &xgcv);
168
169 /* clear shapeMask to zeros */
170 XSetForeground(dpy, gc, 0);
171 XFillRectangle(dpy, shapeMask, gc, 0, 0, width, height);
172
173 /* draw mask */
174 XSetForeground(dpy, gc, 1);
175 {
176 int cx = width / 2;
177 int cy = height / 2;
178 float angle = 0.0;
179 float step = 2.0 * PI / sides;
180 float radius = width / 2;
181 int i;
182 XPoint points[100];
183 for (i=0;i<sides;i++) {
184 int x = cx + radius * sin(angle);
185 int y = cy - radius * cos(angle);
186 points[i].x = x;
187 points[i].y = y;
188 angle += step;
189 }
190 XFillPolygon(dpy, shapeMask, gc, points, sides, Convex, CoordModeOrigin);
191 }
192
193 /* This is the only SHAPE extension call- simple! */
194 XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, shapeMask, ShapeSet);
195
196 XFreeGC(dpy, gc);
197 XFreePixmap(dpy, shapeMask);
198 }
199
200
201 /*
202 * Called when window is resized. Do OpenGL viewport and projection stuff.
203 */
204 static void reshape(int width, int height)
205 {
206 glViewport(0, 0, width, height);
207 glMatrixMode(GL_PROJECTION);
208 glLoadIdentity();
209 glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
210 glMatrixMode(GL_MODELVIEW);
211 glLoadIdentity();
212 glTranslatef(0.0, 0.0, -10.0);
213
214 glEnable(GL_DEPTH_TEST);
215 }
216
217
218 /*
219 * Process X events.
220 */
221 static void event_loop(Display *dpy, Window win)
222 {
223 while (1) {
224 XEvent event;
225 if (XPending(dpy)) {
226 XNextEvent(dpy, &event);
227 switch (event.type) {
228 case Expose:
229 display(dpy, event.xexpose.window);
230 break;
231 case ConfigureNotify:
232 Width = event.xconfigure.width;
233 Height = event.xconfigure.height,
234 make_shape_mask(dpy, win, Width, Height, Sides);
235 reshape(Width, Height);
236 break;
237 case KeyPress:
238 {
239 char buf[100];
240 KeySym keySym;
241 XComposeStatus stat;
242 XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
243 switch (keySym) {
244 case XK_Escape:
245 exit(0);
246 break;
247 case XK_Up:
248 Sides++;
249 if (Sides>MaxSides) Sides = MaxSides;
250 make_shape_mask(dpy, win, Width, Height, Sides);
251 break;
252 case XK_Down:
253 Sides--;
254 if (Sides<MinSides) Sides = MinSides;
255 make_shape_mask(dpy, win, Width, Height, Sides);
256 break;
257 }
258 }
259 break;
260 default:
261 ;;
262 }
263 }
264 else {
265 idle();
266 if (Redraw) {
267 display(dpy, win);
268 Redraw = 0;
269 }
270 }
271 }
272 }
273
274
275 /*
276 * Allocate a "nice" colormap. This could be better (HP-CR support, etc).
277 */
278 static Colormap alloc_colormap(Display *dpy, Window parent, Visual *vis)
279 {
280 Screen *scr = DefaultScreenOfDisplay(dpy);
281 int scrnum = DefaultScreen(dpy);
282
283 if (MaxCmapsOfScreen(scr)==1 && vis==DefaultVisual(dpy, scrnum)) {
284 /* The window and root are of the same visual type so */
285 /* share the root colormap. */
286 return DefaultColormap(dpy, scrnum);
287 }
288 else {
289 return XCreateColormap(dpy, parent, vis, AllocNone);
290 }
291 }
292
293
294 int main(int argc, char *argv[])
295 {
296 static int glAttribs[] = {
297 GLX_DOUBLEBUFFER,
298 GLX_RGBA,
299 GLX_DEPTH_SIZE, 1,
300 None
301 };
302 Display *dpy;
303 XVisualInfo *visInfo;
304 int scrn;
305 Window root;
306 Colormap cmap;
307 Window win;
308 XSetWindowAttributes winAttribs;
309 unsigned long winAttribsMask;
310 GLXContext glCtx;
311 int ignore;
312 const char *name = "OpenGL in a Shaped Window";
313
314 dpy = XOpenDisplay(NULL);
315 if (!dpy) {
316 fprintf(stderr, "Couldn't open default display\n");
317 return 1;
318 }
319
320 /* check that we can use the shape extension */
321 if (!XQueryExtension(dpy, "SHAPE", &ignore, &ignore, &ignore )) {
322 fprintf(stderr, "Display doesn't support shape extension\n");
323 return 1;
324 }
325
326 scrn = DefaultScreen(dpy);
327
328 root = RootWindow(dpy, scrn);
329
330 visInfo = glXChooseVisual(dpy, scrn, glAttribs);
331 if (!visInfo) {
332 fprintf(stderr, "Couldn't get RGB, DB, Z visual\n");
333 return 1;
334 }
335
336 glCtx = glXCreateContext(dpy, visInfo, 0, True);
337 if (!glCtx) {
338 fprintf(stderr, "Couldn't create GL context\n");
339 return 1;
340 }
341
342 cmap = alloc_colormap(dpy, root, visInfo->visual);
343 if (!cmap) {
344 fprintf(stderr, "Couln't create colormap\n");
345 return 1;
346 }
347
348 winAttribs.border_pixel = 0;
349 winAttribs.colormap = cmap;
350 winAttribs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
351 winAttribsMask = CWBorderPixel | CWColormap | CWEventMask;
352 win = XCreateWindow(dpy, root, 0, 0, Width, Height, 0,
353 visInfo->depth, InputOutput,
354 visInfo->visual,
355 winAttribsMask, &winAttribs);
356
357 {
358 XSizeHints sizehints;
359 /*
360 sizehints.x = xpos;
361 sizehints.y = ypos;
362 sizehints.width = width;
363 sizehints.height = height;
364 */
365 sizehints.flags = 0;
366 XSetNormalHints(dpy, win, &sizehints);
367 XSetStandardProperties(dpy, win, name, name,
368 None, (char **)NULL, 0, &sizehints);
369 }
370
371
372 XMapWindow(dpy, win);
373
374 glXMakeCurrent(dpy, win, glCtx);
375
376 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
377 printf("Press ESC to exit.\n");
378 printf("Press up/down to change window shape.\n");
379
380 event_loop(dpy, win);
381
382 return 0;
383 }