| /* |
| * Mesa 3-D graphics library |
| * Version: 7.1 |
| * |
| * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person obtaining a |
| * copy of this software and associated documentation files (the "Software"), |
| * to deal in the Software without restriction, including without limitation |
| * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| * and/or sell copies of the Software, and to permit persons to whom the |
| * Software is furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be included |
| * in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
| * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| */ |
| |
| |
| /* |
| * Test the GLX_EXT_texture_from_pixmap extension |
| * Brian Paul |
| * 19 May 2007 |
| */ |
| |
| |
| #define GL_GLEXT_PROTOTYPES |
| #define GLX_GLXEXT_PROTOTYPES |
| #include <GL/gl.h> |
| #include <GL/glx.h> |
| #include <X11/keysym.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| |
| |
| static float top, bottom; |
| |
| static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL; |
| static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL; |
| |
| |
| static Display * |
| OpenDisplay(void) |
| { |
| int screen; |
| Display *dpy; |
| const char *ext; |
| |
| dpy = XOpenDisplay(NULL); |
| if (!dpy) { |
| printf("Couldn't open default display!\n"); |
| exit(1); |
| } |
| |
| screen = DefaultScreen(dpy); |
| ext = glXQueryExtensionsString(dpy, screen); |
| if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) { |
| fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n"); |
| exit(1); |
| } |
| |
| glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC) |
| glXGetProcAddress((GLubyte *) "glXBindTexImageEXT"); |
| glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC) |
| glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT"); |
| |
| if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) { |
| fprintf(stderr, "glXGetProcAddress failed!\n"); |
| exit(1); |
| } |
| |
| return dpy; |
| } |
| |
| |
| static GLXFBConfig |
| ChoosePixmapFBConfig(Display *display) |
| { |
| int screen = DefaultScreen(display); |
| GLXFBConfig *fbconfigs; |
| int i, nfbconfigs, value; |
| |
| fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs); |
| for (i = 0; i < nfbconfigs; i++) { |
| |
| glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value); |
| if (!(value & GLX_PIXMAP_BIT)) |
| continue; |
| |
| glXGetFBConfigAttrib(display, fbconfigs[i], |
| GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value); |
| if (!(value & GLX_TEXTURE_2D_BIT_EXT)) |
| continue; |
| |
| glXGetFBConfigAttrib(display, fbconfigs[i], |
| GLX_BIND_TO_TEXTURE_RGBA_EXT, &value); |
| if (value == False) { |
| glXGetFBConfigAttrib(display, fbconfigs[i], |
| GLX_BIND_TO_TEXTURE_RGB_EXT, &value); |
| if (value == False) |
| continue; |
| } |
| |
| glXGetFBConfigAttrib(display, fbconfigs[i], |
| GLX_Y_INVERTED_EXT, &value); |
| if (value == True) { |
| top = 0.0f; |
| bottom = 1.0f; |
| } |
| else { |
| top = 1.0f; |
| bottom = 0.0f; |
| } |
| |
| break; |
| } |
| |
| if (i == nfbconfigs) { |
| printf("Unable to find FBconfig for texturing\n"); |
| exit(1); |
| } |
| |
| return fbconfigs[i]; |
| } |
| |
| |
| static GLXPixmap |
| CreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p) |
| { |
| GLXPixmap gp; |
| const int pixmapAttribs[] = { |
| GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, |
| GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, |
| None |
| }; |
| Window root = RootWindow(dpy, 0); |
| |
| *p = XCreatePixmap(dpy, root, w, h, 24); |
| XSync(dpy, 0); |
| gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs); |
| XSync(dpy, 0); |
| |
| return gp; |
| } |
| |
| |
| static void |
| DrawPixmapImage(Display *dpy, Pixmap pm, int w, int h) |
| { |
| XGCValues gcvals; |
| GC gc; |
| |
| gcvals.background = 0; |
| gc = XCreateGC(dpy, pm, GCBackground, &gcvals); |
| |
| XSetForeground(dpy, gc, 0x0); |
| XFillRectangle(dpy, pm, gc, 0, 0, w, h); |
| |
| XSetForeground(dpy, gc, 0xff0000); |
| XFillRectangle(dpy, pm, gc, 0, 0, 50, 50); |
| |
| XSetForeground(dpy, gc, 0x00ff00); |
| XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50); |
| |
| XSetForeground(dpy, gc, 0x0000ff); |
| XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50); |
| |
| XSetForeground(dpy, gc, 0xffffff); |
| XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50); |
| |
| XSetForeground(dpy, gc, 0xffff00); |
| XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel); |
| XDrawLine(dpy, pm, gc, 0, 0, w, h); |
| XDrawLine(dpy, pm, gc, 0, h, w, 0); |
| |
| XFreeGC(dpy, gc); |
| } |
| |
| |
| static XVisualInfo * |
| ChooseWindowVisual(Display *dpy) |
| { |
| int screen = DefaultScreen(dpy); |
| XVisualInfo *visinfo; |
| int attribs[] = { |
| GLX_RGBA, |
| GLX_RED_SIZE, 1, |
| GLX_GREEN_SIZE, 1, |
| GLX_BLUE_SIZE, 1, |
| GLX_DOUBLEBUFFER, |
| None |
| }; |
| |
| visinfo = glXChooseVisual(dpy, screen, attribs); |
| if (!visinfo) { |
| printf("Unable to find RGB, double-buffered visual\n"); |
| exit(1); |
| } |
| |
| return visinfo; |
| } |
| |
| |
| static Window |
| CreateWindow(Display *dpy, XVisualInfo *visinfo, |
| int width, int height, const char *name) |
| { |
| int screen = DefaultScreen(dpy); |
| Window win; |
| XSetWindowAttributes attr; |
| unsigned long mask; |
| Window root; |
| |
| root = RootWindow(dpy, screen); |
| |
| /* window attributes */ |
| attr.background_pixel = 0; |
| attr.border_pixel = 0; |
| attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); |
| attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; |
| mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; |
| |
| win = XCreateWindow(dpy, root, 0, 0, width, height, |
| 0, visinfo->depth, InputOutput, |
| visinfo->visual, mask, &attr); |
| if (win) { |
| XSizeHints sizehints; |
| sizehints.width = width; |
| sizehints.height = height; |
| sizehints.flags = USSize; |
| XSetNormalHints(dpy, win, &sizehints); |
| XSetStandardProperties(dpy, win, name, name, |
| None, (char **)NULL, 0, &sizehints); |
| |
| XMapWindow(dpy, win); |
| } |
| return win; |
| } |
| |
| |
| static void |
| BindPixmapTexture(Display *dpy, GLXPixmap gp) |
| { |
| GLuint texture; |
| |
| glGenTextures(1, &texture); |
| glBindTexture(GL_TEXTURE_2D, texture); |
| |
| glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL); |
| |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| |
| glEnable(GL_TEXTURE_2D); |
| /* |
| glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT); |
| */ |
| } |
| |
| |
| static void |
| Resize(Window win, unsigned int width, unsigned int height) |
| { |
| float sz = 1.5; |
| glViewport(0, 0, width, height); |
| glMatrixMode(GL_PROJECTION); |
| glLoadIdentity(); |
| glOrtho(-sz, sz, -sz, sz, -1.0, 1.0); |
| glMatrixMode(GL_MODELVIEW); |
| } |
| |
| |
| static void |
| Redraw(Display *dpy, Window win, float rot) |
| { |
| glClearColor(0.25, 0.25, 0.25, 0.0); |
| glClear(GL_COLOR_BUFFER_BIT); |
| glPushMatrix(); |
| glRotatef(rot, 0, 0, 1); |
| glRotatef(2.0 * rot, 1, 0, 0); |
| |
| glBegin(GL_QUADS); |
| glTexCoord2d(0.0, bottom); |
| glVertex2f(-1, -1); |
| glTexCoord2d(1.0, bottom); |
| glVertex2f( 1, -1); |
| glTexCoord2d(1.0, top); |
| glVertex2d(1.0, 1.0); |
| glTexCoord2d(0.0, top); |
| glVertex2f(-1.0, 1.0); |
| glEnd(); |
| |
| glPopMatrix(); |
| |
| glXSwapBuffers(dpy, win); |
| } |
| |
| |
| static void |
| EventLoop(Display *dpy, Window win) |
| { |
| GLfloat rot = 0.0; |
| int anim = 0; |
| |
| while (1) { |
| if (!anim || XPending(dpy) > 0) { |
| XEvent event; |
| XNextEvent(dpy, &event); |
| |
| switch (event.type) { |
| case Expose: |
| Redraw(dpy, win, rot); |
| break; |
| case ConfigureNotify: |
| Resize(event.xany.window, |
| event.xconfigure.width, |
| event.xconfigure.height); |
| break; |
| case KeyPress: |
| { |
| char buf[100]; |
| KeySym keySym; |
| XComposeStatus stat; |
| XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat); |
| if (keySym == XK_Escape) { |
| return; /* exit */ |
| } |
| else if (keySym == XK_r) { |
| rot += 1.0; |
| Redraw(dpy, win, rot); |
| } |
| else if (keySym == XK_a) { |
| anim = !anim; |
| } |
| else if (keySym == XK_R) { |
| rot -= 1.0; |
| Redraw(dpy, win, rot); |
| } |
| } |
| break; |
| default: |
| ; /*no-op*/ |
| } |
| } |
| else { |
| /* animate */ |
| rot += 1.0; |
| Redraw(dpy, win, rot); |
| } |
| } |
| } |
| |
| |
| |
| int |
| main(int argc, char *argv[]) |
| { |
| Display *dpy; |
| GLXFBConfig pixmapConfig; |
| XVisualInfo *windowVis; |
| GLXPixmap gp; |
| Window win; |
| GLXContext ctx; |
| Pixmap p; |
| |
| dpy = OpenDisplay(); |
| |
| pixmapConfig = ChoosePixmapFBConfig(dpy); |
| windowVis = ChooseWindowVisual(dpy); |
| win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap"); |
| |
| gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p); |
| DrawPixmapImage(dpy, p, 512, 512); |
| |
| ctx = glXCreateContext(dpy, windowVis, NULL, True); |
| if (!ctx) { |
| printf("Couldn't create GLX context\n"); |
| exit(1); |
| } |
| |
| glXMakeCurrent(dpy, win, ctx); |
| |
| BindPixmapTexture(dpy, gp); |
| |
| EventLoop(dpy, win); |
| |
| return 0; |
| } |