132001f49Smrg/*
232001f49Smrg * Mesa 3-D graphics library
332001f49Smrg * Version:  7.1
432001f49Smrg *
532001f49Smrg * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
632001f49Smrg *
732001f49Smrg * Permission is hereby granted, free of charge, to any person obtaining a
832001f49Smrg * copy of this software and associated documentation files (the "Software"),
932001f49Smrg * to deal in the Software without restriction, including without limitation
1032001f49Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1132001f49Smrg * and/or sell copies of the Software, and to permit persons to whom the
1232001f49Smrg * Software is furnished to do so, subject to the following conditions:
1332001f49Smrg *
1432001f49Smrg * The above copyright notice and this permission notice shall be included
1532001f49Smrg * in all copies or substantial portions of the Software.
1632001f49Smrg *
1732001f49Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1832001f49Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1932001f49Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2032001f49Smrg * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2132001f49Smrg * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
2232001f49Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2332001f49Smrg */
2432001f49Smrg
2532001f49Smrg
2632001f49Smrg/*
2732001f49Smrg * Test the GLX_EXT_texture_from_pixmap extension
2832001f49Smrg * Brian Paul
2932001f49Smrg * 19 May 2007
3032001f49Smrg */
3132001f49Smrg
3232001f49Smrg
3332001f49Smrg#define GL_GLEXT_PROTOTYPES
3432001f49Smrg#define GLX_GLXEXT_PROTOTYPES
3532001f49Smrg#include <GL/gl.h>
3632001f49Smrg#include <GL/glx.h>
3732001f49Smrg#include <X11/keysym.h>
3832001f49Smrg#include <stdio.h>
3932001f49Smrg#include <stdlib.h>
4032001f49Smrg#include <string.h>
4132001f49Smrg#include <unistd.h>
4232001f49Smrg
4332001f49Smrg
4432001f49Smrgstatic float top, bottom;
4532001f49Smrg
4632001f49Smrgstatic PFNGLXBINDTEXIMAGEEXTPROC glXBindTexImageEXT_func = NULL;
4732001f49Smrgstatic PFNGLXRELEASETEXIMAGEEXTPROC glXReleaseTexImageEXT_func = NULL;
4832001f49Smrg
4932001f49Smrg
5032001f49Smrgstatic Display *
5132001f49SmrgOpenDisplay(void)
5232001f49Smrg{
5332001f49Smrg   int screen;
5432001f49Smrg   Display *dpy;
5532001f49Smrg   const char *ext;
5632001f49Smrg
5732001f49Smrg   dpy = XOpenDisplay(NULL);
5832001f49Smrg   if (!dpy) {
5932001f49Smrg      printf("Couldn't open default display!\n");
6032001f49Smrg      exit(1);
6132001f49Smrg   }
6232001f49Smrg
6332001f49Smrg   screen = DefaultScreen(dpy);
6432001f49Smrg   ext = glXQueryExtensionsString(dpy, screen);
6532001f49Smrg   if (!strstr(ext, "GLX_EXT_texture_from_pixmap")) {
6632001f49Smrg      fprintf(stderr, "GLX_EXT_texture_from_pixmap not supported.\n");
6732001f49Smrg      exit(1);
6832001f49Smrg   }
6932001f49Smrg
7032001f49Smrg   glXBindTexImageEXT_func = (PFNGLXBINDTEXIMAGEEXTPROC)
7132001f49Smrg      glXGetProcAddress((GLubyte *) "glXBindTexImageEXT");
7232001f49Smrg   glXReleaseTexImageEXT_func = (PFNGLXRELEASETEXIMAGEEXTPROC)
7332001f49Smrg      glXGetProcAddress((GLubyte*) "glXReleaseTexImageEXT");
7432001f49Smrg
7532001f49Smrg   if (!glXBindTexImageEXT_func || !glXReleaseTexImageEXT_func) {
7632001f49Smrg      fprintf(stderr, "glXGetProcAddress failed!\n");
7732001f49Smrg      exit(1);
7832001f49Smrg   }
7932001f49Smrg
8032001f49Smrg   return dpy;
8132001f49Smrg}
8232001f49Smrg
8332001f49Smrg
8432001f49Smrgstatic GLXFBConfig
8532001f49SmrgChoosePixmapFBConfig(Display *display)
8632001f49Smrg{
8732001f49Smrg   int screen = DefaultScreen(display);
8832001f49Smrg   GLXFBConfig *fbconfigs;
8932001f49Smrg   int i, nfbconfigs = 0, value;
9032001f49Smrg
9132001f49Smrg   fbconfigs = glXGetFBConfigs(display, screen, &nfbconfigs);
9232001f49Smrg   for (i = 0; i < nfbconfigs; i++) {
9332001f49Smrg
9432001f49Smrg      glXGetFBConfigAttrib(display, fbconfigs[i], GLX_DRAWABLE_TYPE, &value);
9532001f49Smrg      if (!(value & GLX_PIXMAP_BIT))
9632001f49Smrg         continue;
9732001f49Smrg
9832001f49Smrg      glXGetFBConfigAttrib(display, fbconfigs[i],
9932001f49Smrg                           GLX_BIND_TO_TEXTURE_TARGETS_EXT, &value);
10032001f49Smrg      if (!(value & GLX_TEXTURE_2D_BIT_EXT))
10132001f49Smrg         continue;
10232001f49Smrg
10332001f49Smrg      glXGetFBConfigAttrib(display, fbconfigs[i],
10432001f49Smrg                           GLX_BIND_TO_TEXTURE_RGBA_EXT, &value);
10532001f49Smrg      if (value == False) {
10632001f49Smrg         glXGetFBConfigAttrib(display, fbconfigs[i],
10732001f49Smrg                              GLX_BIND_TO_TEXTURE_RGB_EXT, &value);
10832001f49Smrg         if (value == False)
10932001f49Smrg            continue;
11032001f49Smrg      }
11132001f49Smrg
11232001f49Smrg      glXGetFBConfigAttrib(display, fbconfigs[i],
11332001f49Smrg                           GLX_Y_INVERTED_EXT, &value);
11432001f49Smrg      if (value == True) {
11532001f49Smrg         top = 0.0f;
11632001f49Smrg         bottom = 1.0f;
11732001f49Smrg      }
11832001f49Smrg      else {
11932001f49Smrg         top = 1.0f;
12032001f49Smrg         bottom = 0.0f;
12132001f49Smrg      }
12232001f49Smrg
12332001f49Smrg      break;
12432001f49Smrg   }
12532001f49Smrg
12632001f49Smrg   if (i == nfbconfigs) {
12732001f49Smrg      printf("Unable to find FBconfig for texturing\n");
12832001f49Smrg      exit(1);
12932001f49Smrg   }
13032001f49Smrg
13132001f49Smrg   return fbconfigs[i];
13232001f49Smrg}
13332001f49Smrg
13432001f49Smrg
13532001f49Smrgstatic GLXPixmap
13632001f49SmrgCreatePixmap(Display *dpy, GLXFBConfig config, int w, int h, Pixmap *p)
13732001f49Smrg{
13832001f49Smrg   GLXPixmap gp;
13932001f49Smrg   const int pixmapAttribs[] = {
14032001f49Smrg      GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
14132001f49Smrg      GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT,
14232001f49Smrg      None
14332001f49Smrg   };
14432001f49Smrg   Window root = RootWindow(dpy, 0);
14532001f49Smrg
14632001f49Smrg   *p = XCreatePixmap(dpy, root, w, h, 24);
14732001f49Smrg   XSync(dpy, 0);
14832001f49Smrg   gp = glXCreatePixmap(dpy, config, *p, pixmapAttribs);
14932001f49Smrg   XSync(dpy, 0);
15032001f49Smrg
15132001f49Smrg   return gp;
15232001f49Smrg}
15332001f49Smrg
15432001f49Smrg
15532001f49Smrgstatic void
15632001f49SmrgDrawPixmapImage(Display *dpy, Pixmap pm, int w, int h)
15732001f49Smrg{
15832001f49Smrg   XGCValues gcvals;
15932001f49Smrg   GC gc;
16032001f49Smrg
16132001f49Smrg   gcvals.background = 0;
16232001f49Smrg   gc = XCreateGC(dpy, pm, GCBackground, &gcvals);
16332001f49Smrg
16432001f49Smrg   XSetForeground(dpy, gc, 0x0);
16532001f49Smrg   XFillRectangle(dpy, pm, gc, 0, 0, w, h);
16632001f49Smrg
16732001f49Smrg   XSetForeground(dpy, gc, 0xff0000);
16832001f49Smrg   XFillRectangle(dpy, pm, gc, 0, 0, 50, 50);
16932001f49Smrg
17032001f49Smrg   XSetForeground(dpy, gc, 0x00ff00);
17132001f49Smrg   XFillRectangle(dpy, pm, gc, w - 50, 0, 50, 50);
17232001f49Smrg
17332001f49Smrg   XSetForeground(dpy, gc, 0x0000ff);
17432001f49Smrg   XFillRectangle(dpy, pm, gc, 0, h - 50, 50, 50);
17532001f49Smrg
17632001f49Smrg   XSetForeground(dpy, gc, 0xffffff);
17732001f49Smrg   XFillRectangle(dpy, pm, gc, h - 50, h - 50, 50, 50);
17832001f49Smrg
17932001f49Smrg   XSetForeground(dpy, gc, 0xffff00);
18032001f49Smrg   XSetLineAttributes(dpy, gc, 3, LineSolid, CapButt, JoinBevel);
18132001f49Smrg   XDrawLine(dpy, pm, gc, 0, 0, w, h);
18232001f49Smrg   XDrawLine(dpy, pm, gc, 0, h, w, 0);
18332001f49Smrg
18432001f49Smrg   XFreeGC(dpy, gc);
18532001f49Smrg}
18632001f49Smrg
18732001f49Smrg
18832001f49Smrgstatic XVisualInfo *
18932001f49SmrgChooseWindowVisual(Display *dpy)
19032001f49Smrg{
19132001f49Smrg   int screen = DefaultScreen(dpy);
19232001f49Smrg   XVisualInfo *visinfo;
19332001f49Smrg   int attribs[] = {
19432001f49Smrg      GLX_RGBA,
19532001f49Smrg      GLX_RED_SIZE, 1,
19632001f49Smrg      GLX_GREEN_SIZE, 1,
19732001f49Smrg      GLX_BLUE_SIZE, 1,
19832001f49Smrg      GLX_DOUBLEBUFFER,
19932001f49Smrg      None
20032001f49Smrg   };
20132001f49Smrg
20232001f49Smrg   visinfo = glXChooseVisual(dpy, screen, attribs);
20332001f49Smrg   if (!visinfo) {
20432001f49Smrg      printf("Unable to find RGB, double-buffered visual\n");
20532001f49Smrg      exit(1);
20632001f49Smrg   }
20732001f49Smrg
20832001f49Smrg   return visinfo;
20932001f49Smrg}
21032001f49Smrg
21132001f49Smrg
21232001f49Smrgstatic Window
21332001f49SmrgCreateWindow(Display *dpy, XVisualInfo *visinfo,
21432001f49Smrg             int width, int height, const char *name)
21532001f49Smrg{
21632001f49Smrg   int screen = DefaultScreen(dpy);
21732001f49Smrg   Window win;
21832001f49Smrg   XSetWindowAttributes attr;
21932001f49Smrg   unsigned long mask;
22032001f49Smrg   Window root;
22132001f49Smrg
22232001f49Smrg   root = RootWindow(dpy, screen);
22332001f49Smrg
22432001f49Smrg   /* window attributes */
22532001f49Smrg   attr.background_pixel = 0;
22632001f49Smrg   attr.border_pixel = 0;
22732001f49Smrg   attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone);
22832001f49Smrg   attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
22932001f49Smrg   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
23032001f49Smrg
23132001f49Smrg   win = XCreateWindow(dpy, root, 0, 0, width, height,
23232001f49Smrg		        0, visinfo->depth, InputOutput,
23332001f49Smrg		        visinfo->visual, mask, &attr);
23432001f49Smrg   if (win) {
23532001f49Smrg      XSizeHints sizehints;
23632001f49Smrg      sizehints.width  = width;
23732001f49Smrg      sizehints.height = height;
23832001f49Smrg      sizehints.flags = USSize;
23932001f49Smrg      XSetNormalHints(dpy, win, &sizehints);
24032001f49Smrg      XSetStandardProperties(dpy, win, name, name,
24132001f49Smrg                              None, (char **)NULL, 0, &sizehints);
24232001f49Smrg
24332001f49Smrg      XMapWindow(dpy, win);
24432001f49Smrg   }
24532001f49Smrg   return win;
24632001f49Smrg}
24732001f49Smrg
24832001f49Smrg
24932001f49Smrgstatic void
25032001f49SmrgBindPixmapTexture(Display *dpy, GLXPixmap gp)
25132001f49Smrg{
25232001f49Smrg   GLuint texture;
25332001f49Smrg
25432001f49Smrg   glGenTextures(1, &texture);
25532001f49Smrg   glBindTexture(GL_TEXTURE_2D, texture);
25632001f49Smrg
25732001f49Smrg   glXBindTexImageEXT_func(dpy, gp, GLX_FRONT_LEFT_EXT, NULL);
25832001f49Smrg
25932001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
26032001f49Smrg   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
26132001f49Smrg
26232001f49Smrg   glEnable(GL_TEXTURE_2D);
26332001f49Smrg   /*
26432001f49Smrg     glXReleaseTexImageEXT_func(display, glxpixmap, GLX_FRONT_LEFT_EXT);
26532001f49Smrg   */
26632001f49Smrg}
26732001f49Smrg
26832001f49Smrg
26932001f49Smrgstatic void
27032001f49SmrgResize(Window win, unsigned int width, unsigned int height)
27132001f49Smrg{
27232001f49Smrg   float sz = 1.5;
27332001f49Smrg   glViewport(0, 0, width, height);
27432001f49Smrg   glMatrixMode(GL_PROJECTION);
27532001f49Smrg   glLoadIdentity();
27632001f49Smrg   glOrtho(-sz, sz, -sz, sz, -1.0, 1.0);
27732001f49Smrg   glMatrixMode(GL_MODELVIEW);
27832001f49Smrg}
27932001f49Smrg
28032001f49Smrg
28132001f49Smrgstatic void
28232001f49SmrgRedraw(Display *dpy, Window win, float rot)
28332001f49Smrg{
28432001f49Smrg   glClearColor(0.25, 0.25, 0.25, 0.0);
28532001f49Smrg   glClear(GL_COLOR_BUFFER_BIT);
28632001f49Smrg   glPushMatrix();
28732001f49Smrg   glRotatef(rot, 0, 0, 1);
28832001f49Smrg   glRotatef(2.0 * rot, 1, 0, 0);
28932001f49Smrg
29032001f49Smrg   glBegin(GL_QUADS);
29132001f49Smrg   glTexCoord2d(0.0, bottom);
29232001f49Smrg   glVertex2f(-1, -1);
29332001f49Smrg   glTexCoord2d(1.0, bottom);
29432001f49Smrg   glVertex2f( 1, -1);
29532001f49Smrg   glTexCoord2d(1.0, top);
29632001f49Smrg   glVertex2d(1.0, 1.0);
29732001f49Smrg   glTexCoord2d(0.0, top);
29832001f49Smrg   glVertex2f(-1.0, 1.0);
29932001f49Smrg   glEnd();
30032001f49Smrg
30132001f49Smrg   glPopMatrix();
30232001f49Smrg
30332001f49Smrg   glXSwapBuffers(dpy, win);
30432001f49Smrg}
30532001f49Smrg
30632001f49Smrg
30732001f49Smrgstatic void
30832001f49SmrgEventLoop(Display *dpy, Window win)
30932001f49Smrg{
31032001f49Smrg   GLfloat rot = 0.0;
31132001f49Smrg   int anim = 0;
31232001f49Smrg
31332001f49Smrg   while (1) {
31432001f49Smrg      if (!anim || XPending(dpy) > 0) {
31532001f49Smrg         XEvent event;
31632001f49Smrg         XNextEvent(dpy, &event);
31732001f49Smrg
31832001f49Smrg         switch (event.type) {
31932001f49Smrg         case Expose:
32032001f49Smrg            Redraw(dpy, win, rot);
32132001f49Smrg            break;
32232001f49Smrg         case ConfigureNotify:
32332001f49Smrg            Resize(event.xany.window,
32432001f49Smrg                   event.xconfigure.width,
32532001f49Smrg                   event.xconfigure.height);
32632001f49Smrg            break;
32732001f49Smrg         case KeyPress:
32832001f49Smrg            {
32932001f49Smrg               char buf[100];
33032001f49Smrg               KeySym keySym;
33132001f49Smrg               XComposeStatus stat;
33232001f49Smrg               XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat);
33332001f49Smrg               if (keySym == XK_Escape) {
33432001f49Smrg                  return; /* exit */
33532001f49Smrg               }
33632001f49Smrg               else if (keySym == XK_r) {
33732001f49Smrg                  rot += 1.0;
33832001f49Smrg                  Redraw(dpy, win, rot);
33932001f49Smrg               }
34032001f49Smrg               else if (keySym == XK_a) {
34132001f49Smrg                  anim = !anim;
34232001f49Smrg               }
34332001f49Smrg               else if (keySym == XK_R) {
34432001f49Smrg                  rot -= 1.0;
34532001f49Smrg                  Redraw(dpy, win, rot);
34632001f49Smrg               }
34732001f49Smrg            }
34832001f49Smrg            break;
34932001f49Smrg         default:
35032001f49Smrg            ; /*no-op*/
35132001f49Smrg         }
35232001f49Smrg      }
35332001f49Smrg      else {
35432001f49Smrg         /* animate */
35532001f49Smrg         rot += 1.0;
35632001f49Smrg         Redraw(dpy, win, rot);
35732001f49Smrg      }
35832001f49Smrg   }
35932001f49Smrg}
36032001f49Smrg
36132001f49Smrg
36232001f49Smrg
36332001f49Smrgint
36432001f49Smrgmain(int argc, char *argv[])
36532001f49Smrg{
36632001f49Smrg   Display *dpy;
36732001f49Smrg   GLXFBConfig pixmapConfig;
36832001f49Smrg   XVisualInfo *windowVis;
36932001f49Smrg   GLXPixmap gp;
37032001f49Smrg   Window win;
37132001f49Smrg   GLXContext ctx;
37232001f49Smrg   Pixmap p;
37332001f49Smrg
37432001f49Smrg   dpy = OpenDisplay();
37532001f49Smrg
37632001f49Smrg   pixmapConfig = ChoosePixmapFBConfig(dpy);
37732001f49Smrg   windowVis = ChooseWindowVisual(dpy);
37832001f49Smrg   win = CreateWindow(dpy, windowVis, 500, 500, "Texture From Pixmap");
37932001f49Smrg
38032001f49Smrg   gp = CreatePixmap(dpy, pixmapConfig, 512, 512, &p);
38132001f49Smrg   DrawPixmapImage(dpy, p, 512, 512);
38232001f49Smrg
38332001f49Smrg   ctx = glXCreateContext(dpy, windowVis, NULL, True);
38432001f49Smrg   if (!ctx) {
38532001f49Smrg      printf("Couldn't create GLX context\n");
38632001f49Smrg      exit(1);
38732001f49Smrg   }
38832001f49Smrg
38932001f49Smrg   glXMakeCurrent(dpy, win, ctx);
39032001f49Smrg
39132001f49Smrg   BindPixmapTexture(dpy, gp);
39232001f49Smrg
39332001f49Smrg   EventLoop(dpy, win);
39432001f49Smrg
39532001f49Smrg   return 0;
39632001f49Smrg}
397