1 /* $Id: shape.c,v 1.3 2000/06/27 15:34:35 brianp Exp $ */
4 * Example of using the X "shape" extension with OpenGL: render a spinning
5 * cube inside of a non-rectangular window.
7 * Press ESC to exit. Press up/down to change window shape.
9 * To compile add "shape" to the PROGS list in Makefile.
14 * This program is in the public domain.
22 #include <X11/Xutil.h>
23 #include <X11/keysym.h>
24 #include <X11/extensions/shape.h>
32 static int Width
=500, Height
=500;
34 static float Xangle
= 0.0, Yangle
= 0.0;
35 static int Redraw
= 0;
37 static int MinSides
= 3;
38 static int MaxSides
= 20;
42 * Draw the OpenGL stuff and do a SwapBuffers.
44 static void display(Display
*dpy
, Window win
)
48 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
52 glScalef(scale
, scale
, scale
);
53 glRotatef(Xangle
, 1.0, 0.0, 0.0);
54 glRotatef(Yangle
, 0.0, 1.0, 0.0);
59 glColor3f(1.0, 1.0, 1.0);
60 glBegin(GL_LINE_LOOP
);
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 glVertex3f(-1.0, 1.0, -1.0);
67 glBegin(GL_LINE_LOOP
);
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 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 glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
85 glScalef(0.75, 0.75, 0.75);
89 glVertex3f(1, -1, -1);
97 glVertex3f(-1, -1, -1);
98 glVertex3f(-1, 1, -1);
100 glVertex3f(-1, -1, 1);
105 glVertex3f(-1, 1, -1);
106 glVertex3f( 1, 1, -1);
107 glVertex3f( 1, 1, 1);
108 glVertex3f(-1, 1, 1);
113 glVertex3f(-1, -1, -1);
114 glVertex3f( 1, -1, -1);
115 glVertex3f( 1, -1, 1);
116 glVertex3f(-1, -1, 1);
121 glVertex3f(-1, -1, 1);
122 glVertex3f( 1, -1, 1);
123 glVertex3f( 1, 1, 1);
124 glVertex3f(-1, 1, 1);
129 glVertex3f(-1, -1, -1);
130 glVertex3f( 1, -1, -1);
131 glVertex3f( 1, 1, -1);
132 glVertex3f(-1, 1, -1);
139 glXSwapBuffers(dpy
, win
);
144 * Called when no events are pending.
146 static void idle(void)
155 * This is called when we have to recompute the window shape bitmask.
156 * We just generate an n-sided regular polygon here but any other shape
159 static void make_shape_mask(Display
*dpy
, Window win
, int width
, int height
,
166 /* allocate 1-bit deep pixmap and a GC */
167 shapeMask
= XCreatePixmap(dpy
, win
, width
, height
, 1);
168 gc
= XCreateGC(dpy
, shapeMask
, 0, &xgcv
);
170 /* clear shapeMask to zeros */
171 XSetForeground(dpy
, gc
, 0);
172 XFillRectangle(dpy
, shapeMask
, gc
, 0, 0, width
, height
);
175 XSetForeground(dpy
, gc
, 1);
180 float step
= 2.0 * PI
/ sides
;
181 float radius
= width
/ 2;
184 for (i
=0;i
<sides
;i
++) {
185 int x
= cx
+ radius
* sin(angle
);
186 int y
= cy
- radius
* cos(angle
);
191 XFillPolygon(dpy
, shapeMask
, gc
, points
, sides
, Convex
, CoordModeOrigin
);
194 /* This is the only SHAPE extension call- simple! */
195 XShapeCombineMask(dpy
, win
, ShapeBounding
, 0, 0, shapeMask
, ShapeSet
);
198 XFreePixmap(dpy
, shapeMask
);
203 * Called when window is resized. Do OpenGL viewport and projection stuff.
205 static void reshape(int width
, int height
)
207 glViewport(0, 0, width
, height
);
208 glMatrixMode(GL_PROJECTION
);
210 glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
211 glMatrixMode(GL_MODELVIEW
);
213 glTranslatef(0.0, 0.0, -10.0);
215 glEnable(GL_DEPTH_TEST
);
222 static void event_loop(Display
*dpy
, Window win
)
227 XNextEvent(dpy
, &event
);
228 switch (event
.type
) {
230 display(dpy
, event
.xexpose
.window
);
232 case ConfigureNotify
:
233 Width
= event
.xconfigure
.width
;
234 Height
= event
.xconfigure
.height
,
235 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
236 reshape(Width
, Height
);
243 XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keySym
, &stat
);
250 if (Sides
>MaxSides
) Sides
= MaxSides
;
251 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
255 if (Sides
<MinSides
) Sides
= MinSides
;
256 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
277 * Allocate a "nice" colormap. This could be better (HP-CR support, etc).
279 static Colormap
alloc_colormap(Display
*dpy
, Window parent
, Visual
*vis
)
281 Screen
*scr
= DefaultScreenOfDisplay(dpy
);
282 int scrnum
= DefaultScreen(dpy
);
284 if (MaxCmapsOfScreen(scr
)==1 && vis
==DefaultVisual(dpy
, scrnum
)) {
285 /* The window and root are of the same visual type so */
286 /* share the root colormap. */
287 return DefaultColormap(dpy
, scrnum
);
290 return XCreateColormap(dpy
, parent
, vis
, AllocNone
);
295 int main(int argc
, char *argv
[])
297 static int glAttribs
[] = {
304 XVisualInfo
*visInfo
;
309 XSetWindowAttributes winAttribs
;
310 unsigned long winAttribsMask
;
313 const char *name
= "OpenGL in a Shaped Window";
315 dpy
= XOpenDisplay(NULL
);
317 fprintf(stderr
, "Couldn't open default display\n");
321 /* check that we can use the shape extension */
322 if (!XQueryExtension(dpy
, "SHAPE", &ignore
, &ignore
, &ignore
)) {
323 fprintf(stderr
, "Display doesn't support shape extension\n");
327 scrn
= DefaultScreen(dpy
);
329 root
= RootWindow(dpy
, scrn
);
331 visInfo
= glXChooseVisual(dpy
, scrn
, glAttribs
);
333 fprintf(stderr
, "Couldn't get RGB, DB, Z visual\n");
337 glCtx
= glXCreateContext(dpy
, visInfo
, 0, True
);
339 fprintf(stderr
, "Couldn't create GL context\n");
343 cmap
= alloc_colormap(dpy
, root
, visInfo
->visual
);
345 fprintf(stderr
, "Couln't create colormap\n");
349 winAttribs
.border_pixel
= 0;
350 winAttribs
.colormap
= cmap
;
351 winAttribs
.event_mask
= StructureNotifyMask
| ExposureMask
| KeyPressMask
;
352 winAttribsMask
= CWBorderPixel
| CWColormap
| CWEventMask
;
353 win
= XCreateWindow(dpy
, root
, 0, 0, Width
, Height
, 0,
354 visInfo
->depth
, InputOutput
,
356 winAttribsMask
, &winAttribs
);
359 XSizeHints sizehints
;
363 sizehints.width = width;
364 sizehints.height = height;
367 XSetNormalHints(dpy
, win
, &sizehints
);
368 XSetStandardProperties(dpy
, win
, name
, name
,
369 None
, (char **)NULL
, 0, &sizehints
);
373 XMapWindow(dpy
, win
);
375 glXMakeCurrent(dpy
, win
, glCtx
);
377 printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER
));
378 printf("Press ESC to exit.\n");
379 printf("Press up/down to change window shape.\n");
381 event_loop(dpy
, win
);