3 * Example of using the X "shape" extension with OpenGL: render a spinning
4 * cube inside of a non-rectangular window.
6 * Press ESC to exit. Press up/down to change window shape.
8 * To compile add "shape" to the PROGS list in Makefile.
13 * This program is in the public domain.
21 #include <X11/Xutil.h>
22 #include <X11/keysym.h>
23 #include <X11/extensions/shape.h>
31 static int Width
=500, Height
=500;
33 static float Xangle
= 0.0, Yangle
= 0.0;
34 static int Redraw
= 0;
36 static int MinSides
= 3;
37 static int MaxSides
= 20;
41 * Draw the OpenGL stuff and do a SwapBuffers.
43 static void display(Display
*dpy
, Window win
)
47 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
);
51 glScalef(scale
, scale
, scale
);
52 glRotatef(Xangle
, 1.0, 0.0, 0.0);
53 glRotatef(Yangle
, 0.0, 1.0, 0.0);
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);
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);
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);
84 glScalef(0.75, 0.75, 0.75);
88 glVertex3f(1, -1, -1);
96 glVertex3f(-1, -1, -1);
97 glVertex3f(-1, 1, -1);
99 glVertex3f(-1, -1, 1);
104 glVertex3f(-1, 1, -1);
105 glVertex3f( 1, 1, -1);
106 glVertex3f( 1, 1, 1);
107 glVertex3f(-1, 1, 1);
112 glVertex3f(-1, -1, -1);
113 glVertex3f( 1, -1, -1);
114 glVertex3f( 1, -1, 1);
115 glVertex3f(-1, -1, 1);
120 glVertex3f(-1, -1, 1);
121 glVertex3f( 1, -1, 1);
122 glVertex3f( 1, 1, 1);
123 glVertex3f(-1, 1, 1);
128 glVertex3f(-1, -1, -1);
129 glVertex3f( 1, -1, -1);
130 glVertex3f( 1, 1, -1);
131 glVertex3f(-1, 1, -1);
138 glXSwapBuffers(dpy
, win
);
143 * Called when no events are pending.
145 static void idle(void)
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
158 static void make_shape_mask(Display
*dpy
, Window win
, int width
, int height
,
165 /* allocate 1-bit deep pixmap and a GC */
166 shapeMask
= XCreatePixmap(dpy
, win
, width
, height
, 1);
167 gc
= XCreateGC(dpy
, shapeMask
, 0, &xgcv
);
169 /* clear shapeMask to zeros */
170 XSetForeground(dpy
, gc
, 0);
171 XFillRectangle(dpy
, shapeMask
, gc
, 0, 0, width
, height
);
174 XSetForeground(dpy
, gc
, 1);
179 float step
= 2.0 * PI
/ sides
;
180 float radius
= width
/ 2;
183 for (i
=0;i
<sides
;i
++) {
184 int x
= cx
+ radius
* sin(angle
);
185 int y
= cy
- radius
* cos(angle
);
190 XFillPolygon(dpy
, shapeMask
, gc
, points
, sides
, Convex
, CoordModeOrigin
);
193 /* This is the only SHAPE extension call- simple! */
194 XShapeCombineMask(dpy
, win
, ShapeBounding
, 0, 0, shapeMask
, ShapeSet
);
197 XFreePixmap(dpy
, shapeMask
);
202 * Called when window is resized. Do OpenGL viewport and projection stuff.
204 static void reshape(int width
, int height
)
206 glViewport(0, 0, width
, height
);
207 glMatrixMode(GL_PROJECTION
);
209 glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
210 glMatrixMode(GL_MODELVIEW
);
212 glTranslatef(0.0, 0.0, -10.0);
214 glEnable(GL_DEPTH_TEST
);
221 static void event_loop(Display
*dpy
, Window win
)
226 XNextEvent(dpy
, &event
);
227 switch (event
.type
) {
229 display(dpy
, event
.xexpose
.window
);
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
);
242 XLookupString(&event
.xkey
, buf
, sizeof(buf
), &keySym
, &stat
);
249 if (Sides
>MaxSides
) Sides
= MaxSides
;
250 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
254 if (Sides
<MinSides
) Sides
= MinSides
;
255 make_shape_mask(dpy
, win
, Width
, Height
, Sides
);
276 * Allocate a "nice" colormap. This could be better (HP-CR support, etc).
278 static Colormap
alloc_colormap(Display
*dpy
, Window parent
, Visual
*vis
)
280 Screen
*scr
= DefaultScreenOfDisplay(dpy
);
281 int scrnum
= DefaultScreen(dpy
);
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
);
289 return XCreateColormap(dpy
, parent
, vis
, AllocNone
);
294 int main(int argc
, char *argv
[])
296 static int glAttribs
[] = {
303 XVisualInfo
*visInfo
;
308 XSetWindowAttributes winAttribs
;
309 unsigned long winAttribsMask
;
312 const char *name
= "OpenGL in a Shaped Window";
314 dpy
= XOpenDisplay(NULL
);
316 fprintf(stderr
, "Couldn't open default display\n");
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");
326 scrn
= DefaultScreen(dpy
);
328 root
= RootWindow(dpy
, scrn
);
330 visInfo
= glXChooseVisual(dpy
, scrn
, glAttribs
);
332 fprintf(stderr
, "Couldn't get RGB, DB, Z visual\n");
336 glCtx
= glXCreateContext(dpy
, visInfo
, 0, True
);
338 fprintf(stderr
, "Couldn't create GL context\n");
342 cmap
= alloc_colormap(dpy
, root
, visInfo
->visual
);
344 fprintf(stderr
, "Couln't create colormap\n");
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
,
355 winAttribsMask
, &winAttribs
);
358 XSizeHints sizehints
;
362 sizehints.width = width;
363 sizehints.height = height;
366 XSetNormalHints(dpy
, win
, &sizehints
);
367 XSetStandardProperties(dpy
, win
, name
, name
,
368 None
, (char **)NULL
, 0, &sizehints
);
372 XMapWindow(dpy
, win
);
374 glXMakeCurrent(dpy
, win
, glCtx
);
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");
380 event_loop(dpy
, win
);