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.
24
#include <X11/Xutil.h>
25
#include <X11/keysym.h>
26
#include <X11/extensions/shape.h>
34
static int Width=500, Height=500;
36
static float Xangle = 0.0, Yangle = 0.0;
38
static int MinSides = 3;
39
static int MaxSides = 20;
42
/* return current time (in seconds) */
48
(void) gettimeofday(&tv, NULL );
51
(void) gettimeofday(&tv, &tz);
53
return (double) tv.tv_sec + tv.tv_usec / 1000000.0;
58
* Draw the OpenGL stuff and do a SwapBuffers.
60
static void display(Display *dpy, Window win)
64
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
68
glScalef(scale, scale, scale);
69
glRotatef(Xangle, 1.0, 0.0, 0.0);
70
glRotatef(Yangle, 0.0, 1.0, 0.0);
75
glColor3f(1.0, 1.0, 1.0);
76
glBegin(GL_LINE_LOOP);
77
glVertex3f(-1.0, -1.0, -1.0);
78
glVertex3f( 1.0, -1.0, -1.0);
79
glVertex3f( 1.0, 1.0, -1.0);
80
glVertex3f(-1.0, 1.0, -1.0);
83
glBegin(GL_LINE_LOOP);
84
glVertex3f(-1.0, -1.0, 1.0);
85
glVertex3f( 1.0, -1.0, 1.0);
86
glVertex3f( 1.0, 1.0, 1.0);
87
glVertex3f(-1.0, 1.0, 1.0);
91
glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0);
92
glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, 1.0);
93
glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, 1.0, 1.0);
94
glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0);
101
glScalef(0.75, 0.75, 0.75);
105
glVertex3f(1, -1, -1);
106
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);
137
glVertex3f(-1, -1, 1);
138
glVertex3f( 1, -1, 1);
139
glVertex3f( 1, 1, 1);
140
glVertex3f(-1, 1, 1);
145
glVertex3f(-1, -1, -1);
146
glVertex3f( 1, -1, -1);
147
glVertex3f( 1, 1, -1);
148
glVertex3f(-1, 1, -1);
155
glXSwapBuffers(dpy, win);
160
* This is called when we have to recompute the window shape bitmask.
161
* We just generate an n-sided regular polygon here but any other shape
164
static void make_shape_mask(Display *dpy, Window win, int width, int height,
171
/* allocate 1-bit deep pixmap and a GC */
172
shapeMask = XCreatePixmap(dpy, win, width, height, 1);
173
gc = XCreateGC(dpy, shapeMask, 0, &xgcv);
175
/* clear shapeMask to zeros */
176
XSetForeground(dpy, gc, 0);
177
XFillRectangle(dpy, shapeMask, gc, 0, 0, width, height);
180
XSetForeground(dpy, gc, 1);
185
float step = 2.0 * PI / sides;
186
float radius = width / 2;
189
for (i=0;i<sides;i++) {
190
int x = cx + radius * sin(angle);
191
int y = cy - radius * cos(angle);
196
XFillPolygon(dpy, shapeMask, gc, points, sides, Convex, CoordModeOrigin);
199
/* This is the only SHAPE extension call- simple! */
200
XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, shapeMask, ShapeSet);
203
XFreePixmap(dpy, shapeMask);
208
* Called when window is resized. Do OpenGL viewport and projection stuff.
210
static void reshape(int width, int height)
212
glViewport(0, 0, width, height);
213
glMatrixMode(GL_PROJECTION);
215
glFrustum(-1.0, 1.0, -1.0, 1.0, 3.0, 20.0);
216
glMatrixMode(GL_MODELVIEW);
218
glTranslatef(0.0, 0.0, -10.0);
220
glEnable(GL_DEPTH_TEST);
227
static void event_loop(Display *dpy, Window win)
232
XNextEvent(dpy, &event);
233
switch (event.type) {
235
display(dpy, event.xexpose.window);
237
case ConfigureNotify:
238
Width = event.xconfigure.width;
239
Height = event.xconfigure.height,
240
make_shape_mask(dpy, win, Width, Height, Sides);
241
reshape(Width, Height);
248
XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
255
if (Sides>MaxSides) Sides = MaxSides;
256
make_shape_mask(dpy, win, Width, Height, Sides);
260
if (Sides<MinSides) Sides = MinSides;
261
make_shape_mask(dpy, win, Width, Height, Sides);
271
static double t0 = -1.0;
272
double dt, t = current_time();
276
Xangle += 90.0 * dt; /* 90 degrees per second */
286
* Allocate a "nice" colormap. This could be better (HP-CR support, etc).
288
static Colormap alloc_colormap(Display *dpy, Window parent, Visual *vis)
290
Screen *scr = DefaultScreenOfDisplay(dpy);
291
int scrnum = DefaultScreen(dpy);
293
if (MaxCmapsOfScreen(scr)==1 && vis==DefaultVisual(dpy, scrnum)) {
294
/* The window and root are of the same visual type so */
295
/* share the root colormap. */
296
return DefaultColormap(dpy, scrnum);
299
return XCreateColormap(dpy, parent, vis, AllocNone);
304
int main(int argc, char *argv[])
306
static int glAttribs[] = {
313
XVisualInfo *visInfo;
318
XSetWindowAttributes winAttribs;
319
unsigned long winAttribsMask;
322
const char *name = "OpenGL in a Shaped Window";
324
dpy = XOpenDisplay(NULL);
326
fprintf(stderr, "Couldn't open default display\n");
330
/* check that we can use the shape extension */
331
if (!XQueryExtension(dpy, "SHAPE", &ignore, &ignore, &ignore )) {
332
fprintf(stderr, "Display doesn't support shape extension\n");
336
scrn = DefaultScreen(dpy);
338
root = RootWindow(dpy, scrn);
340
visInfo = glXChooseVisual(dpy, scrn, glAttribs);
342
fprintf(stderr, "Couldn't get RGB, DB, Z visual\n");
346
glCtx = glXCreateContext(dpy, visInfo, 0, True);
348
fprintf(stderr, "Couldn't create GL context\n");
352
cmap = alloc_colormap(dpy, root, visInfo->visual);
354
fprintf(stderr, "Couln't create colormap\n");
358
winAttribs.border_pixel = 0;
359
winAttribs.colormap = cmap;
360
winAttribs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
361
winAttribsMask = CWBorderPixel | CWColormap | CWEventMask;
362
win = XCreateWindow(dpy, root, 0, 0, Width, Height, 0,
363
visInfo->depth, InputOutput,
365
winAttribsMask, &winAttribs);
368
XSizeHints sizehints;
372
sizehints.width = width;
373
sizehints.height = height;
376
XSetNormalHints(dpy, win, &sizehints);
377
XSetStandardProperties(dpy, win, name, name,
378
None, (char **)NULL, 0, &sizehints);
382
XMapWindow(dpy, win);
384
glXMakeCurrent(dpy, win, glCtx);
386
printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
387
printf("Press ESC to exit.\n");
388
printf("Press up/down to change window shape.\n");
390
event_loop(dpy, win);