/* * 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 #include #include #include #include #include #include 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; }