1/*
2 * GLX overlay test/demo.
3 *
4 * Brian Paul
5 * 18 July 2005
6 */
7
8#include <GL/gl.h>
9#include <GL/glx.h>
10#include <X11/keysym.h>
11#include <assert.h>
12#include <stdio.h>
13#include <stdlib.h>
14
15static int WinWidth = 300, WinHeight = 300;
16static Window NormalWindow = 0;
17static Window OverlayWindow = 0;
18static GLXContext NormalContext = 0;
19static GLXContext OverlayContext = 0;
20static GLboolean RGBOverlay = GL_FALSE;
21static GLfloat Angle = 0.0;
22
23
24static void
25RedrawNormal(Display *dpy)
26{
27   glXMakeCurrent(dpy, NormalWindow, NormalContext);
28   glViewport(0, 0, WinWidth, WinHeight);
29   glMatrixMode(GL_PROJECTION);
30   glLoadIdentity();
31   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
32   glMatrixMode(GL_MODELVIEW);
33   glClearColor(0.5, 0.5, 0.5, 1.0);
34   glClear(GL_COLOR_BUFFER_BIT);
35   glColor3f(1.0, 1.0, 0.0);
36   glPushMatrix();
37   glRotatef(Angle, 0, 0, 1);
38   glRectf(-0.8, -0.8, 0.8, 0.8);
39   glPopMatrix();
40   glXSwapBuffers(dpy, NormalWindow);
41}
42
43
44static void
45RedrawOverlay(Display *dpy)
46{
47   glXMakeCurrent(dpy, OverlayWindow, OverlayContext);
48   glViewport(0, 0, WinWidth, WinHeight);
49   glMatrixMode(GL_PROJECTION);
50   glLoadIdentity();
51   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
52   glMatrixMode(GL_MODELVIEW);
53   glClear(GL_COLOR_BUFFER_BIT);
54   if (RGBOverlay) {
55      glColor3f(0.0, 1.0, 1.0);
56   }
57   else {
58      glIndexi(2);
59   }
60   glBegin(GL_LINES);
61   glVertex2f(-1, -1);
62   glVertex2f(1, 1);
63   glVertex2f(1, -1);
64   glVertex2f(-1, 1);
65   glEnd();
66   glXSwapBuffers(dpy, OverlayWindow);
67}
68
69
70static Window
71MakeWindow(Display *dpy, XVisualInfo *visinfo, Window parent,
72             unsigned int width, unsigned int height)
73{
74   int scrnum;
75   XSetWindowAttributes attr;
76   unsigned long mask;
77   Window root;
78   Window win;
79
80   scrnum = DefaultScreen(dpy);
81   root = RootWindow(dpy, scrnum);
82
83   /* window attributes */
84   attr.background_pixel = 0;
85   attr.border_pixel = 0;
86   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
87   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
88   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
89
90   win = XCreateWindow(dpy, parent, 0, 0, width, height,
91		        0, visinfo->depth, InputOutput,
92		        visinfo->visual, mask, &attr);
93   return win;
94}
95
96
97static void
98MakeNormalWindow(Display *dpy)
99{
100   int attrib[] = { GLX_RGBA,
101		    GLX_RED_SIZE, 1,
102		    GLX_GREEN_SIZE, 1,
103		    GLX_BLUE_SIZE, 1,
104		    GLX_DOUBLEBUFFER,
105		    None };
106   int scrnum;
107   Window root;
108   XVisualInfo *visinfo;
109
110   scrnum = DefaultScreen(dpy);
111   root = RootWindow(dpy, scrnum);
112
113   visinfo = glXChooseVisual(dpy, scrnum, attrib);
114   if (!visinfo) {
115      printf("Error: couldn't get an RGB, Double-buffered visual\n");
116      exit(1);
117   }
118
119   NormalWindow = MakeWindow(dpy, visinfo, root, WinWidth, WinHeight);
120   assert(NormalWindow);
121
122   NormalContext = glXCreateContext(dpy, visinfo, NULL, True);
123   assert(NormalContext);
124}
125
126
127static void
128MakeOverlayWindow(Display *dpy)
129{
130   int rgbAttribs[] = {
131      GLX_RGBA,
132      GLX_RED_SIZE, 1,
133      GLX_GREEN_SIZE, 1,
134      GLX_BLUE_SIZE, 1,
135      GLX_DOUBLEBUFFER,
136      GLX_LEVEL, 1,
137      None
138   };
139   int indexAttribs[] = {
140      /*GLX_RGBA, leave this out */
141      GLX_RED_SIZE, 1,
142      GLX_GREEN_SIZE, 1,
143      GLX_BLUE_SIZE, 1,
144      GLX_DOUBLEBUFFER,
145      GLX_LEVEL, 1,
146      None
147   };
148   int scrnum;
149   XVisualInfo *visinfo;
150
151   scrnum = DefaultScreen(dpy);
152
153   visinfo = glXChooseVisual(dpy, scrnum, rgbAttribs);
154   if (visinfo) {
155      printf("Found RGB overlay visual 0x%x\n", (int) visinfo->visualid);
156      RGBOverlay = GL_TRUE;
157   }
158   else {
159      visinfo = glXChooseVisual(dpy, scrnum, indexAttribs);
160      if (visinfo) {
161         printf("Found Color Index overlay visual 0x%x\n",
162                (int) visinfo->visualid);
163         /* XXX setup the colormap entries! */
164      }
165      else {
166         printf("Couldn't get an overlay visual.\n");
167         printf("Your hardware probably doesn't support framebuffer overlay planes.\n");
168         exit(1);
169      }
170   }
171
172   OverlayWindow = MakeWindow(dpy, visinfo, NormalWindow, WinWidth, WinHeight);
173   assert(OverlayWindow);
174
175   OverlayContext = glXCreateContext(dpy, visinfo, NULL, True);
176   assert(OverlayContext);
177}
178
179
180static void
181EventLoop(Display *dpy)
182{
183   XEvent event;
184
185   while (1) {
186      XNextEvent(dpy, &event);
187
188      switch (event.type) {
189	 case Expose:
190	    RedrawNormal(dpy);
191	    RedrawOverlay(dpy);
192	    break;
193	 case ConfigureNotify:
194            WinWidth = event.xconfigure.width;
195            WinHeight = event.xconfigure.height;
196            if (event.xconfigure.window == NormalWindow)
197               XResizeWindow(dpy, OverlayWindow, WinWidth, WinHeight);
198	    break;
199         case KeyPress:
200            {
201               char buffer[10];
202	       XLookupString(&event.xkey, buffer, sizeof(buffer),
203                             NULL, NULL);
204	       if (buffer[0] == 27) {
205                  /* escape */
206                  return;
207               }
208               else if (buffer[0] == ' ') {
209                  Angle += 5.0;
210                  RedrawNormal(dpy);
211               }
212            }
213            break;
214         default:
215            ; /* nothing */
216      }
217   }
218}
219
220
221int
222main(int argc, char *argv[])
223{
224   Display *dpy = XOpenDisplay(NULL);
225
226   assert(dpy);
227
228   MakeNormalWindow(dpy);
229   MakeOverlayWindow(dpy);
230
231   XMapWindow(dpy, NormalWindow);
232   XMapWindow(dpy, OverlayWindow);
233
234   EventLoop(dpy);
235
236   glXDestroyContext(dpy, OverlayContext);
237   glXDestroyContext(dpy, NormalContext);
238   XDestroyWindow(dpy, OverlayWindow);
239   XDestroyWindow(dpy, NormalWindow);
240
241   return 0;
242}
243