glxpixmap.c revision 32001f49
1
2
3/*
4 * A demonstration of using the GLXPixmap functions.  This program is in
5 * the public domain.
6 *
7 * Brian Paul
8 */
9
10
11#include <GL/gl.h>
12#define GLX_GLXEXT_PROTOTYPES
13#include <GL/glx.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17
18
19static GLXContext ctx;
20static XVisualInfo *visinfo;
21static GC gc;
22
23
24
25static Window make_rgb_window( Display *dpy,
26				  unsigned int width, unsigned int height )
27{
28   const int sbAttrib[] = { GLX_RGBA,
29                            GLX_RED_SIZE, 1,
30                            GLX_GREEN_SIZE, 1,
31                            GLX_BLUE_SIZE, 1,
32                            None };
33   const int dbAttrib[] = { GLX_RGBA,
34                            GLX_RED_SIZE, 1,
35                            GLX_GREEN_SIZE, 1,
36                            GLX_BLUE_SIZE, 1,
37                            GLX_DOUBLEBUFFER,
38                            None };
39   int scrnum;
40   XSetWindowAttributes attr;
41   unsigned long mask;
42   Window root;
43   Window win;
44
45   scrnum = DefaultScreen( dpy );
46   root = RootWindow( dpy, scrnum );
47
48   visinfo = glXChooseVisual( dpy, scrnum, (int *) sbAttrib );
49   if (!visinfo) {
50      visinfo = glXChooseVisual( dpy, scrnum, (int *) dbAttrib );
51      if (!visinfo) {
52         printf("Error: couldn't get an RGB visual\n");
53         exit(1);
54      }
55   }
56
57   /* window attributes */
58   attr.background_pixel = 0;
59   attr.border_pixel = 0;
60   /* TODO: share root colormap if possible */
61   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
62   attr.event_mask = StructureNotifyMask | ExposureMask;
63   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
64
65   win = XCreateWindow( dpy, root, 0, 0, width, height,
66		        0, visinfo->depth, InputOutput,
67		        visinfo->visual, mask, &attr );
68
69   /* make an X GC so we can do XCopyArea later */
70   gc = XCreateGC( dpy, win, 0, NULL );
71
72   /* need indirect context */
73   ctx = glXCreateContext( dpy, visinfo, NULL, False );
74   if (!ctx) {
75      printf("Error: glXCreateContext failed\n");
76      exit(-1);
77   }
78
79   printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No");
80
81   return win;
82}
83
84
85static GLXPixmap make_pixmap( Display *dpy, Window win,
86			       unsigned int width, unsigned int height,
87                               Pixmap *pixmap)
88{
89   Pixmap pm;
90   GLXPixmap glxpm;
91   XWindowAttributes attr;
92
93   pm = XCreatePixmap( dpy, win, width, height, visinfo->depth );
94   if (!pm) {
95      printf("Error: XCreatePixmap failed\n");
96      exit(-1);
97   }
98
99   XGetWindowAttributes( dpy, win, &attr );
100
101   /*
102    * IMPORTANT:
103    *   Use the glXCreateGLXPixmapMESA funtion when using Mesa because
104    *   Mesa needs to know the colormap associated with a pixmap in order
105    *   to render correctly.  This is because Mesa allows RGB rendering
106    *   into any kind of visual, not just TrueColor or DirectColor.
107    */
108#ifdef GLX_MESA_pixmap_colormap
109   if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) {
110      /* stand-alone Mesa, specify the colormap */
111      PFNGLXCREATEGLXPIXMAPMESAPROC glXCreateGLXPixmapMESA_func =
112         (PFNGLXCREATEGLXPIXMAPMESAPROC)
113         glXGetProcAddressARB((GLubyte *) "glXCreateGLXPixmapMESA");
114      glxpm = glXCreateGLXPixmapMESA_func( dpy, visinfo, pm, attr.colormap );
115   }
116   else {
117      glxpm = glXCreateGLXPixmap( dpy, visinfo, pm );
118   }
119#else
120   /* This will work with Mesa too if the visual is TrueColor or DirectColor */
121   glxpm = glXCreateGLXPixmap( dpy, visinfo, pm );
122#endif
123
124   if (!glxpm) {
125      printf("Error: GLXCreateGLXPixmap failed\n");
126      exit(-1);
127   }
128
129   *pixmap = pm;
130
131   return glxpm;
132}
133
134
135
136static void event_loop( Display *dpy, GLXPixmap pm )
137{
138   XEvent event;
139
140   while (1) {
141      XNextEvent( dpy, &event );
142
143      switch (event.type) {
144	 case Expose:
145	    printf("Redraw\n");
146	    /* copy the image from GLXPixmap to window */
147	    XCopyArea( dpy, pm, event.xany.window,  /* src, dest */
148		       gc, 0, 0, 300, 300,          /* gc, src pos, size */
149		       0, 0 );                      /* dest pos */
150	    break;
151	 case ConfigureNotify:
152	    /* nothing */
153	    break;
154      }
155   }
156}
157
158
159
160int main( int argc, char *argv[] )
161{
162   Display *dpy;
163   Window win;
164   Pixmap pm;
165   GLXPixmap glxpm;
166
167   dpy = XOpenDisplay(NULL);
168
169   win = make_rgb_window( dpy, 300, 300 );
170   glxpm = make_pixmap( dpy, win, 300, 300, &pm );
171
172   glXMakeCurrent( dpy, glxpm, ctx );
173   printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER));
174
175   /* Render an image into the pixmap */
176   glShadeModel( GL_FLAT );
177   glClearColor( 0.5, 0.5, 0.5, 1.0 );
178   glClear( GL_COLOR_BUFFER_BIT );
179   glViewport( 0, 0, 300, 300 );
180   glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 );
181   glColor3f( 0.0, 1.0, 1.0 );
182   glRectf( -0.75, -0.75, 0.75, 0.75 );
183   glFlush();
184   glXWaitGL();
185
186   XMapWindow( dpy, win );
187
188   event_loop( dpy, pm );
189   return 0;
190}
191