132001f49Smrg/*
232001f49Smrg * GLX overlay test/demo.
332001f49Smrg *
432001f49Smrg * Brian Paul
532001f49Smrg * 18 July 2005
632001f49Smrg */
732001f49Smrg
832001f49Smrg#include <GL/gl.h>
932001f49Smrg#include <GL/glx.h>
1032001f49Smrg#include <X11/keysym.h>
1132001f49Smrg#include <assert.h>
1232001f49Smrg#include <stdio.h>
1332001f49Smrg#include <stdlib.h>
1432001f49Smrg
1532001f49Smrgstatic int WinWidth = 300, WinHeight = 300;
1632001f49Smrgstatic Window NormalWindow = 0;
1732001f49Smrgstatic Window OverlayWindow = 0;
1832001f49Smrgstatic GLXContext NormalContext = 0;
1932001f49Smrgstatic GLXContext OverlayContext = 0;
2032001f49Smrgstatic GLboolean RGBOverlay = GL_FALSE;
2132001f49Smrgstatic GLfloat Angle = 0.0;
2232001f49Smrg
2332001f49Smrg
2432001f49Smrgstatic void
2532001f49SmrgRedrawNormal(Display *dpy)
2632001f49Smrg{
2732001f49Smrg   glXMakeCurrent(dpy, NormalWindow, NormalContext);
2832001f49Smrg   glViewport(0, 0, WinWidth, WinHeight);
2932001f49Smrg   glMatrixMode(GL_PROJECTION);
3032001f49Smrg   glLoadIdentity();
3132001f49Smrg   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
3232001f49Smrg   glMatrixMode(GL_MODELVIEW);
3332001f49Smrg   glClearColor(0.5, 0.5, 0.5, 1.0);
3432001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
3532001f49Smrg   glColor3f(1.0, 1.0, 0.0);
3632001f49Smrg   glPushMatrix();
3732001f49Smrg   glRotatef(Angle, 0, 0, 1);
3832001f49Smrg   glRectf(-0.8, -0.8, 0.8, 0.8);
3932001f49Smrg   glPopMatrix();
4032001f49Smrg   glXSwapBuffers(dpy, NormalWindow);
4132001f49Smrg}
4232001f49Smrg
4332001f49Smrg
4432001f49Smrgstatic void
4532001f49SmrgRedrawOverlay(Display *dpy)
4632001f49Smrg{
4732001f49Smrg   glXMakeCurrent(dpy, OverlayWindow, OverlayContext);
4832001f49Smrg   glViewport(0, 0, WinWidth, WinHeight);
4932001f49Smrg   glMatrixMode(GL_PROJECTION);
5032001f49Smrg   glLoadIdentity();
5132001f49Smrg   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
5232001f49Smrg   glMatrixMode(GL_MODELVIEW);
5332001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
5432001f49Smrg   if (RGBOverlay) {
5532001f49Smrg      glColor3f(0.0, 1.0, 1.0);
5632001f49Smrg   }
5732001f49Smrg   else {
5832001f49Smrg      glIndexi(2);
5932001f49Smrg   }
6032001f49Smrg   glBegin(GL_LINES);
6132001f49Smrg   glVertex2f(-1, -1);
6232001f49Smrg   glVertex2f(1, 1);
6332001f49Smrg   glVertex2f(1, -1);
6432001f49Smrg   glVertex2f(-1, 1);
6532001f49Smrg   glEnd();
6632001f49Smrg   glXSwapBuffers(dpy, OverlayWindow);
6732001f49Smrg}
6832001f49Smrg
6932001f49Smrg
7032001f49Smrgstatic Window
7132001f49SmrgMakeWindow(Display *dpy, XVisualInfo *visinfo, Window parent,
7232001f49Smrg             unsigned int width, unsigned int height)
7332001f49Smrg{
7432001f49Smrg   int scrnum;
7532001f49Smrg   XSetWindowAttributes attr;
7632001f49Smrg   unsigned long mask;
7732001f49Smrg   Window root;
7832001f49Smrg   Window win;
7932001f49Smrg
8032001f49Smrg   scrnum = DefaultScreen(dpy);
8132001f49Smrg   root = RootWindow(dpy, scrnum);
8232001f49Smrg
8332001f49Smrg   /* window attributes */
8432001f49Smrg   attr.background_pixel = 0;
8532001f49Smrg   attr.border_pixel = 0;
8632001f49Smrg   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
8732001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
8832001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
8932001f49Smrg
9032001f49Smrg   win = XCreateWindow(dpy, parent, 0, 0, width, height,
9132001f49Smrg		        0, visinfo->depth, InputOutput,
9232001f49Smrg		        visinfo->visual, mask, &attr);
9332001f49Smrg   return win;
9432001f49Smrg}
9532001f49Smrg
9632001f49Smrg
9732001f49Smrgstatic void
9832001f49SmrgMakeNormalWindow(Display *dpy)
9932001f49Smrg{
10032001f49Smrg   int attrib[] = { GLX_RGBA,
10132001f49Smrg		    GLX_RED_SIZE, 1,
10232001f49Smrg		    GLX_GREEN_SIZE, 1,
10332001f49Smrg		    GLX_BLUE_SIZE, 1,
10432001f49Smrg		    GLX_DOUBLEBUFFER,
10532001f49Smrg		    None };
10632001f49Smrg   int scrnum;
10732001f49Smrg   Window root;
10832001f49Smrg   XVisualInfo *visinfo;
10932001f49Smrg
11032001f49Smrg   scrnum = DefaultScreen(dpy);
11132001f49Smrg   root = RootWindow(dpy, scrnum);
11232001f49Smrg
11332001f49Smrg   visinfo = glXChooseVisual(dpy, scrnum, attrib);
11432001f49Smrg   if (!visinfo) {
11532001f49Smrg      printf("Error: couldn't get an RGB, Double-buffered visual\n");
11632001f49Smrg      exit(1);
11732001f49Smrg   }
11832001f49Smrg
11932001f49Smrg   NormalWindow = MakeWindow(dpy, visinfo, root, WinWidth, WinHeight);
12032001f49Smrg   assert(NormalWindow);
12132001f49Smrg
12232001f49Smrg   NormalContext = glXCreateContext(dpy, visinfo, NULL, True);
12332001f49Smrg   assert(NormalContext);
12432001f49Smrg}
12532001f49Smrg
12632001f49Smrg
12732001f49Smrgstatic void
12832001f49SmrgMakeOverlayWindow(Display *dpy)
12932001f49Smrg{
13032001f49Smrg   int rgbAttribs[] = {
13132001f49Smrg      GLX_RGBA,
13232001f49Smrg      GLX_RED_SIZE, 1,
13332001f49Smrg      GLX_GREEN_SIZE, 1,
13432001f49Smrg      GLX_BLUE_SIZE, 1,
13532001f49Smrg      GLX_DOUBLEBUFFER,
13632001f49Smrg      GLX_LEVEL, 1,
13732001f49Smrg      None
13832001f49Smrg   };
13932001f49Smrg   int indexAttribs[] = {
14032001f49Smrg      /*GLX_RGBA, leave this out */
14132001f49Smrg      GLX_RED_SIZE, 1,
14232001f49Smrg      GLX_GREEN_SIZE, 1,
14332001f49Smrg      GLX_BLUE_SIZE, 1,
14432001f49Smrg      GLX_DOUBLEBUFFER,
14532001f49Smrg      GLX_LEVEL, 1,
14632001f49Smrg      None
14732001f49Smrg   };
14832001f49Smrg   int scrnum;
14932001f49Smrg   XVisualInfo *visinfo;
15032001f49Smrg
15132001f49Smrg   scrnum = DefaultScreen(dpy);
15232001f49Smrg
15332001f49Smrg   visinfo = glXChooseVisual(dpy, scrnum, rgbAttribs);
15432001f49Smrg   if (visinfo) {
15532001f49Smrg      printf("Found RGB overlay visual 0x%x\n", (int) visinfo->visualid);
15632001f49Smrg      RGBOverlay = GL_TRUE;
15732001f49Smrg   }
15832001f49Smrg   else {
15932001f49Smrg      visinfo = glXChooseVisual(dpy, scrnum, indexAttribs);
16032001f49Smrg      if (visinfo) {
16132001f49Smrg         printf("Found Color Index overlay visual 0x%x\n",
16232001f49Smrg                (int) visinfo->visualid);
16332001f49Smrg         /* XXX setup the colormap entries! */
16432001f49Smrg      }
16532001f49Smrg      else {
16632001f49Smrg         printf("Couldn't get an overlay visual.\n");
16732001f49Smrg         printf("Your hardware probably doesn't support framebuffer overlay planes.\n");
16832001f49Smrg         exit(1);
16932001f49Smrg      }
17032001f49Smrg   }
17132001f49Smrg
17232001f49Smrg   OverlayWindow = MakeWindow(dpy, visinfo, NormalWindow, WinWidth, WinHeight);
17332001f49Smrg   assert(OverlayWindow);
17432001f49Smrg
17532001f49Smrg   OverlayContext = glXCreateContext(dpy, visinfo, NULL, True);
17632001f49Smrg   assert(OverlayContext);
17732001f49Smrg}
17832001f49Smrg
17932001f49Smrg
18032001f49Smrgstatic void
18132001f49SmrgEventLoop(Display *dpy)
18232001f49Smrg{
18332001f49Smrg   XEvent event;
18432001f49Smrg
18532001f49Smrg   while (1) {
18632001f49Smrg      XNextEvent(dpy, &event);
18732001f49Smrg
18832001f49Smrg      switch (event.type) {
18932001f49Smrg	 case Expose:
19032001f49Smrg	    RedrawNormal(dpy);
19132001f49Smrg	    RedrawOverlay(dpy);
19232001f49Smrg	    break;
19332001f49Smrg	 case ConfigureNotify:
19432001f49Smrg            WinWidth = event.xconfigure.width;
19532001f49Smrg            WinHeight = event.xconfigure.height;
19632001f49Smrg            if (event.xconfigure.window == NormalWindow)
19732001f49Smrg               XResizeWindow(dpy, OverlayWindow, WinWidth, WinHeight);
19832001f49Smrg	    break;
19932001f49Smrg         case KeyPress:
20032001f49Smrg            {
20132001f49Smrg               char buffer[10];
20232001f49Smrg	       XLookupString(&event.xkey, buffer, sizeof(buffer),
20332001f49Smrg                             NULL, NULL);
20432001f49Smrg	       if (buffer[0] == 27) {
20532001f49Smrg                  /* escape */
20632001f49Smrg                  return;
20732001f49Smrg               }
20832001f49Smrg               else if (buffer[0] == ' ') {
20932001f49Smrg                  Angle += 5.0;
21032001f49Smrg                  RedrawNormal(dpy);
21132001f49Smrg               }
21232001f49Smrg            }
21332001f49Smrg            break;
21432001f49Smrg         default:
21532001f49Smrg            ; /* nothing */
21632001f49Smrg      }
21732001f49Smrg   }
21832001f49Smrg}
21932001f49Smrg
22032001f49Smrg
22132001f49Smrgint
22232001f49Smrgmain(int argc, char *argv[])
22332001f49Smrg{
22432001f49Smrg   Display *dpy = XOpenDisplay(NULL);
22532001f49Smrg
22632001f49Smrg   assert(dpy);
22732001f49Smrg
22832001f49Smrg   MakeNormalWindow(dpy);
22932001f49Smrg   MakeOverlayWindow(dpy);
23032001f49Smrg
23132001f49Smrg   XMapWindow(dpy, NormalWindow);
23232001f49Smrg   XMapWindow(dpy, OverlayWindow);
23332001f49Smrg
23432001f49Smrg   EventLoop(dpy);
23532001f49Smrg
23632001f49Smrg   glXDestroyContext(dpy, OverlayContext);
23732001f49Smrg   glXDestroyContext(dpy, NormalContext);
23832001f49Smrg   XDestroyWindow(dpy, OverlayWindow);
23932001f49Smrg   XDestroyWindow(dpy, NormalWindow);
24032001f49Smrg
24132001f49Smrg   return 0;
24232001f49Smrg}
243