1 /*
2  * Mesa 3-D graphics library
3  * Version:  7.1
4  *
5  * Copyright (C) 1999-2007  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  * Test the GLX_EXT_texture_from_pixmap extension
28  * Brian Paul
29  * 19 May 2007
30  */
31 
32 
33 #define GL_GLEXT_PROTOTYPES
34 #define GLX_GLXEXT_PROTOTYPES
35 #include <GL/gl.h>
36 #include <GL/glx.h>
37 #include <X11/keysym.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <unistd.h>
42 
43 
44 static float top, bottom;
45 
46 static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL;
47 static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL;
48 
49 
50 static Display *
OpenDisplay(void)51 OpenDisplay(void)
52 {
53    int screen;
54    Display *dpy;
55    const char *ext;
56 
57    dpy = XOpenDisplay(NULL);
58    if (!dpy) {
59       printf("Couldn't open default display!\n");
60       exit(1);
61    }
62 
63    screen = DefaultScreen(dpy);
64    ext = glXQueryExtensionsString(dpy, screen);
65    if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) {
66       fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n");
67       exit(1);
68    }
69 
70    glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC)
71       glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
72    glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC)
73       glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT");
74 
75    if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) {
76       fprintf(stderr, "glXGetProcAddress failed!\n");
77       exit(1);
78    }
79 
80    return dpy;
81 }
82 
83 
84 static GLXFBConfig
ChoosePixmapFBConfig(Display * display)85 ChoosePixmapFBConfig(Display *display)
86 {
87    int screen = DefaultScreen(display);
88    GLXFBConfig *fbconfigs;
89    int i, nfbconfigs = 0, value;
90 
91    fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs);
92    for (i = 0; i < nfbconfigs; i++) {
93 
94       glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
95       if (!(value & GLX_PIXMAP_BIT))
96          continue;
97 
98       glXGetFBConfigAttrib(display, fbconfigs[i],
99                            GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value);
100       if (!(value & GLX_TEXTURE_2D_BIT_EXT))
101          continue;
102 
103       glXGetFBConfigAttrib(display, fbconfigs[i],
104                            GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
105       if (value == False) {
106          glXGetFBConfigAttrib(display, fbconfigs[i],
107                               GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
108          if (value == False)
109             continue;
110       }
111 
112       glXGetFBConfigAttrib(display, fbconfigs[i],
113                            GLX_Y_INVERTED_EXT, &value);
114       if (value == True) {
115          top = 0.0f;
116          bottom = 1.0f;
117       }
118       else {
119          top = 1.0f;
120          bottom = 0.0f;
121       }
122 
123       break;
124    }
125 
126    if (i == nfbconfigs) {
127       printf("Unable to find FBconfig for texturing\n");
128       exit(1);
129    }
130 
131    return fbconfigs[i];
132 }
133 
134 
135 static GLXPixmap
CreatePixmap(Display * dpy,GLXFBConfig config,int w,int h,Pixmap * p)136 CreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p)
137 {
138    GLXPixmap gp;
139    const int pixmapAttribs[] = {
140       GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
141       GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
142       None
143    };
144    Window root = RootWindow(dpy, 0);
145 
146    *p = XCreatePixmap(dpy, root, w, h, 24);
147    XSync(dpy, 0);
148    gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs);
149    XSync(dpy, 0);
150 
151    return gp;
152 }
153 
154 
155 static void
DrawPixmapImage(Display * dpy,Pixmap pm,int w,int h)156 DrawPixmapImage(Display *dpy, Pixmap pm, int w, int h)
157 {
158    XGCValues gcvals;
159    GC gc;
160 
161    gcvals.background = 0;
162    gc = XCreateGC(dpy, pm, GCBackground, &gcvals);
163 
164    XSetForeground(dpy, gc, 0x0);
165    XFillRectangle(dpy, pm, gc, 0, 0, w, h);
166 
167    XSetForeground(dpy, gc, 0xff0000);
168    XFillRectangle(dpy, pm, gc, 0, 0, 50, 50);
169 
170    XSetForeground(dpy, gc, 0x00ff00);
171    XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50);
172 
173    XSetForeground(dpy, gc, 0x0000ff);
174    XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50);
175 
176    XSetForeground(dpy, gc, 0xffffff);
177    XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50);
178 
179    XSetForeground(dpy, gc, 0xffff00);
180    XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel);
181    XDrawLine(dpy, pm, gc, 0, 0, w, h);
182    XDrawLine(dpy, pm, gc, 0, h, w, 0);
183 
184    XFreeGC(dpy, gc);
185 }
186 
187 
188 static XVisualInfo *
ChooseWindowVisual(Display * dpy)189 ChooseWindowVisual(Display *dpy)
190 {
191    int screen = DefaultScreen(dpy);
192    XVisualInfo *visinfo;
193    int attribs[] = {
194       GLX_RGBA,
195       GLX_RED_SIZE, 1,
196       GLX_GREEN_SIZE, 1,
197       GLX_BLUE_SIZE, 1,
198       GLX_DOUBLEBUFFER,
199       None
200    };
201 
202    visinfo = glXChooseVisual(dpy, screen, attribs);
203    if (!visinfo) {
204       printf("Unable to find RGB, double-buffered visual\n");
205       exit(1);
206    }
207 
208    return visinfo;
209 }
210 
211 
212 static Window
CreateWindow(Display * dpy,XVisualInfo * visinfo,int width,int height,const char * name)213 CreateWindow(Display *dpy, XVisualInfo *visinfo,
214              int width, int height, const char *name)
215 {
216    int screen = DefaultScreen(dpy);
217    Window win;
218    XSetWindowAttributes attr;
219    unsigned long mask;
220    Window root;
221 
222    root = RootWindow(dpy, screen);
223 
224    /* window attributes */
225    attr.background_pixel = 0;
226    attr.border_pixel = 0;
227    attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
228    attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
229    mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
230 
231    win = XCreateWindow(dpy, root, 0, 0, width, height,
232                         0, visinfo->depth, InputOutput,
233                         visinfo->visual, mask, &attr);
234    if (win) {
235       XSizeHints sizehints;
236       sizehints.width  = width;
237       sizehints.height = height;
238       sizehints.flags = USSize;
239       XSetNormalHints(dpy, win, &sizehints);
240       XSetStandardProperties(dpy, win, name, name,
241                               None, (char **)NULL, 0, &sizehints);
242 
243       XMapWindow(dpy, win);
244    }
245    return win;
246 }
247 
248 
249 static void
BindPixmapTexture(Display * dpy,GLXPixmap gp)250 BindPixmapTexture(Display *dpy, GLXPixmap gp)
251 {
252    GLuint texture;
253 
254    glGenTextures(1, &texture);
255    glBindTexture(GL_TEXTURE_2D, texture);
256 
257    glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL);
258 
259    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
260    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
261 
262    glEnable(GL_TEXTURE_2D);
263    /*
264      glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT);
265    */
266 }
267 
268 
269 static void
Resize(Window win,unsigned int width,unsigned int height)270 Resize(Window win, unsigned int width, unsigned int height)
271 {
272    float sz = 1.5;
273    glViewport(0, 0, width, height);
274    glMatrixMode(GL_PROJECTION);
275    glLoadIdentity();
276    glOrtho(-sz, sz, -sz, sz, -1.0, 1.0);
277    glMatrixMode(GL_MODELVIEW);
278 }
279 
280 
281 static void
Redraw(Display * dpy,Window win,float rot)282 Redraw(Display *dpy, Window win, float rot)
283 {
284    glClearColor(0.25, 0.25, 0.25, 0.0);
285    glClear(GL_COLOR_BUFFER_BIT);
286    glPushMatrix();
287    glRotatef(rot, 0, 0, 1);
288    glRotatef(2.0 * rot, 1, 0, 0);
289 
290    glBegin(GL_QUADS);
291    glTexCoord2d(0.0, bottom);
292    glVertex2f(-1, -1);
293    glTexCoord2d(1.0, bottom);
294    glVertex2f( 1, -1);
295    glTexCoord2d(1.0, top);
296    glVertex2d(1.0, 1.0);
297    glTexCoord2d(0.0, top);
298    glVertex2f(-1.0, 1.0);
299    glEnd();
300 
301    glPopMatrix();
302 
303    glXSwapBuffers(dpy, win);
304 }
305 
306 
307 static void
EventLoop(Display * dpy,Window win)308 EventLoop(Display *dpy, Window win)
309 {
310    GLfloat rot = 0.0;
311    int anim = 0;
312 
313    while (1) {
314       if (!anim || XPending(dpy) > 0) {
315          XEvent event;
316          XNextEvent(dpy, &event);
317 
318          switch (event.type) {
319          case Expose:
320             Redraw(dpy, win, rot);
321             break;
322          case ConfigureNotify:
323             Resize(event.xany.window,
324                    event.xconfigure.width,
325                    event.xconfigure.height);
326             break;
327          case KeyPress:
328             {
329                char buf[100];
330                KeySym keySym;
331                XComposeStatus stat;
332                XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
333                if (keySym == XK_Escape) {
334                   return; /* exit */
335                }
336                else if (keySym == XK_r) {
337                   rot += 1.0;
338                   Redraw(dpy, win, rot);
339                }
340                else if (keySym == XK_a) {
341                   anim = !anim;
342                }
343                else if (keySym == XK_R) {
344                   rot -= 1.0;
345                   Redraw(dpy, win, rot);
346                }
347             }
348             break;
349          default:
350             ; /*no-op*/
351          }
352       }
353       else {
354          /* animate */
355          rot += 1.0;
356          Redraw(dpy, win, rot);
357       }
358    }
359 }
360 
361 
362 
363 int
main(int argc,char * argv[])364 main(int argc, char *argv[])
365 {
366    Display *dpy;
367    GLXFBConfig pixmapConfig;
368    XVisualInfo *windowVis;
369    GLXPixmap gp;
370    Window win;
371    GLXContext ctx;
372    Pixmap p;
373 
374    dpy = OpenDisplay();
375 
376    pixmapConfig = ChoosePixmapFBConfig(dpy);
377    windowVis = ChooseWindowVisual(dpy);
378    win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap");
379 
380    gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p);
381    DrawPixmapImage(dpy, p, 512, 512);
382 
383    ctx = glXCreateContext(dpy, windowVis, NULL, True);
384    if (!ctx) {
385       printf("Couldn't create GLX context\n");
386       exit(1);
387    }
388 
389    glXMakeCurrent(dpy, win, ctx);
390 
391    BindPixmapTexture(dpy, gp);
392 
393    EventLoop(dpy, win);
394 
395    return 0;
396 }
397