home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 5 / MA_Cover_5.iso / ppc / mesa / demos / shape.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-31  |  7.4 KB  |  306 lines

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