wincopy.c revision 32001f49
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.2
4 *
5 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/*
27 * This program opens two GLX windows, renders into one and uses
28 * glCopyPixels to copy the image from the first window into the
29 * second by means of the GLX 1.3 function glxMakeContextCurrent().
30 * This function works just like the glXMakeCurrentReadSGI() function
31 * in the GLX_SGI_make_current_read extension.
32 */
33
34
35#define GL_GLEXT_PROTOTYPES
36#define GLX_GLXEXT_PROTOTYPES
37#include <GL/gl.h>
38#include <GL/glx.h>
39#include <X11/keysym.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <unistd.h>
44
45
46#ifdef GLX_VERSION_1_3
47
48
49static Display *Dpy;
50static int ScrNum;
51static GLXContext Context;
52static Window Win[2];  /* Win[0] = source,  Win[1] = dest */
53static GLint Width[2], Height[2];
54static GLboolean TestClipping = GL_FALSE;
55static GLfloat Angle = 0.0;
56
57static GLboolean DrawFront = GL_FALSE;
58
59PFNGLXMAKECURRENTREADSGIPROC make_context_current = NULL;
60
61static Window
62CreateWindow(Display *dpy, int scrnum, XVisualInfo *visinfo,
63             int xpos, int ypos, int width, int height,
64             const char *name)
65{
66   Window win;
67   XSetWindowAttributes attr;
68   unsigned long mask;
69   Window root;
70
71   root = RootWindow(dpy, scrnum);
72
73   /* window attributes */
74   attr.background_pixel = 0;
75   attr.border_pixel = 0;
76   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
77   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
78   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
79
80   win = XCreateWindow(dpy, root, xpos, ypos, width, height,
81		        0, visinfo->depth, InputOutput,
82		        visinfo->visual, mask, &attr);
83   if (win) {
84      XSizeHints sizehints;
85      sizehints.x = xpos;
86      sizehints.y = ypos;
87      sizehints.width  = width;
88      sizehints.height = height;
89      sizehints.flags = USSize | USPosition;
90      XSetNormalHints(dpy, win, &sizehints);
91      XSetStandardProperties(dpy, win, name, name,
92                              None, (char **)NULL, 0, &sizehints);
93
94      XMapWindow(dpy, win);
95   }
96   return win;
97}
98
99
100static void
101Redraw(void)
102{
103   /* make the first window the current one */
104   if (! (*make_context_current)(Dpy, Win[0], Win[0], Context)) {
105      printf("glXMakeContextCurrent failed in Redraw()\n");
106      return;
107   }
108
109   Angle += 1.0;
110
111   if (DrawFront) {
112      glDrawBuffer(GL_FRONT);
113      glReadBuffer(GL_FRONT);
114   }
115   else {
116      glDrawBuffer(GL_BACK);
117      glReadBuffer(GL_BACK);
118   }
119
120   glViewport(0, 0, Width[0], Height[0]);
121   glMatrixMode(GL_PROJECTION);
122   glLoadIdentity();
123   glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
124   glMatrixMode(GL_MODELVIEW);
125
126   glShadeModel(GL_FLAT);
127   glClearColor(0.5, 0.5, 0.5, 0.0);
128   glClear(GL_COLOR_BUFFER_BIT);
129
130   /* draw blue quad */
131   glColor3f(0.3, 0.3, 1.0);
132   glPushMatrix();
133   glRotatef(Angle, 0, 0, 1);
134   glBegin(GL_POLYGON);
135   glVertex2f(-0.5, -0.25);
136   glVertex2f( 0.5, -0.25);
137   glVertex2f( 0.5, 0.25);
138   glVertex2f(-0.5, 0.25);
139   glEnd();
140   glPopMatrix();
141
142   if (DrawFront)
143      glFinish();
144   else
145      glXSwapBuffers(Dpy, Win[0]);
146
147
148   /* copy image from window 0 to window 1 */
149   if (!(*make_context_current)(Dpy, Win[1], Win[0], Context)) {
150      printf("glXMakeContextCurrent failed in Redraw()\n");
151      return;
152   }
153
154   /* copy the image between windows */
155   glClearColor(0.0, 0.0, 0.0, 0.0);
156   glClear(GL_COLOR_BUFFER_BIT);
157
158   if (TestClipping) {
159      glWindowPos2iARB(-2, -2);
160      glCopyPixels(-2, -2, Width[0] + 4, Height[0] + 4, GL_COLOR);
161   }
162   else {
163      glWindowPos2iARB(0, 0);
164      glCopyPixels(0, 0, Width[0], Height[0], GL_COLOR);
165   }
166
167   if (DrawFront)
168      glFinish();
169   else
170      glXSwapBuffers(Dpy, Win[1]);
171}
172
173
174
175static void
176Resize(Window win, unsigned int width, unsigned int height)
177{
178   int i;
179   if (win == Win[0]) {
180      i = 0;
181   }
182   else {
183      i = 1;
184   }
185   Width[i] = width;
186   Height[i] = height;
187   if (!glXMakeCurrent(Dpy, Win[i], Context)) {
188      printf("glXMakeCurrent failed in Resize()\n");
189      return;
190   }
191}
192
193
194
195static void
196EventLoop(void)
197{
198   XEvent event;
199   while (1) {
200      if (XPending(Dpy) > 0) {
201         XNextEvent( Dpy, &event );
202         switch (event.type) {
203            case Expose:
204               Redraw();
205               break;
206            case ConfigureNotify:
207               Resize(event.xany.window, event.xconfigure.width, event.xconfigure.height);
208               break;
209            case KeyPress:
210               {
211                  char buf[100];
212                  KeySym keySym;
213                  XComposeStatus stat;
214                  XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
215                  if (keySym == XK_Escape) {
216                        /* exit */
217                        return;
218                  }
219                  else if (buf[0] == 'f') {
220                     DrawFront = !DrawFront;
221                     printf("Drawing to %s buffer\n",
222                            DrawFront ? "GL_FRONT" : "GL_BACK");
223                  }
224               }
225               break;
226            default:
227               /*no-op*/ ;
228         }
229      }
230      else {
231         /* animate */
232         Redraw();
233      }
234   }
235}
236
237
238static void
239Init(void)
240{
241   XVisualInfo *visinfo;
242   int attrib[] = { GLX_RGBA,
243		    GLX_RED_SIZE, 1,
244		    GLX_GREEN_SIZE, 1,
245		    GLX_BLUE_SIZE, 1,
246		    GLX_DOUBLEBUFFER,
247		    None };
248   int major, minor;
249
250   Dpy = XOpenDisplay(NULL);
251   if (!Dpy) {
252      printf("Couldn't open default display!\n");
253      exit(1);
254   }
255
256   ScrNum = DefaultScreen(Dpy);
257
258   glXQueryVersion(Dpy, &major, &minor);
259
260   if (major * 100 + minor >= 103) {
261      make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
262	  glXGetProcAddressARB( (GLubyte *) "glXMakeContextCurrent" );
263   }
264   else {
265      const char * const glxExtensions = glXQueryExtensionsString(Dpy, ScrNum);
266      const char * ext = strstr( glxExtensions, "GLX_SGI_make_current_read" );
267      const size_t len = strlen( "GLX_SGI_make_current_read" );
268
269      if ( (ext != NULL)
270	   && ((ext[len] == ' ') || (ext[len] == '\0')) ) {
271	 make_context_current = (PFNGLXMAKECURRENTREADSGIPROC)
272	     glXGetProcAddressARB( (GLubyte *) "glXMakeCurrentReadSGI" );
273      }
274   }
275
276   if (make_context_current == NULL) {
277      fprintf(stderr, "Sorry, this program requires either GLX 1.3 "
278	      "or GLX_SGI_make_current_read.\n");
279      exit(1);
280   }
281
282   visinfo = glXChooseVisual(Dpy, ScrNum, attrib);
283   if (!visinfo) {
284      printf("Unable to find RGB, double-buffered visual\n");
285      exit(1);
286   }
287
288   Context = glXCreateContext(Dpy, visinfo, NULL, True);
289   if (!Context) {
290      printf("Couldn't create GLX context\n");
291      exit(1);
292   }
293
294
295   Win[0] = CreateWindow(Dpy, ScrNum, visinfo,
296                         0, 0, 300, 300, "source window");
297
298   Win[1] = CreateWindow(Dpy, ScrNum, visinfo,
299                         350, 0, 300, 300, "dest window");
300
301   printf("Press Esc to exit\n");
302   printf("Press 'f' to toggle front/back buffer drawing\n");
303}
304
305
306int
307main(int argc, char *argv[])
308{
309   if (argc > 1 && strcmp(argv[1], "-clip") == 0)
310      TestClipping = GL_TRUE;
311   Init();
312   EventLoop();
313   return 0;
314}
315
316
317#else
318
319
320int
321main(int argc, char *argv[])
322{
323   printf("This program requires GLX 1.3!\n");
324   return 0;
325}
326
327
328#endif /* GLX_VERSION_1_3 */
329