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 44static float top, bottom; 45 46static PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL; 47static PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL; 48 49 50static Display * 51OpenDisplay(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 84static GLXFBConfig 85ChoosePixmapFBConfig(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 135static GLXPixmap 136CreatePixmap(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 155static void 156DrawPixmapImage(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 188static XVisualInfo * 189ChooseWindowVisual(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 212static Window 213CreateWindow(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 249static void 250BindPixmapTexture(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 269static void 270Resize(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 281static void 282Redraw(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 307static void 308EventLoop(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 363int 364main(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