From 1f75542012f665a5ee9659fa78574977266b900d Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 12 Apr 2010 02:26:42 +0200 Subject: grub-bin: set same section as grub --- package/grub-bin/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'package') diff --git a/package/grub-bin/Makefile b/package/grub-bin/Makefile index f7ae5c08b..df8a0d9d3 100644 --- a/package/grub-bin/Makefile +++ b/package/grub-bin/Makefile @@ -10,7 +10,7 @@ PKG_VERSION:= 1.97.1 PKG_RELEASE:= 1 PKG_MD5SUM:= 24961a39e63d8ec16d765aad3a301cda PKG_DESCR:= GRUB bootloader -PKG_SECTION:= sys +PKG_SECTION:= base PKG_SITES:= http://openadk.org/distfiles/ PKG_TARGET_DEPENDS:= x86 x86_64 -- cgit v1.2.3 From e1e56a0d326e753654a224e012d2d38142107cbc Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 12 Apr 2010 23:19:08 +0200 Subject: asterisk: default astdatadir to /usr/lib/asterisk This is needed in order for asterisk to find the sound files we provide (and I found adding a symlink from the sounds dir to /var/lib/asterisk/ being just too ugly). As it changes only the default configuration, I guess this is fine without increasing PKG_RELEASE. --- package/asterisk/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'package') diff --git a/package/asterisk/Makefile b/package/asterisk/Makefile index c35e686a5..c7ec0c0fa 100644 --- a/package/asterisk/Makefile +++ b/package/asterisk/Makefile @@ -174,6 +174,7 @@ do-install: ${SUB_INSTALLS-m} ${SUB_INSTALLS-y} rm -f gtalk.conf ; \ rm -f skinny.conf ; \ rm -f dundi.conf ; \ + echo -e '/^astdatadir =/s/var/usr/\nwq\n' | ed asterisk.conf ; \ ) ${INSTALL_DATA} ./files/modules.conf $(IDIR_ASTERISK)/etc/asterisk/ $(SED) 's|/var/lib/asterisk|/usr/lib/asterisk|g' \ -- cgit v1.2.3 From ed46beee877b0f659fa83049ecb0e50885a41257 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 12 Apr 2010 23:37:17 +0200 Subject: asterisk-sounds: do not install useless files Still leave that sounds.xml in there, as I'm not sure what it is for. And besides, with 5k of plain text size it shouldn't hurt too much if you already have space for the sounds package. :) --- package/asterisk/Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'package') diff --git a/package/asterisk/Makefile b/package/asterisk/Makefile index c7ec0c0fa..a6b3ef4a6 100644 --- a/package/asterisk/Makefile +++ b/package/asterisk/Makefile @@ -192,8 +192,11 @@ asterisk-sounds-install: ${INSTALL_DIR} $(IDIR_ASTERISK_SOUNDS)/usr/lib/asterisk/sounds $(CP) $(WRKBUILD)/sounds/* \ $(IDIR_ASTERISK_SOUNDS)/usr/lib/asterisk/sounds/ - rm -f $(IDIR_ASTERISK_SOUNDS)/usr/lib/asterisk/sounds/*.mp3 - rm -f $(IDIR_ASTERISK_SOUNDS)/usr/lib/asterisk/sounds/vm-* + (cd $(IDIR_ASTERISK_SOUNDS)/usr/lib/asterisk/sounds; \ + rm -f *.mp3 vm-*; \ + rm -f CHANGES* CREDITS* LICENSE* *.txt ; \ + rm -f *.tar.gz Makefile ; \ + ) asterisk-voicemail-install: ${INSTALL_DIR} $(IDIR_ASTERISK_VOICEMAIL)/etc/asterisk -- cgit v1.2.3 From 1d99bed8cd4a9c1fa942bbb094259ffd0ea6985b Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 6 Jun 2010 02:43:40 +0200 Subject: xinit: fix dependency, xinit needs xauth --- package/xinit/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'package') diff --git a/package/xinit/Makefile b/package/xinit/Makefile index a5180511a..9574024d9 100644 --- a/package/xinit/Makefile +++ b/package/xinit/Makefile @@ -9,7 +9,7 @@ PKG_RELEASE:= 1 PKG_MD5SUM:= 7ad82221ebd6600a8d33712ec3b62efb PKG_DESCR:= X Window System initializer PKG_SECTION:= x11 -PKG_DEPENDS:= xorg-server mcookie +PKG_DEPENDS:= xorg-server mcookie xauth PKG_BUILDDEP+= xorg-server PKG_URL:= http://xorg.freedesktop.org PKG_SITES:= http://xorg.freedesktop.org/archive/individual/app/ -- cgit v1.2.3 From 6753dd303c33fcd2e7ecf35e5d1c785c4726105b Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 20 Jun 2010 14:13:50 +0200 Subject: libXaw: fix PKG_template invocation For the sake of simplicity, we should stick to ${PKG_NAME} here, not the hard-coded lower-case variant of it. This way one has to stick to the original casing of the package name when specifying as dependency, but that's in fact more straight forward than always having to lookup the PKG_template invocation in question. --- package/libXaw/Makefile | 2 +- package/xorg-server/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'package') diff --git a/package/libXaw/Makefile b/package/libXaw/Makefile index 9b6481da8..16930e11d 100644 --- a/package/libXaw/Makefile +++ b/package/libXaw/Makefile @@ -14,7 +14,7 @@ PKG_SITES:= ${MASTER_SITE_XORG} include $(TOPDIR)/mk/package.mk -$(eval $(call PKG_template,LIBXAW,libxaw,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +$(eval $(call PKG_template,LIBXAW,${PKG_NAME},$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) CONFIGURE_ARGS+= --disable-docs diff --git a/package/xorg-server/Makefile b/package/xorg-server/Makefile index 5ec3e3aff..17ad6e8b9 100644 --- a/package/xorg-server/Makefile +++ b/package/xorg-server/Makefile @@ -10,7 +10,7 @@ PKG_MD5SUM:= ba0360b4ec1f6e541b264e45906bf5f2 PKG_DESCR:= Xorg server PKG_SECTION:= x11 PKG_DEPENDS:= libopenssl libxfont pixman libpciaccess libxkbfile \ - libfontenc xkeyboard-config xkbcomp libxau libxaw \ + libfontenc xkeyboard-config xkbcomp libxau libXaw \ libxmu libxpm libxrender libxt libxxf86dga libxext \ libxdmcp libxv libsm libice libx11 PKG_BUILDDEP+= libX11 randrproto renderproto fixesproto damageproto \ -- cgit v1.2.3 From df58b9c606edf2c33abb87595fd3c7d4b7ee1ee5 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 7 Jun 2010 18:22:20 +0200 Subject: port xterm --- package/Config.in | 1 + package/xterm/Makefile | 30 ++++++++++++++++++++++++++++++ package/xterm/patches/patch-Makefile_in | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 package/xterm/Makefile create mode 100644 package/xterm/patches/patch-Makefile_in (limited to 'package') diff --git a/package/Config.in b/package/Config.in index 2f7aecaa4..000403d56 100644 --- a/package/Config.in +++ b/package/Config.in @@ -633,6 +633,7 @@ source "package/twm/Config.in" source "package/xauth/Config.in" source "package/xinit/Config.in" source "package/xlsfonts/Config.in" +source "package/xterm/Config.in" endmenu menu "X fonts" diff --git a/package/xterm/Makefile b/package/xterm/Makefile new file mode 100644 index 000000000..720516586 --- /dev/null +++ b/package/xterm/Makefile @@ -0,0 +1,30 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= xterm +PKG_VERSION:= 259 +PKG_RELEASE:= 1 +PKG_MD5SUM:= 22037e1b794d749072310cb142800f05 +PKG_DESCR:= Terminal Emulator for X Windows +PKG_SECTION:= x11 +PKG_DEPENDS:= xorg-server libXaw +PKG_URL:= http://invisible-island.net/xterm/xterm.html +PKG_SITES:= ftp://invisible-island.net/xterm/ + +DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tgz + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,XTERM,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +post-install: + $(INSTALL_DIR) $(IDIR_XTERM)/usr/bin + $(INSTALL_BIN) $(WRKINST)/usr/bin/{koi8rxterm,resize,uxterm,xterm} \ + $(IDIR_XTERM)/usr/bin/ + $(INSTALL_DIR) $(IDIR_XTERM)/usr/lib/X11/app-defaults + $(INSTALL_DATA) ${WRKINST}/usr/lib/X11/app-defaults/{KOI8RXTerm,KOI8RXTerm-color,UXTerm,UXTerm-color,XTerm,XTerm-color} \ + ${IDIR_XTERM}/usr/lib/X11/app-defaults/ + +include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/xterm/patches/patch-Makefile_in b/package/xterm/patches/patch-Makefile_in new file mode 100644 index 000000000..1282767e2 --- /dev/null +++ b/package/xterm/patches/patch-Makefile_in @@ -0,0 +1,22 @@ + Fix shell compatibility problem. Note: this is rather hacky, as it + changes the actual semantics of the code - instead of evaluating the + shell statement when being used as parameter to a command, now the + $(shell) function is being used and therefore the result computed at + variable assignment stage. +--- xterm-259.orig/Makefile.in 2010-04-05 00:41:32.000000000 +0200 ++++ xterm-259/Makefile.in 2010-06-06 22:35:13.384934404 +0200 +@@ -175,10 +175,10 @@ resize$x : $(OBJS2) + + charproc$o : main.h @CHARPROC_DEPS@ + ################################################################################ +-actual_xterm = `echo xterm| sed '$(transform)'` +-actual_resize = `echo resize| sed '$(transform)'` +-actual_uxterm = `echo uxterm| sed '$(transform)'` +-actual_k8term = `echo koi8rxterm| sed '$(transform)'` ++actual_xterm = $(shell echo xterm| sed '$(transform)') ++actual_resize = $(shell echo resize| sed '$(transform)') ++actual_uxterm = $(shell echo uxterm| sed '$(transform)') ++actual_k8term = $(shell echo koi8rxterm| sed '$(transform)') + + binary_xterm = $(actual_xterm)$x + binary_resize = $(actual_resize)$x -- cgit v1.2.3 From 2d9d093cdedc57643f3ef2c1a6a5b20d96f7e080 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 15 Jun 2010 22:26:25 +0200 Subject: libXaw: fix wildcard ('?' must be non-empty) --- package/libXaw/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'package') diff --git a/package/libXaw/Makefile b/package/libXaw/Makefile index 16930e11d..8bf3fbb35 100644 --- a/package/libXaw/Makefile +++ b/package/libXaw/Makefile @@ -20,6 +20,6 @@ CONFIGURE_ARGS+= --disable-docs post-install: ${INSTALL_DIR} ${IDIR_LIBXAW}/usr/lib - ${CP} ${WRKINST}/usr/lib/libXaw?.so* ${IDIR_LIBXAW}/usr/lib/ + ${CP} ${WRKINST}/usr/lib/libXaw*.so* ${IDIR_LIBXAW}/usr/lib/ include ${TOPDIR}/mk/pkg-bottom.mk -- cgit v1.2.3 From 0549414af010737828696592acec9b263cd0513a Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sat, 12 Jun 2010 19:15:14 +0200 Subject: MesaLib: enable for lemote No render support for siliconmotion, so use swraster driver. Also the obligatory SAREA fix is needed here. --- package/MesaLib/Makefile | 19 +++++++++++++++++-- .../MesaLib/patches/patch-include_GL_internal_sarea_h | 12 ++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 package/MesaLib/patches/patch-include_GL_internal_sarea_h (limited to 'package') diff --git a/package/MesaLib/Makefile b/package/MesaLib/Makefile index 0a4ff3b9a..a5f624374 100644 --- a/package/MesaLib/Makefile +++ b/package/MesaLib/Makefile @@ -23,11 +23,22 @@ include $(TOPDIR)/mk/package.mk $(eval $(call PKG_template,MESALIB,mesalib,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +ifeq (${ADK_LINUX_X86_IBMX40},y) +DRI_DRIVERS:=i810 +endif + +# Lemote's SMI712 is not directly supported by Mesa, +# and at least some SIS driver fails to build when +# keeping the driver auto-selection intact. +ifeq (${ADK_LINUX_MIPS64_LEMOTE},y) +DRI_DRIVERS:=swrast +endif + CONFIGURE_ARGS+= --disable-static \ --disable-gallium \ --disable-glw \ --with-driver=dri \ - --with-dri-drivers=i810 \ + --with-dri-drivers=${DRI_DRIVERS} \ --without-demos XAKE_FLAGS+= APP_CC=${HOSTCC} HOST_CC=${HOSTCC} @@ -48,8 +59,12 @@ pre-configure: ${MAKE} -C ${WRKBUILD}/src/glsl clean post-install: - $(INSTALL_DIR) $(IDIR_MESALIB)/usr/lib + $(INSTALL_DIR) $(IDIR_MESALIB)/usr/lib/dri $(CP) $(WRKINST)/usr/lib/libGL*.so* \ $(IDIR_MESALIB)/usr/lib +ifeq (${ADK_LINUX_MIPS64_LEMOTE},y) + $(INSTALL_BIN) $(WRKINST)/usr/lib/dri/swrast_dri.so \ + ${IDIR_MESALIB}/usr/lib/dri/ +endif include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/MesaLib/patches/patch-include_GL_internal_sarea_h b/package/MesaLib/patches/patch-include_GL_internal_sarea_h new file mode 100644 index 000000000..7de643397 --- /dev/null +++ b/package/MesaLib/patches/patch-include_GL_internal_sarea_h @@ -0,0 +1,12 @@ + fix for loongson +--- Mesa-7.8.1.orig/include/GL/internal/sarea.h 2010-02-05 01:10:39.000000000 +0100 ++++ Mesa-7.8.1/include/GL/internal/sarea.h 2010-06-12 19:13:41.417809541 +0200 +@@ -42,6 +42,8 @@ + /* SAREA area needs to be at least a page */ + #if defined(__alpha__) + #define SAREA_MAX 0x2000 ++#elif defined(__mips__) ++#define SAREA_MAX 0x4000 + #elif defined(__ia64__) + #define SAREA_MAX 0x10000 /* 64kB */ + #else -- cgit v1.2.3 From 48ad3e135426d7f0116e4ad8efc85d20aad64910 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 15 Jun 2010 22:28:54 +0200 Subject: MesaLib: add glxinfo and glxgears subpackages As these xdemos reside in their own package but without the necessary infrastructure (this config thingy), I've created a patch from the addon-package. --- package/MesaLib/Makefile | 17 +- package/MesaLib/patches/000-mesalib-xdemos.patch | 14774 +++++++++++++++++++++ 2 files changed, 14789 insertions(+), 2 deletions(-) create mode 100644 package/MesaLib/patches/000-mesalib-xdemos.patch (limited to 'package') diff --git a/package/MesaLib/Makefile b/package/MesaLib/Makefile index a5f624374..5836f994f 100644 --- a/package/MesaLib/Makefile +++ b/package/MesaLib/Makefile @@ -15,6 +15,11 @@ PKG_BUILDDEP+= dri2proto glproto expat PKG_URL:= http://www.mesa3d.org/ PKG_SITES:= ftp://ftp.freedesktop.org/pub/mesa/7.8.1/ +PKG_DESCR_GLXINFO:= Display various GLX information +PKG_SECT_GLXINFO:= x11 +PKG_DESCR_GLXGEARS:= Nice little OpenGL demo application +PKG_SECT_GLXGEARS:= x11 + WRKDIST= ${WRKDIR}/Mesa-${PKG_VERSION} PKG_TARGET_DEPENDS:= ibmx40 lemote @@ -22,6 +27,8 @@ PKG_TARGET_DEPENDS:= ibmx40 lemote include $(TOPDIR)/mk/package.mk $(eval $(call PKG_template,MESALIB,mesalib,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +$(eval $(call PKG_template,GLXINFO,glxinfo,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR_GLXINFO},${PKG_SECT_GLXINFO})) +$(eval $(call PKG_template,GLXGEARS,glxgears,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR_GLXGEARS},${PKG_SECT_GLXGEARS})) ifeq (${ADK_LINUX_X86_IBMX40},y) DRI_DRIVERS:=i810 @@ -39,7 +46,7 @@ CONFIGURE_ARGS+= --disable-static \ --disable-glw \ --with-driver=dri \ --with-dri-drivers=${DRI_DRIVERS} \ - --without-demos + --with-demos=xdemos XAKE_FLAGS+= APP_CC=${HOSTCC} HOST_CC=${HOSTCC} @@ -50,7 +57,7 @@ pre-configure: --disable-glw \ --disable-gallium \ --with-driver=xlib \ - --without-demos \ + --with-demos=xdemos \ ); ${MAKE} -C ${WRKBUILD}/src/glsl ${MAKE} -C ${WRKBUILD}/src/glsl/apps @@ -66,5 +73,11 @@ ifeq (${ADK_LINUX_MIPS64_LEMOTE},y) $(INSTALL_BIN) $(WRKINST)/usr/lib/dri/swrast_dri.so \ ${IDIR_MESALIB}/usr/lib/dri/ endif + ${INSTALL_DIR} ${IDIR_GLXINFO}/usr/bin + ${INSTALL_BIN} ${WRKBUILD}/progs/xdemos/glxinfo \ + ${IDIR_GLXINFO}/usr/bin/ + ${INSTALL_DIR} ${IDIR_GLXGEARS}/usr/bin + ${INSTALL_BIN} ${WRKBUILD}/progs/xdemos/glxgears \ + ${IDIR_GLXGEARS}/usr/bin/ include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/MesaLib/patches/000-mesalib-xdemos.patch b/package/MesaLib/patches/000-mesalib-xdemos.patch new file mode 100644 index 000000000..866e68c2e --- /dev/null +++ b/package/MesaLib/patches/000-mesalib-xdemos.patch @@ -0,0 +1,14774 @@ +diff -Naurp Mesa-7.8.1/progs/xdemos/corender.c Mesa-7.8.1.patched/progs/xdemos/corender.c +--- Mesa-7.8.1/progs/xdemos/corender.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/corender.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,400 @@ ++/** ++ * Example of cooperative rendering into one window by two processes. ++ * The first instance of the program creates the GLX window. ++ * The second instance of the program gets the window ID from the first ++ * and draws into it. ++ * Socket IPC is used for synchronization. ++ * ++ * Usage: ++ * 1. run 'corender &' ++ * 2. run 'corender 2' (any arg will do) ++ * ++ * Brian Paul ++ * 11 Oct 2007 ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ipc.h" ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265358979323846 ++#endif ++ ++static int MyID = 0; /* 0 or 1 */ ++static int WindowID = 0; ++static GLXContext Context = 0; ++static int Width = 700, Height = 350; ++static int Rot = 0; ++static int Sock = 0; ++ ++static GLfloat Red[4] = {1.0, 0.2, 0.2, 1.0}; ++static GLfloat Blue[4] = {0.2, 0.2, 1.0, 1.0}; ++ ++static int Sync = 1; /** synchronized rendering? */ ++ ++ ++static void ++setup_ipc(void) ++{ ++ int k, port = 10001; ++ ++ if (MyID == 0) { ++ /* I'm the first one, wait for connection from second */ ++ k = CreatePort(&port); ++ assert(k != -1); ++ ++ printf("Waiting for connection from another 'corender'\n"); ++ Sock = AcceptConnection(k); ++ assert(Sock != -1); ++ ++ printf("Got connection, sending windowID\n"); ++ ++ /* send windowID */ ++ SendData(Sock, &WindowID, sizeof(WindowID)); ++ } ++ else { ++ /* I'm the second one, connect to first */ ++ char hostname[1000]; ++ ++ MyHostName(hostname, 1000); ++ Sock = Connect(hostname, port); ++ assert(Sock != -1); ++ ++ /* get windowID */ ++ ReceiveData(Sock, &WindowID, sizeof(WindowID)); ++ printf("Contacted first 'corender', getting WindowID\n"); ++ } ++} ++ ++ ++ ++/** from GLUT */ ++static void ++doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings) ++{ ++ int i, j; ++ GLfloat theta, phi, theta1; ++ GLfloat cosTheta, sinTheta; ++ GLfloat cosTheta1, sinTheta1; ++ GLfloat ringDelta, sideDelta; ++ ++ ringDelta = 2.0 * M_PI / rings; ++ sideDelta = 2.0 * M_PI / nsides; ++ ++ theta = 0.0; ++ cosTheta = 1.0; ++ sinTheta = 0.0; ++ for (i = rings - 1; i >= 0; i--) { ++ theta1 = theta + ringDelta; ++ cosTheta1 = cos(theta1); ++ sinTheta1 = sin(theta1); ++ glBegin(GL_QUAD_STRIP); ++ phi = 0.0; ++ for (j = nsides; j >= 0; j--) { ++ GLfloat cosPhi, sinPhi, dist; ++ ++ phi += sideDelta; ++ cosPhi = cos(phi); ++ sinPhi = sin(phi); ++ dist = R + r * cosPhi; ++ ++ glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); ++ glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi); ++ glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); ++ glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi); ++ } ++ glEnd(); ++ theta = theta1; ++ cosTheta = cosTheta1; ++ sinTheta = sinTheta1; ++ } ++} ++ ++ ++static void ++redraw(Display *dpy) ++{ ++ int dbg = 0; ++ ++ glXMakeCurrent(dpy, WindowID, Context); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ glClearColor(0.5, 0.5, 0.5, 0.0); ++ ++ if (MyID == 0) { ++ /* First process */ ++ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glTranslatef(-1, 0, 0); ++ glRotatef(Rot, 1, 0, 0); ++ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Red); ++ doughnut(0.5, 2.0, 20, 30); ++ glPopMatrix(); ++ ++ glFinish(); ++ if (!Sync) { ++ usleep(1000*10); ++ } ++ ++ /* signal second process to render */ ++ if (Sync) { ++ int code = 1; ++ if (dbg) printf("0: send signal\n"); ++ SendData(Sock, &code, sizeof(code)); ++ SendData(Sock, &Rot, sizeof(Rot)); ++ } ++ ++ /* wait for second process to finish rendering */ ++ if (Sync) { ++ int code = 0; ++ if (dbg) printf("0: wait signal\n"); ++ ReceiveData(Sock, &code, sizeof(code)); ++ if (dbg) printf("0: got signal\n"); ++ assert(code == 2); ++ } ++ ++ } ++ else { ++ /* Second process */ ++ ++ /* wait for first process's signal for me to render */ ++ if (Sync) { ++ int code = 0; ++ if (dbg) printf("1: wait signal\n"); ++ ReceiveData(Sock, &code, sizeof(code)); ++ ReceiveData(Sock, &Rot, sizeof(Rot)); ++ ++ if (dbg) printf("1: got signal\n"); ++ assert(code == 1); ++ } ++ ++ /* XXX this clear should not be here, but for some reason, it ++ * makes things _mostly_ work correctly w/ NVIDIA's driver. ++ * There's only occasional glitches. ++ * Without this glClear(), depth buffer for the second process ++ * is pretty much broken. ++ */ ++ /* glClear(GL_DEPTH_BUFFER_BIT); */ ++ ++ glPushMatrix(); ++ glTranslatef(1, 0, 0); ++ glRotatef(Rot + 90 , 1, 0, 0); ++ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Blue); ++ doughnut(0.5, 2.0, 20, 30); ++ glPopMatrix(); ++ glFinish(); ++ ++ glXSwapBuffers(dpy, WindowID); ++ usleep(1000*10); ++ ++ /* signal first process that I'm done rendering */ ++ if (Sync) { ++ int code = 2; ++ if (dbg) printf("1: send signal\n"); ++ SendData(Sock, &code, sizeof(code)); ++ } ++ } ++} ++ ++ ++static void ++resize(Display *dpy, int width, int height) ++{ ++ float ar = (float) width / height; ++ ++ glXMakeCurrent(dpy, WindowID, Context); ++ ++ glViewport(0, 0, width, height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-ar, ar, 1.0, -1.0, 5.0, 200.0); ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0, 0, -15); ++ ++ Width = width; ++ Height = height; ++} ++ ++ ++ ++static void ++set_window_title(Display *dpy, Window win, const char *title) ++{ ++ XSizeHints sizehints; ++ sizehints.flags = 0; ++ XSetStandardProperties(dpy, win, title, title, ++ None, (char **)NULL, 0, &sizehints); ++} ++ ++ ++static Window ++make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height) ++{ ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ int x = 0, y = 0; ++ char *name = NULL; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ /* 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, x, y, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ return win; ++} ++ ++ ++static void ++set_event_mask(Display *dpy, Window win) ++{ ++ XSetWindowAttributes attr; ++ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ XChangeWindowAttributes(dpy, win, CWEventMask, &attr); ++} ++ ++ ++static void ++event_loop(Display *dpy) ++{ ++ while (1) { ++ while (XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ ++ switch (event.type) { ++ case Expose: ++ redraw(dpy); ++ break; ++ case ConfigureNotify: ++ resize(dpy, event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ if (code == XK_Left) { ++ } ++ else { ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ exit(0); ++ } ++ } ++ } ++ default: ++ /* nothing */ ++ ; ++ } ++ } ++ ++ if (MyID == 0 || !Sync) ++ Rot += 1; ++ redraw(dpy); ++ } ++} ++ ++ ++static XVisualInfo * ++choose_visual(Display *dpy) ++{ ++ int attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int scrnum = DefaultScreen( dpy ); ++ return glXChooseVisual(dpy, scrnum, attribs); ++} ++ ++ ++static void ++parse_opts(int argc, char *argv[]) ++{ ++ if (argc > 1) { ++ MyID = 1; ++ } ++} ++ ++ ++int ++main( int argc, char *argv[] ) ++{ ++ Display *dpy; ++ XVisualInfo *visinfo; ++ ++ parse_opts(argc, argv); ++ ++ dpy = XOpenDisplay(NULL); ++ ++ visinfo = choose_visual(dpy); ++ ++ Context = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!Context) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ if (MyID == 0) { ++ WindowID = make_gl_window(dpy, visinfo, Width, Height); ++ set_window_title(dpy, WindowID, "corender"); ++ XMapWindow(dpy, WindowID); ++ /*printf("WindowID 0x%x\n", (int) WindowID);*/ ++ } ++ ++ /* do ipc hand-shake here */ ++ setup_ipc(); ++ assert(Sock); ++ assert(WindowID); ++ ++ if (MyID == 1) { ++ set_event_mask(dpy, WindowID); ++ } ++ ++ resize(dpy, Width, Height); ++ ++ event_loop(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glsync.c Mesa-7.8.1.patched/progs/xdemos/glsync.c +--- Mesa-7.8.1/progs/xdemos/glsync.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glsync.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,295 @@ ++/* ++ * Copyright © 2007 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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 ++ * THE AUTHORS OR COPYRIGHT HOLDERS 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. ++ * ++ * Authors: ++ * Jesse Barnes ++ * ++ */ ++ ++/** @file glsync.c ++ * The program is simple: it paints a window alternating colors (red & ++ * white) either as fast as possible or synchronized to vblank events ++ * ++ * If run normally, the program should display a window that exhibits ++ * significant tearing between red and white colors (e.g. you might get ++ * a "waterfall" effect of red and white horizontal bars). ++ * ++ * If run with the '-s b' option, the program should synchronize the ++ * window color changes with the vertical blank period, resulting in a ++ * window that looks orangish with a high frequency flicker (which may ++ * be invisible). If the window is moved to another screen, this ++ * property should be preserved. If the window spans two screens, it ++ * shouldn't tear on whichever screen most of the window is on; the ++ * portion on the other screen may show some tearing (like the ++ * waterfall effect above). ++ * ++ * Other options include '-w ' and '-h ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++void (*video_sync_get)(); ++void (*video_sync)(); ++void (*swap_interval)(); ++ ++static int GLXExtensionSupported(Display *dpy, const char *extension) ++{ ++ const char *extensionsString, *pos; ++ ++ extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); ++ ++ pos = strstr(extensionsString, extension); ++ ++ if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && ++ (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) ++ return 1; ++ ++ return 0; ++} ++ ++extern char *optarg; ++extern int optind, opterr, optopt; ++static char optstr[] = "w:h:s:vi:"; ++ ++enum sync_type { ++ none = 0, ++ sgi_video_sync, ++ buffer_swap ++}; ++ ++static void usage(char *name) ++{ ++ printf("usage: %s [-w ] [-h ] [-s] " ++ "[-v]\n", name); ++ printf("\t-s:\n"); ++ printf("\t\tn: none\n"); ++ printf("\t\ts: SGI video sync extension\n"); ++ printf("\t\tb: buffer swap\n"); ++ printf("\t-i\n"); ++ printf("\t-v: verbose (print count)\n"); ++ exit(-1); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ Display *disp; ++ XVisualInfo *pvi; ++ XSetWindowAttributes swa; ++ GLint last_val = -1, count = 0; ++ Window winGL; ++ GLXContext context; ++ int dummy; ++ Atom wmDelete; ++ enum sync_type waitforsync = none; ++ int width = 500, height = 500, verbose = 0, interval = 1; ++ int c, i = 1; ++ int ret; ++ int attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ None }; ++ int db_attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ XSizeHints sizehints; ++ ++ opterr = 0; ++ while ((c = getopt(argc, argv, optstr)) != -1) { ++ switch (c) { ++ case 'w': ++ width = atoi(optarg); ++ break; ++ case 'h': ++ height = atoi(optarg); ++ break; ++ case 's': ++ switch (optarg[0]) { ++ case 'n': ++ waitforsync = none; ++ break; ++ case 's': ++ waitforsync = sgi_video_sync; ++ break; ++ case 'b': ++ waitforsync = buffer_swap; ++ break; ++ default: ++ usage(argv[0]); ++ break; ++ } ++ break; ++ case 'v': ++ verbose = 1; ++ break; ++ case 'i': ++ interval = atoi(optarg); ++ break; ++ default: ++ usage(argv[0]); ++ break; ++ } ++ } ++ ++ disp = XOpenDisplay(NULL); ++ if (!disp) { ++ fprintf(stderr, "failed to open display\n"); ++ return -1; ++ } ++ ++ if (!glXQueryExtension(disp, &dummy, &dummy)) { ++ fprintf(stderr, "glXQueryExtension failed\n"); ++ return -1; ++ } ++ ++ if (!GLXExtensionSupported(disp, "GLX_SGI_video_sync")) { ++ fprintf(stderr, "GLX_SGI_video_sync not supported, exiting\n"); ++ return -1; ++ } ++ ++ if (waitforsync != buffer_swap) { ++ pvi = glXChooseVisual(disp, DefaultScreen(disp), attribs); ++ } else { ++ pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs); ++ } ++ ++ if (!pvi) { ++ fprintf(stderr, "failed to choose visual, exiting\n"); ++ return -1; ++ } ++ ++ pvi->screen = DefaultScreen(disp); ++ ++ swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen), ++ pvi->visual, AllocNone); ++ swa.border_pixel = 0; ++ swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | ++ StructureNotifyMask; ++ winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen), ++ 0, 0, ++ width, height, ++ 0, pvi->depth, InputOutput, pvi->visual, ++ CWBorderPixel | CWColormap | CWEventMask, &swa); ++ if (!winGL) { ++ fprintf(stderr, "window creation failed\n"); ++ return -1; ++ } ++ wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); ++ XSetWMProtocols(disp, winGL, &wmDelete, 1); ++ ++ sizehints.x = 0; ++ sizehints.y = 0; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ ++ XSetNormalHints(disp, winGL, &sizehints); ++ XSetStandardProperties(disp, winGL, "glsync test", "glsync text", ++ None, NULL, 0, &sizehints); ++ ++ context = glXCreateContext(disp, pvi, NULL, GL_TRUE); ++ if (!context) { ++ fprintf(stderr, "failed to create glx context\n"); ++ return -1; ++ } ++ ++ XMapWindow(disp, winGL); ++ ret = glXMakeCurrent(disp, winGL, context); ++ if (!ret) { ++ fprintf(stderr, "failed to make context current: %d\n", ret); ++ } ++ ++ video_sync_get = glXGetProcAddress((unsigned char *)"glXGetVideoSyncSGI"); ++ video_sync = glXGetProcAddress((unsigned char *)"glXWaitVideoSyncSGI"); ++ ++ swap_interval = glXGetProcAddress((unsigned char *)"glXSwapIntervalSGI"); ++ ++ if (!video_sync_get || !video_sync || !swap_interval) { ++ fprintf(stderr, "failed to get sync functions\n"); ++ return -1; ++ } ++ ++ if (waitforsync == buffer_swap) { ++ swap_interval(interval); ++ fprintf(stderr, "set swap interval to %d\n", interval); ++ } ++ video_sync_get(&count); ++ count++; ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ while (i++) { ++ /* Alternate colors to make tearing obvious */ ++ if (i & 1) { ++ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); ++ glColor3f(1.0f, 1.0f, 1.0f); ++ } else { ++ glClearColor(1.0f, 0.0f, 0.0f, 0.0f); ++ glColor3f(1.0f, 0.0f, 0.0f); ++ } ++ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ glRectf(0, 0, width, height); ++ ++ /* Wait for vsync */ ++ if (waitforsync == sgi_video_sync) { ++ if (verbose) ++ fprintf(stderr, "waiting on count %d\n", count); ++ video_sync(2, (count + 1) % 2, &count); ++ if (count < last_val) ++ fprintf(stderr, "error: vblank count went backwards: %d -> %d\n", last_val, count); ++ if (count == last_val) ++ fprintf(stderr, "error: count didn't change: %d\n", count); ++ last_val = count; ++ glFlush(); ++ } else if (waitforsync == buffer_swap) { ++ glXSwapBuffers(disp, winGL); ++ } else { ++ video_sync_get(&count); ++ sleep(1); ++ glFinish(); ++ } ++ ++ if (verbose) { ++ video_sync_get(&count); ++ fprintf(stderr, "current count: %d\n", count); ++ } ++ } ++ ++ XDestroyWindow(disp, winGL); ++ glXDestroyContext(disp, context); ++ XCloseDisplay(disp); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glthreads.c Mesa-7.8.1.patched/progs/xdemos/glthreads.c +--- Mesa-7.8.1/progs/xdemos/glthreads.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glthreads.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,716 @@ ++/* ++ * Copyright (C) 2000 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. ++ */ ++ ++ ++/* ++ * This program tests GLX thread safety. ++ * Command line options: ++ * -p Open a display connection for each thread ++ * -l Enable application-side locking ++ * -n Number of threads to create (default is 2) ++ * -display Specify X display (default is $DISPLAY) ++ * -t Use texture mapping ++ * ++ * Brian Paul 20 July 2000 ++ */ ++ ++ ++/* ++ * Notes: ++ * - Each thread gets its own GLX context. ++ * ++ * - The GLX contexts share texture objects. ++ * ++ * - When 't' is pressed to update the texture image, the window/thread which ++ * has input focus is signalled to change the texture. The other threads ++ * should see the updated texture the next time they call glBindTexture. ++ */ ++ ++ ++#if defined(PTHREADS) /* defined by Mesa on Linux and other platforms */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* ++ * Each window/thread/context: ++ */ ++struct winthread { ++ Display *Dpy; ++ int Index; ++ pthread_t Thread; ++ Window Win; ++ GLXContext Context; ++ float Angle; ++ int WinWidth, WinHeight; ++ GLboolean NewSize; ++ GLboolean Initialized; ++ GLboolean MakeNewTexture; ++}; ++ ++ ++#define MAX_WINTHREADS 100 ++static struct winthread WinThreads[MAX_WINTHREADS]; ++static int NumWinThreads = 0; ++static volatile GLboolean ExitFlag = GL_FALSE; ++ ++static GLboolean MultiDisplays = 0; ++static GLboolean Locking = 0; ++static GLboolean Texture = GL_FALSE; ++static GLuint TexObj = 12; ++static GLboolean Animate = GL_TRUE; ++ ++static pthread_mutex_t Mutex; ++static pthread_cond_t CondVar; ++static pthread_mutex_t CondMutex; ++ ++ ++static void ++Error(const char *msg) ++{ ++ fprintf(stderr, "Error: %s\n", msg); ++ exit(1); ++} ++ ++ ++static void ++signal_redraw(void) ++{ ++ pthread_mutex_lock(&CondMutex); ++ pthread_cond_broadcast(&CondVar); ++ pthread_mutex_unlock(&CondMutex); ++} ++ ++ ++static void ++MakeNewTexture(struct winthread *wt) ++{ ++#define TEX_SIZE 128 ++ static float step = 0.0; ++ GLfloat image[TEX_SIZE][TEX_SIZE][4]; ++ GLint width; ++ int i, j; ++ ++ for (j = 0; j < TEX_SIZE; j++) { ++ for (i = 0; i < TEX_SIZE; i++) { ++ float dt = 5.0 * (j - 0.5 * TEX_SIZE) / TEX_SIZE; ++ float ds = 5.0 * (i - 0.5 * TEX_SIZE) / TEX_SIZE; ++ float r = dt * dt + ds * ds + step; ++ image[j][i][0] = ++ image[j][i][1] = ++ image[j][i][2] = 0.75 + 0.25 * cos(r); ++ image[j][i][3] = 1.0; ++ } ++ } ++ ++ step += 0.5; ++ ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ ++ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width); ++ if (width) { ++ assert(width == TEX_SIZE); ++ /* sub-tex replace */ ++ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, TEX_SIZE, TEX_SIZE, ++ GL_RGBA, GL_FLOAT, image); ++ } ++ else { ++ /* create new */ ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, ++ GL_RGBA, GL_FLOAT, image); ++ } ++} ++ ++ ++ ++/* draw a colored cube */ ++static void ++draw_object(void) ++{ ++ glPushMatrix(); ++ glScalef(0.75, 0.75, 0.75); ++ ++ glColor3f(1, 0, 0); ++ ++ if (Texture) { ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ glEnable(GL_TEXTURE_2D); ++ } ++ else { ++ glDisable(GL_TEXTURE_2D); ++ } ++ ++ glBegin(GL_QUADS); ++ ++ /* -X */ ++ glColor3f(0, 1, 1); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); ++ glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); ++ ++ /* +X */ ++ glColor3f(1, 0, 0); ++ glTexCoord2f(0, 0); glVertex3f(1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f(1, 1, -1); ++ glTexCoord2f(1, 1); glVertex3f(1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(1, -1, 1); ++ ++ /* -Y */ ++ glColor3f(1, 0, 1); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); ++ glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); ++ ++ /* +Y */ ++ glColor3f(0, 1, 0); ++ glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); ++ glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); ++ glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); ++ ++ /* -Z */ ++ glColor3f(1, 1, 0); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); ++ glTexCoord2f(1, 1); glVertex3f( 1, 1, -1); ++ glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); ++ ++ /* +Y */ ++ glColor3f(0, 0, 1); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); ++ glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); ++ glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); ++ ++ glEnd(); ++ ++ glPopMatrix(); ++} ++ ++ ++/* signal resize of given window */ ++static void ++resize(struct winthread *wt, int w, int h) ++{ ++ wt->NewSize = GL_TRUE; ++ wt->WinWidth = w; ++ wt->WinHeight = h; ++ if (!Animate) ++ signal_redraw(); ++} ++ ++ ++/* ++ * We have an instance of this for each thread. ++ */ ++static void ++draw_loop(struct winthread *wt) ++{ ++ while (!ExitFlag) { ++ ++ if (Locking) ++ pthread_mutex_lock(&Mutex); ++ ++ glXMakeCurrent(wt->Dpy, wt->Win, wt->Context); ++ if (!wt->Initialized) { ++ printf("glthreads: %d: GL_RENDERER = %s\n", wt->Index, ++ (char *) glGetString(GL_RENDERER)); ++ if (Texture /*&& wt->Index == 0*/) { ++ MakeNewTexture(wt); ++ } ++ wt->Initialized = GL_TRUE; ++ } ++ ++ if (Locking) ++ pthread_mutex_unlock(&Mutex); ++ ++ glEnable(GL_DEPTH_TEST); ++ ++ if (wt->NewSize) { ++ GLfloat w = (float) wt->WinWidth / (float) wt->WinHeight; ++ glViewport(0, 0, wt->WinWidth, wt->WinHeight); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-w, w, -1.0, 1.0, 1.5, 10); ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0, 0, -2.5); ++ wt->NewSize = GL_FALSE; ++ } ++ ++ if (wt->MakeNewTexture) { ++ MakeNewTexture(wt); ++ wt->MakeNewTexture = GL_FALSE; ++ } ++ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(wt->Angle, 0, 1, 0); ++ glRotatef(wt->Angle, 1, 0, 0); ++ glScalef(0.7, 0.7, 0.7); ++ draw_object(); ++ glPopMatrix(); ++ ++ if (Locking) ++ pthread_mutex_lock(&Mutex); ++ ++ glXSwapBuffers(wt->Dpy, wt->Win); ++ ++ if (Locking) ++ pthread_mutex_unlock(&Mutex); ++ ++ if (Animate) { ++ usleep(5000); ++ } ++ else { ++ /* wait for signal to draw */ ++ pthread_mutex_lock(&CondMutex); ++ pthread_cond_wait(&CondVar, &CondMutex); ++ pthread_mutex_unlock(&CondMutex); ++ } ++ wt->Angle += 1.0; ++ } ++} ++ ++ ++static void ++keypress(XEvent *event, struct winthread *wt) ++{ ++ char buf[100]; ++ KeySym keySym; ++ XComposeStatus stat; ++ ++ XLookupString(&event->xkey, buf, sizeof(buf), &keySym, &stat); ++ ++ switch (keySym) { ++ case XK_Escape: ++ /* tell all threads to exit */ ++ if (!Animate) { ++ signal_redraw(); ++ } ++ ExitFlag = GL_TRUE; ++ /*printf("exit draw_loop %d\n", wt->Index);*/ ++ return; ++ case XK_t: ++ case XK_T: ++ if (Texture) { ++ wt->MakeNewTexture = GL_TRUE; ++ if (!Animate) ++ signal_redraw(); ++ } ++ break; ++ case XK_a: ++ case XK_A: ++ Animate = !Animate; ++ if (Animate) /* yes, prev Animate state! */ ++ signal_redraw(); ++ break; ++ case XK_s: ++ case XK_S: ++ if (!Animate) ++ signal_redraw(); ++ break; ++ default: ++ ; /* nop */ ++ } ++} ++ ++ ++/* ++ * The main process thread runs this loop. ++ * Single display connection for all threads. ++ */ ++static void ++event_loop(Display *dpy) ++{ ++ XEvent event; ++ int i; ++ ++ assert(!MultiDisplays); ++ ++ while (!ExitFlag) { ++ ++ if (Locking) { ++ while (1) { ++ int k; ++ pthread_mutex_lock(&Mutex); ++ k = XPending(dpy); ++ if (k) { ++ XNextEvent(dpy, &event); ++ pthread_mutex_unlock(&Mutex); ++ break; ++ } ++ pthread_mutex_unlock(&Mutex); ++ usleep(5000); ++ } ++ } ++ else { ++ XNextEvent(dpy, &event); ++ } ++ ++ switch (event.type) { ++ case ConfigureNotify: ++ /* Find winthread for this event's window */ ++ for (i = 0; i < NumWinThreads; i++) { ++ struct winthread *wt = &WinThreads[i]; ++ if (event.xconfigure.window == wt->Win) { ++ resize(wt, event.xconfigure.width, ++ event.xconfigure.height); ++ break; ++ } ++ } ++ break; ++ case KeyPress: ++ for (i = 0; i < NumWinThreads; i++) { ++ struct winthread *wt = &WinThreads[i]; ++ if (event.xkey.window == wt->Win) { ++ keypress(&event, wt); ++ break; ++ } ++ } ++ break; ++ default: ++ /*no-op*/ ; ++ } ++ } ++} ++ ++ ++/* ++ * Separate display connection for each thread. ++ */ ++static void ++event_loop_multi(void) ++{ ++ XEvent event; ++ int w = 0; ++ ++ assert(MultiDisplays); ++ ++ while (!ExitFlag) { ++ struct winthread *wt = &WinThreads[w]; ++ if (XPending(wt->Dpy)) { ++ XNextEvent(wt->Dpy, &event); ++ switch (event.type) { ++ case ConfigureNotify: ++ resize(wt, event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ keypress(&event, wt); ++ break; ++ default: ++ ; /* nop */ ++ } ++ } ++ w = (w + 1) % NumWinThreads; ++ usleep(5000); ++ } ++} ++ ++ ++ ++/* ++ * we'll call this once for each thread, before the threads are created. ++ */ ++static void ++create_window(struct winthread *wt, GLXContext shareCtx) ++{ ++ Window win; ++ GLXContext ctx; ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DEPTH_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ XVisualInfo *visinfo; ++ int width = 160, height = 160; ++ int xpos = (wt->Index % 8) * (width + 10); ++ int ypos = (wt->Index / 8) * (width + 20); ++ ++ scrnum = DefaultScreen(wt->Dpy); ++ root = RootWindow(wt->Dpy, scrnum); ++ ++ visinfo = glXChooseVisual(wt->Dpy, scrnum, attrib); ++ if (!visinfo) { ++ Error("Unable to find RGB, Z, double-buffered visual"); ++ } ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap(wt->Dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ++ ++ win = XCreateWindow(wt->Dpy, root, xpos, ypos, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr); ++ if (!win) { ++ Error("Couldn't create window"); ++ } ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(wt->Dpy, win, &sizehints); ++ XSetStandardProperties(wt->Dpy, win, "glthreads", "glthreads", ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ++ ctx = glXCreateContext(wt->Dpy, visinfo, shareCtx, True); ++ if (!ctx) { ++ Error("Couldn't create GLX context"); ++ } ++ ++ XMapWindow(wt->Dpy, win); ++ XSync(wt->Dpy, 0); ++ ++ /* save the info for this window/context */ ++ wt->Win = win; ++ wt->Context = ctx; ++ wt->Angle = 0.0; ++ wt->WinWidth = width; ++ wt->WinHeight = height; ++ wt->NewSize = GL_TRUE; ++} ++ ++ ++/* ++ * Called by pthread_create() ++ */ ++static void * ++thread_function(void *p) ++{ ++ struct winthread *wt = (struct winthread *) p; ++ draw_loop(wt); ++ return NULL; ++} ++ ++ ++/* ++ * called before exit to wait for all threads to finish ++ */ ++static void ++clean_up(void) ++{ ++ int i; ++ ++ /* wait for threads to finish */ ++ for (i = 0; i < NumWinThreads; i++) { ++ pthread_join(WinThreads[i].Thread, NULL); ++ } ++ ++ for (i = 0; i < NumWinThreads; i++) { ++ glXDestroyContext(WinThreads[i].Dpy, WinThreads[i].Context); ++ XDestroyWindow(WinThreads[i].Dpy, WinThreads[i].Win); ++ } ++} ++ ++ ++static void ++usage(void) ++{ ++ printf("glthreads: test of GL thread safety (any key = exit)\n"); ++ printf("Usage:\n"); ++ printf(" glthreads [options]\n"); ++ printf("Options:\n"); ++ printf(" -display DISPLAYNAME Specify display string\n"); ++ printf(" -n NUMTHREADS Number of threads to create\n"); ++ printf(" -p Use a separate display connection for each thread\n"); ++ printf(" -l Use application-side locking\n"); ++ printf(" -t Enable texturing\n"); ++ printf("Keyboard:\n"); ++ printf(" Esc Exit\n"); ++ printf(" t Change texture image (requires -t option)\n"); ++ printf(" a Toggle animation\n"); ++ printf(" s Step rotation (when not animating)\n"); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ char *displayName = NULL; ++ int numThreads = 2; ++ Display *dpy = NULL; ++ int i; ++ Status threadStat; ++ ++ if (argc == 1) { ++ usage(); ++ } ++ else { ++ int i; ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) { ++ displayName = argv[i + 1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-p") == 0) { ++ MultiDisplays = 1; ++ } ++ else if (strcmp(argv[i], "-l") == 0) { ++ Locking = 1; ++ } ++ else if (strcmp(argv[i], "-t") == 0) { ++ Texture = 1; ++ } ++ else if (strcmp(argv[i], "-n") == 0 && i + 1 < argc) { ++ numThreads = atoi(argv[i + 1]); ++ if (numThreads < 1) ++ numThreads = 1; ++ else if (numThreads > MAX_WINTHREADS) ++ numThreads = MAX_WINTHREADS; ++ i++; ++ } ++ else { ++ usage(); ++ exit(1); ++ } ++ } ++ } ++ ++ if (Locking) ++ printf("glthreads: Using explicit locks around Xlib calls.\n"); ++ else ++ printf("glthreads: No explict locking.\n"); ++ ++ if (MultiDisplays) ++ printf("glthreads: Per-thread display connections.\n"); ++ else ++ printf("glthreads: Single display connection.\n"); ++ ++ /* ++ * VERY IMPORTANT: call XInitThreads() before any other Xlib functions. ++ */ ++ if (!MultiDisplays) { ++ if (!Locking) { ++ threadStat = XInitThreads(); ++ if (threadStat) { ++ printf("XInitThreads() returned %d (success)\n", (int) threadStat); ++ } ++ else { ++ printf("XInitThreads() returned 0 (failure- this program may fail)\n"); ++ } ++ } ++ ++ dpy = XOpenDisplay(displayName); ++ if (!dpy) { ++ fprintf(stderr, "Unable to open display %s\n", XDisplayName(displayName)); ++ return -1; ++ } ++ } ++ ++ pthread_mutex_init(&Mutex, NULL); ++ pthread_mutex_init(&CondMutex, NULL); ++ pthread_cond_init(&CondVar, NULL); ++ ++ printf("glthreads: creating windows\n"); ++ ++ NumWinThreads = numThreads; ++ ++ /* Create the GLX windows and contexts */ ++ for (i = 0; i < numThreads; i++) { ++ GLXContext share; ++ ++ if (MultiDisplays) { ++ WinThreads[i].Dpy = XOpenDisplay(displayName); ++ assert(WinThreads[i].Dpy); ++ } ++ else { ++ WinThreads[i].Dpy = dpy; ++ } ++ WinThreads[i].Index = i; ++ WinThreads[i].Initialized = GL_FALSE; ++ ++ share = (Texture && i > 0) ? WinThreads[0].Context : 0; ++ ++ create_window(&WinThreads[i], share); ++ } ++ ++ printf("glthreads: creating threads\n"); ++ ++ /* Create the threads */ ++ for (i = 0; i < numThreads; i++) { ++ pthread_create(&WinThreads[i].Thread, NULL, thread_function, ++ (void*) &WinThreads[i]); ++ printf("glthreads: Created thread %p\n", (void *) WinThreads[i].Thread); ++ } ++ ++ if (MultiDisplays) ++ event_loop_multi(); ++ else ++ event_loop(dpy); ++ ++ clean_up(); ++ ++ if (MultiDisplays) { ++ for (i = 0; i < numThreads; i++) { ++ XCloseDisplay(WinThreads[i].Dpy); ++ } ++ } ++ else { ++ XCloseDisplay(dpy); ++ } ++ ++ return 0; ++} ++ ++ ++#else /* PTHREADS */ ++ ++ ++#include ++ ++int ++main(int argc, char *argv[]) ++{ ++ printf("Sorry, this program wasn't compiled with PTHREADS defined.\n"); ++ return 0; ++} ++ ++ ++#endif /* PTHREADS */ +diff -Naurp Mesa-7.8.1/progs/xdemos/glxcontexts.c Mesa-7.8.1.patched/progs/xdemos/glxcontexts.c +--- Mesa-7.8.1/progs/xdemos/glxcontexts.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxcontexts.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,548 @@ ++/* ++ * Copyright (C) 1999-2001 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. ++ */ ++ ++/* ++ * Version of glxgears that creates/destroys the rendering context for each ++ * frame. Also periodically destroy/recreate the window. ++ * Good for finding memory leaks, etc. ++ * ++ * Command line options: ++ * -info print GL implementation information ++ * ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define BENCHMARK ++ ++#ifdef BENCHMARK ++ ++/* XXX this probably isn't very portable */ ++ ++#include ++#include ++ ++/* return current time (in seconds) */ ++static double ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (double) tv.tv_sec + tv.tv_usec / 1000000.0; ++} ++ ++#else /*BENCHMARK*/ ++ ++/* dummy */ ++static double ++current_time(void) ++{ ++ /* update this function for other platforms! */ ++ static double t = 0.0; ++ static int warn = 1; ++ if (warn) { ++ fprintf(stderr, "Warning: current_time() not implemented!!\n"); ++ warn = 0; ++ } ++ return t += 1.0; ++} ++ ++#endif /*BENCHMARK*/ ++ ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265 ++#endif ++ ++ ++static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; ++static GLint gear1, gear2, gear3; ++static GLfloat angle = 0.0; ++ ++static XVisualInfo *visinfo = NULL; ++static int WinWidth = 300, WinHeight = 300; ++ ++ ++/* ++ * ++ * Draw a gear wheel. You'll probably want to call this function when ++ * building a display list since we do a lot of trig here. ++ * ++ * Input: inner_radius - radius of hole at center ++ * outer_radius - radius at center of teeth ++ * width - width of gear ++ * teeth - number of teeth ++ * tooth_depth - depth of tooth ++ */ ++static void ++gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, ++ GLint teeth, GLfloat tooth_depth) ++{ ++ GLint i; ++ GLfloat r0, r1, r2; ++ GLfloat angle, da; ++ GLfloat u, v, len; ++ ++ r0 = inner_radius; ++ r1 = outer_radius - tooth_depth / 2.0; ++ r2 = outer_radius + tooth_depth / 2.0; ++ ++ da = 2.0 * M_PI / teeth / 4.0; ++ ++ glShadeModel(GL_FLAT); ++ ++ glNormal3f(0.0, 0.0, 1.0); ++ ++ /* draw front face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw front sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ glEnd(); ++ ++ glNormal3f(0.0, 0.0, -1.0); ++ ++ /* draw back face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw back sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ } ++ glEnd(); ++ ++ /* draw outward faces of teeth */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ u = r2 * cos(angle + da) - r1 * cos(angle); ++ v = r2 * sin(angle + da) - r1 * sin(angle); ++ len = sqrt(u * u + v * v); ++ u /= len; ++ v /= len; ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); ++ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ } ++ ++ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); ++ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); ++ ++ glEnd(); ++ ++ glShadeModel(GL_SMOOTH); ++ ++ /* draw inside radius cylinder */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glNormal3f(-cos(angle), -sin(angle), 0.0); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ } ++ glEnd(); ++} ++ ++ ++static void ++do_draw(void) ++{ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(view_rotx, 1.0, 0.0, 0.0); ++ glRotatef(view_roty, 0.0, 1.0, 0.0); ++ glRotatef(view_rotz, 0.0, 0.0, 1.0); ++ ++ glPushMatrix(); ++ glTranslatef(-3.0, -2.0, 0.0); ++ glRotatef(angle, 0.0, 0.0, 1.0); ++ glCallList(gear1); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(3.1, -2.0, 0.0); ++ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); ++ glCallList(gear2); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(-3.1, 4.2, 0.0); ++ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); ++ glCallList(gear3); ++ glPopMatrix(); ++ ++ glPopMatrix(); ++} ++ ++ ++/* new window size or exposure */ ++static void ++reshape(int width, int height) ++{ ++ glViewport(0, 0, (GLint) width, (GLint) height); ++ ++ { ++ GLfloat h = (GLfloat) height / (GLfloat) width; ++ ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); ++ } ++ ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -40.0); ++} ++ ++ ++static void ++init(void) ++{ ++ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; ++ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; ++ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; ++ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_CULL_FACE); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ /* make the gears */ ++ gear1 = glGenLists(1); ++ glNewList(gear1, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); ++ gear(1.0, 4.0, 1.0, 20, 0.7); ++ glEndList(); ++ ++ gear2 = glGenLists(1); ++ glNewList(gear2, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); ++ gear(0.5, 2.0, 2.0, 10, 0.7); ++ glEndList(); ++ ++ gear3 = glGenLists(1); ++ glNewList(gear3, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); ++ gear(1.3, 2.0, 0.5, 10, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++} ++ ++ ++static void ++draw( Display *dpy, Window win ) ++{ ++ GLXContext ctx; ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ glXMakeCurrent(dpy, win, ctx); ++ ++ init(); ++ ++ reshape(WinWidth, WinHeight); ++ ++ do_draw(); ++ ++ glDeleteLists(gear1, 1); ++ glDeleteLists(gear2, 1); ++ glDeleteLists(gear3, 1); ++ ++ glXSwapBuffers(dpy, win); ++ glXDestroyContext(dpy, ctx); ++} ++ ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( Display *dpy, const char *name, ++ int x, int y, int width, int height, ++ Window *winRet) ++{ ++ int attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ if (visinfo) ++ XFree(visinfo); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attribs ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ attr.override_redirect = 0; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; ++ ++ win = XCreateWindow( dpy, root, x, y, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ *winRet = win; ++} ++ ++ ++static void ++event_loop(Display *dpy) ++{ ++ Window win; ++ make_window(dpy, "glxgears", 0, 0, WinWidth, WinHeight, &win); ++ XMapWindow(dpy, win); ++ ++ while (1) { ++ while (XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case Expose: ++ /* we'll redraw below */ ++ break; ++ case ConfigureNotify: ++ WinWidth = event.xconfigure.width; ++ WinHeight = event.xconfigure.height; ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ if (code == XK_Left) { ++ view_roty += 5.0; ++ } ++ else if (code == XK_Right) { ++ view_roty -= 5.0; ++ } ++ else if (code == XK_Up) { ++ view_rotx += 5.0; ++ } ++ else if (code == XK_Down) { ++ view_rotx -= 5.0; ++ } ++ else { ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return; ++ } ++ } ++ } ++ } ++ } ++ ++ { ++ static int frames = 0; ++ static double tRot0 = -1.0, tRate0 = -1.0; ++ double dt, t = current_time(); ++ if (tRot0 < 0.0) ++ tRot0 = t; ++ dt = t - tRot0; ++ tRot0 = t; ++ ++ /* advance rotation for next frame */ ++ angle += 70.0 * dt; /* 70 degrees per second */ ++ if (angle > 3600.0) ++ angle -= 3600.0; ++ ++ draw( dpy, win ); ++ ++ frames++; ++ ++ if (tRate0 < 0.0) ++ tRate0 = t; ++ ++ if (t - tRate0 >= 1.0) { ++ GLfloat seconds = t - tRate0; ++ GLfloat fps = frames / seconds; ++ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, ++ fps); ++ tRate0 = t; ++ ++ /* Destroy window and create new one */ ++ XDestroyWindow(dpy, win); ++ make_window(dpy, "glxgears", ++ (int)(fps * 100) % 100, (int)(fps * 100) % 100, /* x,y */ ++ WinWidth, WinHeight, &win); ++ XMapWindow(dpy, win); ++ ++ frames = 0; ++ } ++ } ++ } ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ char *dpyName = NULL; ++ GLboolean printInfo = GL_FALSE; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-info") == 0) { ++ printInfo = GL_TRUE; ++ } ++ else ++ printf("Warrning: unknown parameter: %s\n", argv[i]); ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ fprintf(stderr, "Error: couldn't open display %s\n", ++ XDisplayName(dpyName)); ++ return -1; ++ } ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ } ++ ++ event_loop(dpy); ++ ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxdemo.c Mesa-7.8.1.patched/progs/xdemos/glxdemo.c +--- Mesa-7.8.1/progs/xdemos/glxdemo.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxdemo.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,127 @@ ++ ++ ++/* ++ * A demonstration of using the GLX functions. This program is in the ++ * public domain. ++ * ++ * Brian Paul ++ */ ++ ++#include ++#include ++#include ++#include ++ ++ ++ ++static void redraw( Display *dpy, Window w ) ++{ ++ printf("Redraw event\n"); ++ ++ glClear( GL_COLOR_BUFFER_BIT ); ++ ++ glColor3f( 1.0, 1.0, 0.0 ); ++ glRectf( -0.8, -0.8, 0.8, 0.8 ); ++ ++ glXSwapBuffers( dpy, w ); ++} ++ ++ ++ ++static void resize( unsigned int width, unsigned int height ) ++{ ++ printf("Resize event\n"); ++ glViewport( 0, 0, width, height ); ++ glMatrixMode( GL_PROJECTION ); ++ glLoadIdentity(); ++ glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ); ++} ++ ++ ++ ++static Window make_rgb_db_window( Display *dpy, ++ unsigned int width, unsigned int height ) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attrib ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ++ ++ win = XCreateWindow( dpy, root, 0, 0, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ glXMakeCurrent( dpy, win, ctx ); ++ ++ return win; ++} ++ ++ ++static void event_loop( Display *dpy ) ++{ ++ XEvent event; ++ ++ while (1) { ++ XNextEvent( dpy, &event ); ++ ++ switch (event.type) { ++ case Expose: ++ redraw( dpy, event.xany.window ); ++ break; ++ case ConfigureNotify: ++ resize( event.xconfigure.width, event.xconfigure.height ); ++ break; ++ } ++ } ++} ++ ++ ++ ++int main( int argc, char *argv[] ) ++{ ++ Display *dpy; ++ Window win; ++ ++ dpy = XOpenDisplay(NULL); ++ ++ win = make_rgb_db_window( dpy, 300, 300 ); ++ ++ glShadeModel( GL_FLAT ); ++ glClearColor( 0.5, 0.5, 0.5, 1.0 ); ++ ++ XMapWindow( dpy, win ); ++ ++ event_loop( dpy ); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears.c Mesa-7.8.1.patched/progs/xdemos/glxgears.c +--- Mesa-7.8.1/progs/xdemos/glxgears.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxgears.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,787 @@ ++/* ++ * Copyright (C) 1999-2001 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. ++ */ ++ ++/* ++ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) ++ * Port by Brian Paul 23 March 2001 ++ * ++ * See usage() below for command line options. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef GLX_MESA_swap_control ++#define GLX_MESA_swap_control 1 ++typedef int (*PFNGLXGETSWAPINTERVALMESAPROC)(void); ++#endif ++ ++ ++#define BENCHMARK ++ ++#ifdef BENCHMARK ++ ++/* XXX this probably isn't very portable */ ++ ++#include ++#include ++ ++/* return current time (in seconds) */ ++static double ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (double) tv.tv_sec + tv.tv_usec / 1000000.0; ++} ++ ++#else /*BENCHMARK*/ ++ ++/* dummy */ ++static double ++current_time(void) ++{ ++ /* update this function for other platforms! */ ++ static double t = 0.0; ++ static int warn = 1; ++ if (warn) { ++ fprintf(stderr, "Warning: current_time() not implemented!!\n"); ++ warn = 0; ++ } ++ return t += 1.0; ++} ++ ++#endif /*BENCHMARK*/ ++ ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265 ++#endif ++ ++ ++/** Event handler results: */ ++#define NOP 0 ++#define EXIT 1 ++#define DRAW 2 ++ ++static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; ++static GLint gear1, gear2, gear3; ++static GLfloat angle = 0.0; ++ ++static GLboolean fullscreen = GL_FALSE; /* Create a single fullscreen window */ ++static GLboolean stereo = GL_FALSE; /* Enable stereo. */ ++static GLboolean animate = GL_TRUE; /* Animation */ ++static GLfloat eyesep = 5.0; /* Eye separation. */ ++static GLfloat fix_point = 40.0; /* Fixation point distance. */ ++static GLfloat left, right, asp; /* Stereo frustum params. */ ++ ++ ++/* ++ * ++ * Draw a gear wheel. You'll probably want to call this function when ++ * building a display list since we do a lot of trig here. ++ * ++ * Input: inner_radius - radius of hole at center ++ * outer_radius - radius at center of teeth ++ * width - width of gear ++ * teeth - number of teeth ++ * tooth_depth - depth of tooth ++ */ ++static void ++gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, ++ GLint teeth, GLfloat tooth_depth) ++{ ++ GLint i; ++ GLfloat r0, r1, r2; ++ GLfloat angle, da; ++ GLfloat u, v, len; ++ ++ r0 = inner_radius; ++ r1 = outer_radius - tooth_depth / 2.0; ++ r2 = outer_radius + tooth_depth / 2.0; ++ ++ da = 2.0 * M_PI / teeth / 4.0; ++ ++ glShadeModel(GL_FLAT); ++ ++ glNormal3f(0.0, 0.0, 1.0); ++ ++ /* draw front face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw front sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ glEnd(); ++ ++ glNormal3f(0.0, 0.0, -1.0); ++ ++ /* draw back face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw back sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ } ++ glEnd(); ++ ++ /* draw outward faces of teeth */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ u = r2 * cos(angle + da) - r1 * cos(angle); ++ v = r2 * sin(angle + da) - r1 * sin(angle); ++ len = sqrt(u * u + v * v); ++ u /= len; ++ v /= len; ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); ++ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ } ++ ++ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); ++ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); ++ ++ glEnd(); ++ ++ glShadeModel(GL_SMOOTH); ++ ++ /* draw inside radius cylinder */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glNormal3f(-cos(angle), -sin(angle), 0.0); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ } ++ glEnd(); ++} ++ ++ ++static void ++draw(void) ++{ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(view_rotx, 1.0, 0.0, 0.0); ++ glRotatef(view_roty, 0.0, 1.0, 0.0); ++ glRotatef(view_rotz, 0.0, 0.0, 1.0); ++ ++ glPushMatrix(); ++ glTranslatef(-3.0, -2.0, 0.0); ++ glRotatef(angle, 0.0, 0.0, 1.0); ++ glCallList(gear1); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(3.1, -2.0, 0.0); ++ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); ++ glCallList(gear2); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(-3.1, 4.2, 0.0); ++ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); ++ glCallList(gear3); ++ glPopMatrix(); ++ ++ glPopMatrix(); ++} ++ ++ ++static void ++draw_gears(void) ++{ ++ if (stereo) { ++ /* First left eye. */ ++ glDrawBuffer(GL_BACK_LEFT); ++ ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(left, right, -asp, asp, 5.0, 60.0); ++ ++ glMatrixMode(GL_MODELVIEW); ++ ++ glPushMatrix(); ++ glTranslated(+0.5 * eyesep, 0.0, 0.0); ++ draw(); ++ glPopMatrix(); ++ ++ /* Then right eye. */ ++ glDrawBuffer(GL_BACK_RIGHT); ++ ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-right, -left, -asp, asp, 5.0, 60.0); ++ ++ glMatrixMode(GL_MODELVIEW); ++ ++ glPushMatrix(); ++ glTranslated(-0.5 * eyesep, 0.0, 0.0); ++ draw(); ++ glPopMatrix(); ++ } ++ else { ++ draw(); ++ } ++} ++ ++ ++/** Draw single frame, do SwapBuffers, compute FPS */ ++static void ++draw_frame(Display *dpy, Window win) ++{ ++ static int frames = 0; ++ static double tRot0 = -1.0, tRate0 = -1.0; ++ double dt, t = current_time(); ++ ++ if (tRot0 < 0.0) ++ tRot0 = t; ++ dt = t - tRot0; ++ tRot0 = t; ++ ++ if (animate) { ++ /* advance rotation for next frame */ ++ angle += 70.0 * dt; /* 70 degrees per second */ ++ if (angle > 3600.0) ++ angle -= 3600.0; ++ } ++ ++ draw_gears(); ++ glXSwapBuffers(dpy, win); ++ ++ frames++; ++ ++ if (tRate0 < 0.0) ++ tRate0 = t; ++ if (t - tRate0 >= 5.0) { ++ GLfloat seconds = t - tRate0; ++ GLfloat fps = frames / seconds; ++ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, ++ fps); ++ tRate0 = t; ++ frames = 0; ++ } ++} ++ ++ ++/* new window size or exposure */ ++static void ++reshape(int width, int height) ++{ ++ glViewport(0, 0, (GLint) width, (GLint) height); ++ ++ if (stereo) { ++ GLfloat w; ++ ++ asp = (GLfloat) height / (GLfloat) width; ++ w = fix_point * (1.0 / 5.0); ++ ++ left = -5.0 * ((w - 0.5 * eyesep) / fix_point); ++ right = 5.0 * ((w + 0.5 * eyesep) / fix_point); ++ } ++ else { ++ GLfloat h = (GLfloat) height / (GLfloat) width; ++ ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); ++ } ++ ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -40.0); ++} ++ ++ ++ ++static void ++init(void) ++{ ++ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; ++ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; ++ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; ++ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_CULL_FACE); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ /* make the gears */ ++ gear1 = glGenLists(1); ++ glNewList(gear1, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); ++ gear(1.0, 4.0, 1.0, 20, 0.7); ++ glEndList(); ++ ++ gear2 = glGenLists(1); ++ glNewList(gear2, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); ++ gear(0.5, 2.0, 2.0, 10, 0.7); ++ glEndList(); ++ ++ gear3 = glGenLists(1); ++ glNewList(gear3, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); ++ gear(1.3, 2.0, 0.5, 10, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++} ++ ++ ++/** ++ * Remove window border/decorations. ++ */ ++static void ++no_border( Display *dpy, Window w) ++{ ++ static const unsigned MWM_HINTS_DECORATIONS = (1 << 1); ++ static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5; ++ ++ typedef struct ++ { ++ unsigned long flags; ++ unsigned long functions; ++ unsigned long decorations; ++ long inputMode; ++ unsigned long status; ++ } PropMotifWmHints; ++ ++ PropMotifWmHints motif_hints; ++ Atom prop, proptype; ++ unsigned long flags = 0; ++ ++ /* setup the property */ ++ motif_hints.flags = MWM_HINTS_DECORATIONS; ++ motif_hints.decorations = flags; ++ ++ /* get the atom for the property */ ++ prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True ); ++ if (!prop) { ++ /* something went wrong! */ ++ return; ++ } ++ ++ /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */ ++ proptype = prop; ++ ++ XChangeProperty( dpy, w, /* display, window */ ++ prop, proptype, /* property, type */ ++ 32, /* format: 32-bit datums */ ++ PropModeReplace, /* mode */ ++ (unsigned char *) &motif_hints, /* data */ ++ PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */ ++ ); ++} ++ ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( Display *dpy, const char *name, ++ int x, int y, int width, int height, ++ Window *winRet, GLXContext *ctxRet) ++{ ++ int attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int stereoAttribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ GLX_STEREO, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ if (fullscreen) { ++ x = 0; y = 0; ++ width = DisplayWidth( dpy, scrnum ); ++ height = DisplayHeight( dpy, scrnum ); ++ } ++ ++ if (stereo) ++ visinfo = glXChooseVisual( dpy, scrnum, stereoAttribs ); ++ else ++ visinfo = glXChooseVisual( dpy, scrnum, attribs ); ++ if (!visinfo) { ++ if (stereo) { ++ printf("Error: couldn't get an RGB, " ++ "Double-buffered, Stereo visual\n"); ++ } else ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ /* XXX this is a bad way to get a borderless window! */ ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ++ ++ win = XCreateWindow( dpy, root, x, y, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ if (fullscreen) ++ no_border(dpy, win); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(visinfo); ++ ++ *winRet = win; ++ *ctxRet = ctx; ++} ++ ++ ++/** ++ * Determine whether or not a GLX extension is supported. ++ */ ++static int ++is_glx_extension_supported(Display *dpy, const char *query) ++{ ++ const int scrnum = DefaultScreen(dpy); ++ const char *glx_extensions = NULL; ++ const size_t len = strlen(query); ++ const char *ptr; ++ ++ if (glx_extensions == NULL) { ++ glx_extensions = glXQueryExtensionsString(dpy, scrnum); ++ } ++ ++ ptr = strstr(glx_extensions, query); ++ return ((ptr != NULL) && ((ptr[len] == ' ') || (ptr[len] == '\0'))); ++} ++ ++ ++/** ++ * Attempt to determine whether or not the display is synched to vblank. ++ */ ++static void ++query_vsync(Display *dpy, GLXDrawable drawable) ++{ ++ int interval = 0; ++ ++#if defined(GLX_EXT_swap_control) ++ if (is_glx_extension_supported(dpy, "GLX_EXT_swap_control")) { ++ unsigned int tmp = -1; ++ glXQueryDrawable(dpy, drawable, GLX_SWAP_INTERVAL_EXT, &tmp); ++ interval = tmp; ++ } else ++#endif ++ if (is_glx_extension_supported(dpy, "GLX_MESA_swap_control")) { ++ PFNGLXGETSWAPINTERVALMESAPROC pglXGetSwapIntervalMESA = ++ (PFNGLXGETSWAPINTERVALMESAPROC) ++ glXGetProcAddressARB((const GLubyte *) "glXGetSwapIntervalMESA"); ++ ++ interval = (*pglXGetSwapIntervalMESA)(); ++ } else if (is_glx_extension_supported(dpy, "GLX_SGI_swap_control")) { ++ /* The default swap interval with this extension is 1. Assume that it ++ * is set to the default. ++ * ++ * Many Mesa-based drivers default to 0, but all of these drivers also ++ * export GLX_MESA_swap_control. In that case, this branch will never ++ * be taken, and the correct result should be reported. ++ */ ++ interval = 1; ++ } ++ ++ ++ if (interval > 0) { ++ printf("Running synchronized to the vertical refresh. The framerate should be\n"); ++ if (interval == 1) { ++ printf("approximately the same as the monitor refresh rate.\n"); ++ } else if (interval > 1) { ++ printf("approximately 1/%d the monitor refresh rate.\n", ++ interval); ++ } ++ } ++} ++ ++/** ++ * Handle one X event. ++ * \return NOP, EXIT or DRAW ++ */ ++static int ++handle_event(Display *dpy, Window win, XEvent *event) ++{ ++ (void) dpy; ++ (void) win; ++ ++ switch (event->type) { ++ case Expose: ++ return DRAW; ++ case ConfigureNotify: ++ reshape(event->xconfigure.width, event->xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event->xkey, 0); ++ if (code == XK_Left) { ++ view_roty += 5.0; ++ } ++ else if (code == XK_Right) { ++ view_roty -= 5.0; ++ } ++ else if (code == XK_Up) { ++ view_rotx += 5.0; ++ } ++ else if (code == XK_Down) { ++ view_rotx -= 5.0; ++ } ++ else { ++ r = XLookupString(&event->xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return EXIT; ++ } ++ else if (buffer[0] == 'a' || buffer[0] == 'A') { ++ animate = !animate; ++ } ++ } ++ return DRAW; ++ } ++ } ++ return NOP; ++} ++ ++ ++static void ++event_loop(Display *dpy, Window win) ++{ ++ while (1) { ++ int op; ++ while (!animate || XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ op = handle_event(dpy, win, &event); ++ if (op == EXIT) ++ return; ++ else if (op == DRAW) ++ break; ++ } ++ ++ draw_frame(dpy, win); ++ } ++} ++ ++ ++static void ++usage(void) ++{ ++ printf("Usage:\n"); ++ printf(" -display set the display to run on\n"); ++ printf(" -stereo run in stereo mode\n"); ++ printf(" -fullscreen run in fullscreen mode\n"); ++ printf(" -info display OpenGL renderer info\n"); ++ printf(" -geometry WxH+X+Y window geometry\n"); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ unsigned int winWidth = 300, winHeight = 300; ++ int x = 0, y = 0; ++ Display *dpy; ++ Window win; ++ GLXContext ctx; ++ char *dpyName = NULL; ++ GLboolean printInfo = GL_FALSE; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-info") == 0) { ++ printInfo = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-stereo") == 0) { ++ stereo = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-fullscreen") == 0) { ++ fullscreen = GL_TRUE; ++ } ++ else if (i < argc-1 && strcmp(argv[i], "-geometry") == 0) { ++ XParseGeometry(argv[i+1], &x, &y, &winWidth, &winHeight); ++ i++; ++ } ++ else { ++ usage(); ++ return -1; ++ } ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", ++ dpyName ? dpyName : getenv("DISPLAY")); ++ return -1; ++ } ++ ++ make_window(dpy, "glxgears", x, y, winWidth, winHeight, &win, &ctx); ++ XMapWindow(dpy, win); ++ glXMakeCurrent(dpy, win, ctx); ++ query_vsync(dpy, win); ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ } ++ ++ init(); ++ ++ /* Set initial projection/viewing transformation. ++ * We can't be sure we'll get a ConfigureNotify event when the window ++ * first appears. ++ */ ++ reshape(winWidth, winHeight); ++ ++ event_loop(dpy, win); ++ ++ glDeleteLists(gear1, 1); ++ glDeleteLists(gear2, 1); ++ glDeleteLists(gear3, 1); ++ glXMakeCurrent(dpy, None, NULL); ++ glXDestroyContext(dpy, ctx); ++ XDestroyWindow(dpy, win); ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears_fbconfig.c Mesa-7.8.1.patched/progs/xdemos/glxgears_fbconfig.c +--- Mesa-7.8.1/progs/xdemos/glxgears_fbconfig.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxgears_fbconfig.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,632 @@ ++/* ++ * Copyright (C) 1999-2001 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. ++ */ ++ ++/** ++ * \file glxgears_fbconfig.c ++ * Yet-another-version of gears. Originally ported to GLX by Brian Paul on ++ * 23 March 2001. Modified to use fbconfigs by Ian Romanick on 10 Feb 2004. ++ * ++ * Command line options: ++ * -info print GL implementation information ++ * ++ * \author Brian Paul ++ * \author Ian Romanick ++ */ ++ ++ ++#define GLX_GLXEXT_PROTOTYPES ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pbutil.h" ++ ++static PFNGLXCHOOSEFBCONFIGPROC choose_fbconfig = NULL; ++static PFNGLXGETVISUALFROMFBCONFIGPROC get_visual_from_fbconfig = NULL; ++static PFNGLXCREATENEWCONTEXTPROC create_new_context = NULL; ++static PFNGLXCREATEWINDOWPROC create_window = NULL; ++static PFNGLXDESTROYWINDOWPROC destroy_window = NULL; ++ ++#define BENCHMARK ++ ++#ifdef BENCHMARK ++ ++/* XXX this probably isn't very portable */ ++ ++#include ++#include ++ ++/* return current time (in seconds) */ ++static int ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (int) tv.tv_sec; ++} ++ ++#else /*BENCHMARK*/ ++ ++/* dummy */ ++static int ++current_time(void) ++{ ++ return 0; ++} ++ ++#endif /*BENCHMARK*/ ++ ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265 ++#endif ++ ++ ++static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; ++static GLint gear1, gear2, gear3; ++static GLfloat angle = 0.0; ++ ++ ++/* ++ * ++ * Draw a gear wheel. You'll probably want to call this function when ++ * building a display list since we do a lot of trig here. ++ * ++ * Input: inner_radius - radius of hole at center ++ * outer_radius - radius at center of teeth ++ * width - width of gear ++ * teeth - number of teeth ++ * tooth_depth - depth of tooth ++ */ ++static void ++gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, ++ GLint teeth, GLfloat tooth_depth) ++{ ++ GLint i; ++ GLfloat r0, r1, r2; ++ GLfloat angle, da; ++ GLfloat u, v, len; ++ ++ r0 = inner_radius; ++ r1 = outer_radius - tooth_depth / 2.0; ++ r2 = outer_radius + tooth_depth / 2.0; ++ ++ da = 2.0 * M_PI / teeth / 4.0; ++ ++ glShadeModel(GL_FLAT); ++ ++ glNormal3f(0.0, 0.0, 1.0); ++ ++ /* draw front face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw front sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ glEnd(); ++ ++ glNormal3f(0.0, 0.0, -1.0); ++ ++ /* draw back face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw back sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ } ++ glEnd(); ++ ++ /* draw outward faces of teeth */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ u = r2 * cos(angle + da) - r1 * cos(angle); ++ v = r2 * sin(angle + da) - r1 * sin(angle); ++ len = sqrt(u * u + v * v); ++ u /= len; ++ v /= len; ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); ++ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ } ++ ++ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); ++ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); ++ ++ glEnd(); ++ ++ glShadeModel(GL_SMOOTH); ++ ++ /* draw inside radius cylinder */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glNormal3f(-cos(angle), -sin(angle), 0.0); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ } ++ glEnd(); ++} ++ ++ ++static void ++draw(void) ++{ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(view_rotx, 1.0, 0.0, 0.0); ++ glRotatef(view_roty, 0.0, 1.0, 0.0); ++ glRotatef(view_rotz, 0.0, 0.0, 1.0); ++ ++ glPushMatrix(); ++ glTranslatef(-3.0, -2.0, 0.0); ++ glRotatef(angle, 0.0, 0.0, 1.0); ++ glCallList(gear1); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(3.1, -2.0, 0.0); ++ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); ++ glCallList(gear2); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(-3.1, 4.2, 0.0); ++ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); ++ glCallList(gear3); ++ glPopMatrix(); ++ ++ glPopMatrix(); ++} ++ ++ ++/* new window size or exposure */ ++static void ++reshape(int width, int height) ++{ ++ GLfloat h = (GLfloat) height / (GLfloat) width; ++ ++ glViewport(0, 0, (GLint) width, (GLint) height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -40.0); ++} ++ ++ ++static void ++init(void) ++{ ++ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; ++ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; ++ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; ++ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_CULL_FACE); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ /* make the gears */ ++ gear1 = glGenLists(1); ++ glNewList(gear1, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); ++ gear(1.0, 4.0, 1.0, 20, 0.7); ++ glEndList(); ++ ++ gear2 = glGenLists(1); ++ glNewList(gear2, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); ++ gear(0.5, 2.0, 2.0, 10, 0.7); ++ glEndList(); ++ ++ gear3 = glGenLists(1); ++ glNewList(gear3, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); ++ gear(1.3, 2.0, 0.5, 10, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++} ++ ++ ++static GLXWindow ++dummy_create_window(Display *dpy, GLXFBConfig config, Window win, ++ const int *attrib_list) ++{ ++ (void) dpy; ++ (void) config; ++ (void) attrib_list; ++ ++ return (GLXWindow) win; ++} ++ ++ ++static void ++dummy_destroy_window(Display *dpy, GLXWindow win) ++{ ++ (void) dpy; ++ (void) win; ++} ++ ++ ++/** ++ * Initialize fbconfig related function pointers. ++ */ ++static void ++init_fbconfig_functions(Display *dpy, int scrnum) ++{ ++ const char * glx_extensions; ++ const char * match; ++ static const char ext_name[] = "GLX_SGIX_fbconfig"; ++ const size_t len = strlen( ext_name ); ++ int major; ++ int minor; ++ GLboolean ext_version_supported; ++ GLboolean glx_1_3_supported; ++ ++ ++ /* Determine if GLX 1.3 or greater is supported. ++ */ ++ glXQueryVersion(dpy, & major, & minor); ++ glx_1_3_supported = (major == 1) && (minor >= 3); ++ ++ /* Determine if GLX_SGIX_fbconfig is supported. ++ */ ++ glx_extensions = glXQueryExtensionsString(dpy, scrnum); ++ match = strstr( glx_extensions, ext_name ); ++ ++ ext_version_supported = (match != NULL) ++ && ((match[len] == '\0') || (match[len] == ' ')); ++ ++ printf( "GLX 1.3 is %ssupported.\n", ++ (glx_1_3_supported) ? "" : "not " ); ++ printf( "%s is %ssupported.\n", ++ ext_name, (ext_version_supported) ? "" : "not " ); ++ ++ if ( glx_1_3_supported ) { ++ choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC) ++ glXGetProcAddressARB((GLubyte *) "glXChooseFBConfig"); ++ get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) ++ glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfig"); ++ create_new_context = (PFNGLXCREATENEWCONTEXTPROC) ++ glXGetProcAddressARB((GLubyte *) "glXCreateNewContext"); ++ create_window = (PFNGLXCREATEWINDOWPROC) ++ glXGetProcAddressARB((GLubyte *) "glXCreateWindow"); ++ destroy_window = (PFNGLXDESTROYWINDOWPROC) ++ glXGetProcAddressARB((GLubyte *) "glXDestroyWindow"); ++ } ++ else if ( ext_version_supported ) { ++ choose_fbconfig = (PFNGLXCHOOSEFBCONFIGPROC) ++ glXGetProcAddressARB((GLubyte *) "glXChooseFBConfigSGIX"); ++ get_visual_from_fbconfig = (PFNGLXGETVISUALFROMFBCONFIGPROC) ++ glXGetProcAddressARB((GLubyte *) "glXGetVisualFromFBConfigSGIX"); ++ create_new_context = (PFNGLXCREATENEWCONTEXTPROC) ++ glXGetProcAddressARB((GLubyte *) "glXCreateContextWithConfigSGIX"); ++ create_window = dummy_create_window; ++ destroy_window = dummy_destroy_window; ++ } ++ else { ++ printf( "This demo requires either GLX 1.3 or %s be supported.\n", ++ ext_name ); ++ exit(1); ++ } ++ ++ if ( choose_fbconfig == NULL ) { ++ printf( "glXChooseFBConfig not found!\n" ); ++ exit(1); ++ } ++ ++ if ( get_visual_from_fbconfig == NULL ) { ++ printf( "glXGetVisualFromFBConfig not found!\n" ); ++ exit(1); ++ } ++ ++ if ( create_new_context == NULL ) { ++ printf( "glXCreateNewContext not found!\n" ); ++ exit(1); ++ } ++} ++ ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( Display *dpy, const char *name, ++ int x, int y, int width, int height, ++ Window *winRet, GLXWindow *glxWinRet, GLXContext *ctxRet) ++{ ++ int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, GL_TRUE, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ GLXFBConfig * fbconfig; ++ int num_configs; ++ int scrnum; ++ int i; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXWindow glxWin; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ init_fbconfig_functions(dpy, scrnum); ++ fbconfig = (*choose_fbconfig)(dpy, scrnum, attrib, & num_configs); ++ if (fbconfig == NULL) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ printf("\nThe following fbconfigs meet the requirements. The first one " ++ "will be used.\n\n"); ++ for ( i = 0 ; i < num_configs ; i++ ) { ++ PrintFBConfigInfo(dpy, scrnum, fbconfig[i], GL_TRUE); ++ } ++ ++ /* window attributes */ ++ visinfo = (*get_visual_from_fbconfig)(dpy, fbconfig[0]); ++ assert(visinfo != NULL); ++ 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 ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ glxWin = (*create_window)(dpy, fbconfig[0], win, NULL); ++ ++ ctx = (*create_new_context)(dpy, fbconfig[0], GLX_RGBA_TYPE, NULL, GL_TRUE); ++ if (!ctx) { ++ printf("Error: glXCreateNewContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(fbconfig); ++ ++ *glxWinRet = glxWin; ++ *winRet = win; ++ *ctxRet = ctx; ++} ++ ++ ++static void ++event_loop(Display *dpy, GLXWindow win) ++{ ++ while (1) { ++ while (XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case Expose: ++ /* we'll redraw below */ ++ break; ++ case ConfigureNotify: ++ reshape(event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ if (code == XK_Left) { ++ view_roty += 5.0; ++ } ++ else if (code == XK_Right) { ++ view_roty -= 5.0; ++ } ++ else if (code == XK_Up) { ++ view_rotx += 5.0; ++ } ++ else if (code == XK_Down) { ++ view_rotx -= 5.0; ++ } ++ else { ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return; ++ } ++ } ++ } ++ } ++ } ++ ++ /* next frame */ ++ angle += 2.0; ++ ++ draw(); ++ glXSwapBuffers(dpy, win); ++ ++ /* calc framerate */ ++ { ++ static int t0 = -1; ++ static int frames = 0; ++ int t = current_time(); ++ ++ if (t0 < 0) ++ t0 = t; ++ ++ frames++; ++ ++ if (t - t0 >= 5.0) { ++ GLfloat seconds = t - t0; ++ GLfloat fps = frames / seconds; ++ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, ++ fps); ++ t0 = t; ++ frames = 0; ++ } ++ } ++ } ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ Window win; ++ GLXWindow glxWin; ++ GLXContext ctx; ++ const char *dpyName = NULL; ++ GLboolean printInfo = GL_FALSE; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-info") == 0) { ++ printInfo = GL_TRUE; ++ } ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", XDisplayName(dpyName)); ++ return -1; ++ } ++ ++ make_window(dpy, "glxgears", 0, 0, 300, 300, &win, &glxWin, &ctx); ++ XMapWindow(dpy, win); ++ glXMakeCurrent(dpy, glxWin, ctx); ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ } ++ ++ init(); ++ ++ event_loop(dpy, glxWin); ++ ++ glXDestroyContext(dpy, ctx); ++ destroy_window(dpy, glxWin); ++ XDestroyWindow(dpy, win); ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxgears_pixmap.c Mesa-7.8.1.patched/progs/xdemos/glxgears_pixmap.c +--- Mesa-7.8.1/progs/xdemos/glxgears_pixmap.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxgears_pixmap.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,547 @@ ++/* ++ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. ++ * Copyright (C) 2008 Red Hat, Inc 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. ++ */ ++ ++/** ++ * \file glxgears_pixmap.c ++ * Yet-another-version of gears. Originally ported to GLX by Brian Paul on ++ * 23 March 2001. Modified to use fbconfigs by Ian Romanick on 10 Feb 2004. ++ * ++ * Command line options: ++ * -info print GL implementation information ++ * ++ * \author Brian Paul ++ * \author Ian Romanick ++ * \author Kristian Hoegsberg ++ */ ++ ++ ++#define GLX_GLXEXT_PROTOTYPES ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "pbutil.h" ++ ++#define BENCHMARK ++ ++#ifdef BENCHMARK ++ ++/* XXX this probably isn't very portable */ ++ ++#include ++#include ++ ++/* return current time (in seconds) */ ++static int ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (int) tv.tv_sec; ++} ++ ++#else /*BENCHMARK*/ ++ ++/* dummy */ ++static int ++current_time(void) ++{ ++ return 0; ++} ++ ++#endif /*BENCHMARK*/ ++ ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265 ++#endif ++ ++ ++static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; ++static GLint gear1, gear2, gear3; ++static GLfloat angle = 0.0; ++ ++ ++/* ++ * ++ * Draw a gear wheel. You'll probably want to call this function when ++ * building a display list since we do a lot of trig here. ++ * ++ * Input: inner_radius - radius of hole at center ++ * outer_radius - radius at center of teeth ++ * width - width of gear ++ * teeth - number of teeth ++ * tooth_depth - depth of tooth ++ */ ++static void ++gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, ++ GLint teeth, GLfloat tooth_depth) ++{ ++ GLint i; ++ GLfloat r0, r1, r2; ++ GLfloat angle, da; ++ GLfloat u, v, len; ++ ++ r0 = inner_radius; ++ r1 = outer_radius - tooth_depth / 2.0; ++ r2 = outer_radius + tooth_depth / 2.0; ++ ++ da = 2.0 * M_PI / teeth / 4.0; ++ ++ glShadeModel(GL_FLAT); ++ ++ glNormal3f(0.0, 0.0, 1.0); ++ ++ /* draw front face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw front sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ glEnd(); ++ ++ glNormal3f(0.0, 0.0, -1.0); ++ ++ /* draw back face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw back sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ } ++ glEnd(); ++ ++ /* draw outward faces of teeth */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ u = r2 * cos(angle + da) - r1 * cos(angle); ++ v = r2 * sin(angle + da) - r1 * sin(angle); ++ len = sqrt(u * u + v * v); ++ u /= len; ++ v /= len; ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); ++ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ } ++ ++ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); ++ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); ++ ++ glEnd(); ++ ++ glShadeModel(GL_SMOOTH); ++ ++ /* draw inside radius cylinder */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glNormal3f(-cos(angle), -sin(angle), 0.0); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ } ++ glEnd(); ++} ++ ++ ++static void ++draw(void) ++{ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(view_rotx, 1.0, 0.0, 0.0); ++ glRotatef(view_roty, 0.0, 1.0, 0.0); ++ glRotatef(view_rotz, 0.0, 0.0, 1.0); ++ ++ glPushMatrix(); ++ glTranslatef(-3.0, -2.0, 0.0); ++ glRotatef(angle, 0.0, 0.0, 1.0); ++ glCallList(gear1); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(3.1, -2.0, 0.0); ++ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); ++ glCallList(gear2); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(-3.1, 4.2, 0.0); ++ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); ++ glCallList(gear3); ++ glPopMatrix(); ++ ++ glPopMatrix(); ++} ++ ++ ++struct gears { ++ Window win; ++ GLXContext ctx; ++ Pixmap pixmap; ++ GLXPixmap glxpixmap; ++ GC gc; ++ int width, height; ++}; ++ ++ ++/* new window size or exposure */ ++static void ++reshape(struct gears *gears, int width, int height) ++{ ++ gears->width = width; ++ gears->height = height; ++} ++ ++ ++static void ++init(int width, int height) ++{ ++ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; ++ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; ++ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; ++ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; ++ GLfloat h = (GLfloat) height / (GLfloat) width; ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_CULL_FACE); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ /* make the gears */ ++ gear1 = glGenLists(1); ++ glNewList(gear1, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); ++ gear(1.0, 4.0, 1.0, 20, 0.7); ++ glEndList(); ++ ++ gear2 = glGenLists(1); ++ glNewList(gear2, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); ++ gear(0.5, 2.0, 2.0, 10, 0.7); ++ glEndList(); ++ ++ gear3 = glGenLists(1); ++ glNewList(gear3, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); ++ gear(1.3, 2.0, 0.5, 10, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++ ++ glViewport(0, 0, (GLint) width, (GLint) height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -40.0); ++} ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( Display *dpy, const char *name, ++ int x, int y, int width, int height, struct gears *gears) ++{ ++ int attrib[] = { GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, GL_FALSE, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ GLXFBConfig * fbconfig; ++ int num_configs; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ XVisualInfo *visinfo; ++ ++ gears->width = width; ++ gears->height = height; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ fbconfig = glXChooseFBConfig(dpy, scrnum, attrib, & num_configs); ++ if (fbconfig == NULL) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* window attributes */ ++ visinfo = glXGetVisualFromFBConfig(dpy, fbconfig[0]); ++ assert(visinfo != NULL); ++ 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; ++ ++ gears->win = XCreateWindow( dpy, root, 0, 0, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, gears->win, &sizehints); ++ XSetStandardProperties(dpy, gears->win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ gears->gc = XCreateGC(dpy, gears->win, 0, NULL); ++ ++ gears->pixmap = XCreatePixmap(dpy, gears->win, ++ width, height, visinfo->depth); ++ if (!gears->pixmap) { ++ printf("Error: XCreatePixmap failed\n"); ++ exit(-1); ++ } ++ ++ gears->glxpixmap = glXCreatePixmap(dpy, fbconfig[0], gears->pixmap, NULL); ++ if (!gears->glxpixmap) { ++ printf("Error: glXCreatePixmap failed\n"); ++ exit(-1); ++ } ++ ++ gears->ctx = glXCreateNewContext(dpy, fbconfig[0], ++ GLX_RGBA_TYPE, NULL, GL_TRUE); ++ if (!gears->ctx) { ++ printf("Error: glXCreateNewContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(fbconfig); ++} ++ ++ ++static void ++event_loop(Display *dpy, struct gears *gears) ++{ ++ int x, y; ++ ++ while (1) { ++ while (XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case Expose: ++ /* we'll redraw below */ ++ break; ++ case ConfigureNotify: ++ reshape(gears, event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ if (code == XK_Left) { ++ view_roty += 5.0; ++ } ++ else if (code == XK_Right) { ++ view_roty -= 5.0; ++ } ++ else if (code == XK_Up) { ++ view_rotx += 5.0; ++ } ++ else if (code == XK_Down) { ++ view_rotx -= 5.0; ++ } ++ else { ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return; ++ } ++ } ++ } ++ } ++ } ++ ++ /* next frame */ ++ angle += 2.0; ++ ++ draw(); ++ glFinish(); ++ ++ for (x = 0; x < gears->width; x += 100) ++ for (y = 0; y < gears->width; y += 100) ++ XCopyArea(dpy, gears->pixmap, gears->win, gears->gc, ++ 50, 50, 100, 100, x, y); ++ ++ /* calc framerate */ ++ { ++ static int t0 = -1; ++ static int frames = 0; ++ int t = current_time(); ++ ++ if (t0 < 0) ++ t0 = t; ++ ++ frames++; ++ ++ if (t - t0 >= 5.0) { ++ GLfloat seconds = t - t0; ++ GLfloat fps = frames / seconds; ++ printf("%d frames in %3.1f seconds = %6.3f FPS\n", frames, seconds, ++ fps); ++ t0 = t; ++ frames = 0; ++ } ++ } ++ } ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ const char *dpyName = NULL; ++ GLboolean printInfo = GL_FALSE; ++ struct gears gears; ++ int i, width = 200, height = 200; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-info") == 0) { ++ printInfo = GL_TRUE; ++ } ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", XDisplayName(dpyName)); ++ return -1; ++ } ++ ++ make_window(dpy, "glxgears", 0, 0, width, height, &gears); ++ XMapWindow(dpy, gears.win); ++ glXMakeCurrent(dpy, gears.glxpixmap, gears.ctx); ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ } ++ ++ init(width, height); ++ ++ event_loop(dpy, &gears); ++ ++ glXDestroyContext(dpy, gears.ctx); ++ XDestroyWindow(dpy, gears.win); ++ glXDestroyPixmap(dpy, gears.pixmap); ++ XFreePixmap(dpy, gears.pixmap); ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxheads.c Mesa-7.8.1.patched/progs/xdemos/glxheads.c +--- Mesa-7.8.1/progs/xdemos/glxheads.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxheads.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,313 @@ ++ ++/* ++ * Exercise multiple GLX connections on multiple X displays. ++ * Direct GLX contexts are attempted first, then indirect. ++ * Each window will display a spinning green triangle. ++ * ++ * Copyright (C) 2000 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. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++ ++/* ++ * Each display/window/context: ++ */ ++struct head { ++ char DisplayName[1000]; ++ Display *Dpy; ++ Window Win; ++ GLXContext Context; ++ float Angle; ++ char Renderer[1000]; ++ char Vendor[1000]; ++ char Version[1000]; ++}; ++ ++ ++#define MAX_HEADS 20 ++static struct head Heads[MAX_HEADS]; ++static int NumHeads = 0; ++ ++ ++static void ++Error(const char *display, const char *msg) ++{ ++ fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg); ++ exit(1); ++} ++ ++ ++static struct head * ++AddHead(const char *displayName) ++{ ++ Display *dpy; ++ Window win; ++ GLXContext ctx; ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ XVisualInfo *visinfo; ++ int width = 300, height = 300; ++ int xpos = 10, ypos = 10; ++ ++ if (NumHeads >= MAX_HEADS) ++ return NULL; ++ ++ dpy = XOpenDisplay(displayName); ++ if (!dpy) { ++ Error(displayName, "Unable to open display"); ++ return NULL; ++ } ++ ++ scrnum = DefaultScreen(dpy); ++ root = RootWindow(dpy, scrnum); ++ ++ visinfo = glXChooseVisual(dpy, scrnum, attrib); ++ if (!visinfo) { ++ Error(displayName, "Unable to find RGB, double-buffered visual"); ++ return NULL; ++ } ++ ++ /* 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) { ++ Error(displayName, "Couldn't create window"); ++ return NULL; ++ } ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, displayName, displayName, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ++ ctx = glXCreateContext(dpy, visinfo, NULL, True); ++ if (!ctx) { ++ Error(displayName, "Couldn't create GLX context"); ++ return NULL; ++ } ++ ++ XMapWindow(dpy, win); ++ ++ if (!glXMakeCurrent(dpy, win, ctx)) { ++ Error(displayName, "glXMakeCurrent failed"); ++ printf("glXMakeCurrent failed in Redraw()\n"); ++ return NULL; ++ } ++ ++ /* save the info for this head */ ++ { ++ struct head *h = &Heads[NumHeads]; ++ const char * tmp; ++ ++ if (strlen(displayName) + 1 > sizeof(h->DisplayName)) { ++ Error(displayName, "displayName string length overflow"); ++ return NULL; ++ } ++ strcpy(h->DisplayName, displayName); ++ ++ h->Dpy = dpy; ++ h->Win = win; ++ h->Context = ctx; ++ h->Angle = 0.0; ++ ++ tmp = (char *) glGetString(GL_VERSION); ++ if (strlen(tmp) + 1 > sizeof(h->Version)) { ++ Error(displayName, "GL_VERSION string length overflow"); ++ return NULL; ++ } ++ strcpy(h->Version, tmp); ++ ++ tmp = (char *) glGetString(GL_VENDOR); ++ if (strlen(tmp) + 1 > sizeof(h->Vendor)) { ++ Error(displayName, "GL_VENDOR string length overflow"); ++ return NULL; ++ } ++ strcpy(h->Vendor, tmp); ++ ++ tmp = (char *) glGetString(GL_RENDERER); ++ if (strlen(tmp) + 1 > sizeof(h->Renderer)) { ++ Error(displayName, "GL_RENDERER string length overflow"); ++ return NULL; ++ } ++ strcpy(h->Renderer, tmp); ++ ++ NumHeads++; ++ return &Heads[NumHeads-1]; ++ } ++ ++} ++ ++ ++static void ++Redraw(struct head *h) ++{ ++ if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { ++ Error(h->DisplayName, "glXMakeCurrent failed"); ++ printf("glXMakeCurrent failed in Redraw()\n"); ++ return; ++ } ++ ++ h->Angle += 1.0; ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.5, 0.5, 0.5, 1.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ /* draw green triangle */ ++ glColor3f(0.0, 1.0, 0.0); ++ glPushMatrix(); ++ glRotatef(h->Angle, 0, 0, 1); ++ glBegin(GL_TRIANGLES); ++ glVertex2f(0, 0.8); ++ glVertex2f(-0.8, -0.7); ++ glVertex2f(0.8, -0.7); ++ glEnd(); ++ glPopMatrix(); ++ ++ glXSwapBuffers(h->Dpy, h->Win); ++} ++ ++ ++ ++static void ++Resize(const struct head *h, unsigned int width, unsigned int height) ++{ ++ if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { ++ Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); ++ return; ++ } ++ glFlush(); ++ glViewport(0, 0, width, height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); ++} ++ ++ ++ ++static void ++EventLoop(void) ++{ ++ while (1) { ++ int i; ++ for (i = 0; i < NumHeads; i++) { ++ struct head *h = &Heads[i]; ++ while (XPending(h->Dpy) > 0) { ++ XEvent event; ++ XNextEvent(h->Dpy, &event); ++ if (event.xany.window == h->Win) { ++ switch (event.type) { ++ case Expose: ++ Redraw(h); ++ break; ++ case ConfigureNotify: ++ Resize(h, event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ return; ++ default: ++ /*no-op*/ ; ++ } ++ } ++ else { ++ printf("window mismatch\n"); ++ } ++ } ++ Redraw(h); ++ } ++ usleep(1); ++ } ++} ++ ++ ++ ++static void ++PrintInfo(const struct head *h) ++{ ++ printf("Name: %s\n", h->DisplayName); ++ printf(" Display: %p\n", (void *) h->Dpy); ++ printf(" Window: 0x%x\n", (int) h->Win); ++ printf(" Context: 0x%lx\n", (long) h->Context); ++ printf(" GL_VERSION: %s\n", h->Version); ++ printf(" GL_VENDOR: %s\n", h->Vendor); ++ printf(" GL_RENDERER: %s\n", h->Renderer); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ int i; ++ if (argc == 1) { ++ struct head *h; ++ printf("glxheads: exercise multiple GLX connections (any key = exit)\n"); ++ printf("Usage:\n"); ++ printf(" glxheads xdisplayname ...\n"); ++ printf("Example:\n"); ++ printf(" glxheads :0 mars:0 venus:1\n"); ++ ++ h = AddHead(XDisplayName(NULL)); ++ if (h) ++ PrintInfo(h); ++ } ++ else { ++ for (i = 1; i < argc; i++) { ++ const char *name = argv[i]; ++ struct head *h = AddHead(name); ++ if (h) { ++ PrintInfo(h); ++ } ++ } ++ } ++ ++ EventLoop(); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxinfo.c Mesa-7.8.1.patched/progs/xdemos/glxinfo.c +--- Mesa-7.8.1/progs/xdemos/glxinfo.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxinfo.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,1195 @@ ++/* ++ * Copyright (C) 1999-2006 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. ++ */ ++ ++ ++/* ++ * This program is a work-alike of the IRIX glxinfo program. ++ * Command line options: ++ * -t print wide table ++ * -v print verbose information ++ * -display DisplayName specify the X display to interogate ++ * -b only print ID of "best" visual on screen 0 ++ * -i use indirect rendering connection only ++ * -l print interesting OpenGL limits (added 5 Sep 2002) ++ * ++ * Brian Paul 26 January 2000 ++ */ ++ ++#define GLX_GLXEXT_PROTOTYPES ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#ifndef GLX_NONE_EXT ++#define GLX_NONE_EXT 0x8000 ++#endif ++ ++#ifndef GLX_TRANSPARENT_RGB ++#define GLX_TRANSPARENT_RGB 0x8008 ++#endif ++ ++#ifndef GLX_RGBA_BIT ++#define GLX_RGBA_BIT 0x00000001 ++#endif ++ ++#ifndef GLX_COLOR_INDEX_BIT ++#define GLX_COLOR_INDEX_BIT 0x00000002 ++#endif ++ ++typedef enum ++{ ++ Normal, ++ Wide, ++ Verbose ++} InfoMode; ++ ++ ++struct visual_attribs ++{ ++ /* X visual attribs */ ++ int id; ++ int klass; ++ int depth; ++ int redMask, greenMask, blueMask; ++ int colormapSize; ++ int bitsPerRGB; ++ ++ /* GL visual attribs */ ++ int supportsGL; ++ int transparentType; ++ int transparentRedValue; ++ int transparentGreenValue; ++ int transparentBlueValue; ++ int transparentAlphaValue; ++ int transparentIndexValue; ++ int bufferSize; ++ int level; ++ int render_type; ++ int doubleBuffer; ++ int stereo; ++ int auxBuffers; ++ int redSize, greenSize, blueSize, alphaSize; ++ int depthSize; ++ int stencilSize; ++ int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize; ++ int numSamples, numMultisample; ++ int visualCaveat; ++}; ++ ++ ++/* ++ * Print a list of extensions, with word-wrapping. ++ */ ++static void ++print_extension_list(const char *ext) ++{ ++ const char *indentString = " "; ++ const int indent = 4; ++ const int max = 79; ++ int width, i, j; ++ ++ if (!ext || !ext[0]) ++ return; ++ ++ width = indent; ++ printf("%s", indentString); ++ i = j = 0; ++ while (1) { ++ if (ext[j] == ' ' || ext[j] == 0) { ++ /* found end of an extension name */ ++ const int len = j - i; ++ if (width + len > max) { ++ /* start a new line */ ++ printf("\n"); ++ width = indent; ++ printf("%s", indentString); ++ } ++ /* print the extension name between ext[i] and ext[j] */ ++ while (i < j) { ++ printf("%c", ext[i]); ++ i++; ++ } ++ /* either we're all done, or we'll continue with next extension */ ++ width += len + 1; ++ if (ext[j] == 0) { ++ break; ++ } ++ else { ++ i++; ++ j++; ++ if (ext[j] == 0) ++ break; ++ printf(", "); ++ width += 2; ++ } ++ } ++ j++; ++ } ++ printf("\n"); ++} ++ ++ ++static void ++print_display_info(Display *dpy) ++{ ++ printf("name of display: %s\n", DisplayString(dpy)); ++} ++ ++ ++/** ++ * Print interesting limits for vertex/fragment programs. ++ */ ++static void ++print_program_limits(GLenum target) ++{ ++#if defined(GL_ARB_vertex_program) || defined(GL_ARB_fragment_program) ++ struct token_name { ++ GLenum token; ++ const char *name; ++ }; ++ static const struct token_name common_limits[] = { ++ { GL_MAX_PROGRAM_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_INSTRUCTIONS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB" }, ++ { GL_MAX_PROGRAM_TEMPORARIES_ARB, "GL_MAX_PROGRAM_TEMPORARIES_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB, "GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB" }, ++ { GL_MAX_PROGRAM_PARAMETERS_ARB, "GL_MAX_PROGRAM_PARAMETERS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB, "GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB" }, ++ { GL_MAX_PROGRAM_ATTRIBS_ARB, "GL_MAX_PROGRAM_ATTRIBS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB, "GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB" }, ++ { GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB, "GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB" }, ++ { GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB, "GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB" }, ++ { GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, "GL_MAX_PROGRAM_ENV_PARAMETERS_ARB" }, ++ { (GLenum) 0, NULL } ++ }; ++ static const struct token_name fragment_limits[] = { ++ { GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB" }, ++ { GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB" }, ++ { GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB" }, ++ { GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB, "GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB" }, ++ { (GLenum) 0, NULL } ++ }; ++ ++ PFNGLGETPROGRAMIVARBPROC GetProgramivARB_func = (PFNGLGETPROGRAMIVARBPROC) ++ glXGetProcAddressARB((GLubyte *) "glGetProgramivARB"); ++ ++ GLint max[1]; ++ int i; ++ ++ if (target == GL_VERTEX_PROGRAM_ARB) { ++ printf(" GL_VERTEX_PROGRAM_ARB:\n"); ++ } ++ else if (target == GL_FRAGMENT_PROGRAM_ARB) { ++ printf(" GL_FRAGMENT_PROGRAM_ARB:\n"); ++ } ++ else { ++ return; /* something's wrong */ ++ } ++ ++ for (i = 0; common_limits[i].token; i++) { ++ GetProgramivARB_func(target, common_limits[i].token, max); ++ if (glGetError() == GL_NO_ERROR) { ++ printf(" %s = %d\n", common_limits[i].name, max[0]); ++ } ++ } ++ if (target == GL_FRAGMENT_PROGRAM_ARB) { ++ for (i = 0; fragment_limits[i].token; i++) { ++ GetProgramivARB_func(target, fragment_limits[i].token, max); ++ if (glGetError() == GL_NO_ERROR) { ++ printf(" %s = %d\n", fragment_limits[i].name, max[0]); ++ } ++ } ++ } ++#endif /* GL_ARB_vertex_program / GL_ARB_fragment_program */ ++} ++ ++ ++/** ++ * Print interesting limits for vertex/fragment shaders. ++ */ ++static void ++print_shader_limits(GLenum target) ++{ ++ struct token_name { ++ GLenum token; ++ const char *name; ++ }; ++#if defined(GL_ARB_vertex_shader) ++ static const struct token_name vertex_limits[] = { ++ { GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB, "GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB" }, ++ { GL_MAX_VARYING_FLOATS_ARB, "GL_MAX_VARYING_FLOATS_ARB" }, ++ { GL_MAX_VERTEX_ATTRIBS_ARB, "GL_MAX_VERTEX_ATTRIBS_ARB" }, ++ { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" }, ++ { GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB" }, ++ { GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB" }, ++ { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" }, ++ { (GLenum) 0, NULL } ++ }; ++#endif ++#if defined(GL_ARB_fragment_shader) ++ static const struct token_name fragment_limits[] = { ++ { GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB, "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB" }, ++ { GL_MAX_TEXTURE_COORDS_ARB, "GL_MAX_TEXTURE_COORDS_ARB" }, ++ { GL_MAX_TEXTURE_IMAGE_UNITS_ARB, "GL_MAX_TEXTURE_IMAGE_UNITS_ARB" }, ++ { (GLenum) 0, NULL } ++ }; ++#endif ++ GLint max[1]; ++ int i; ++ ++#if defined(GL_ARB_vertex_shader) ++ if (target == GL_VERTEX_SHADER_ARB) { ++ printf(" GL_VERTEX_SHADER_ARB:\n"); ++ for (i = 0; vertex_limits[i].token; i++) { ++ glGetIntegerv(vertex_limits[i].token, max); ++ if (glGetError() == GL_NO_ERROR) { ++ printf(" %s = %d\n", vertex_limits[i].name, max[0]); ++ } ++ } ++ } ++#endif ++#if defined(GL_ARB_fragment_shader) ++ if (target == GL_FRAGMENT_SHADER_ARB) { ++ printf(" GL_FRAGMENT_SHADER_ARB:\n"); ++ for (i = 0; fragment_limits[i].token; i++) { ++ glGetIntegerv(fragment_limits[i].token, max); ++ if (glGetError() == GL_NO_ERROR) { ++ printf(" %s = %d\n", fragment_limits[i].name, max[0]); ++ } ++ } ++ } ++#endif ++} ++ ++ ++/** ++ * Print interesting OpenGL implementation limits. ++ */ ++static void ++print_limits(const char *extensions) ++{ ++ struct token_name { ++ GLuint count; ++ GLenum token; ++ const char *name; ++ }; ++ static const struct token_name limits[] = { ++ { 1, GL_MAX_ATTRIB_STACK_DEPTH, "GL_MAX_ATTRIB_STACK_DEPTH" }, ++ { 1, GL_MAX_CLIENT_ATTRIB_STACK_DEPTH, "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH" }, ++ { 1, GL_MAX_CLIP_PLANES, "GL_MAX_CLIP_PLANES" }, ++ { 1, GL_MAX_COLOR_MATRIX_STACK_DEPTH, "GL_MAX_COLOR_MATRIX_STACK_DEPTH" }, ++ { 1, GL_MAX_ELEMENTS_VERTICES, "GL_MAX_ELEMENTS_VERTICES" }, ++ { 1, GL_MAX_ELEMENTS_INDICES, "GL_MAX_ELEMENTS_INDICES" }, ++ { 1, GL_MAX_EVAL_ORDER, "GL_MAX_EVAL_ORDER" }, ++ { 1, GL_MAX_LIGHTS, "GL_MAX_LIGHTS" }, ++ { 1, GL_MAX_LIST_NESTING, "GL_MAX_LIST_NESTING" }, ++ { 1, GL_MAX_MODELVIEW_STACK_DEPTH, "GL_MAX_MODELVIEW_STACK_DEPTH" }, ++ { 1, GL_MAX_NAME_STACK_DEPTH, "GL_MAX_NAME_STACK_DEPTH" }, ++ { 1, GL_MAX_PIXEL_MAP_TABLE, "GL_MAX_PIXEL_MAP_TABLE" }, ++ { 1, GL_MAX_PROJECTION_STACK_DEPTH, "GL_MAX_PROJECTION_STACK_DEPTH" }, ++ { 1, GL_MAX_TEXTURE_STACK_DEPTH, "GL_MAX_TEXTURE_STACK_DEPTH" }, ++ { 1, GL_MAX_TEXTURE_SIZE, "GL_MAX_TEXTURE_SIZE" }, ++ { 1, GL_MAX_3D_TEXTURE_SIZE, "GL_MAX_3D_TEXTURE_SIZE" }, ++ { 2, GL_MAX_VIEWPORT_DIMS, "GL_MAX_VIEWPORT_DIMS" }, ++ { 2, GL_ALIASED_LINE_WIDTH_RANGE, "GL_ALIASED_LINE_WIDTH_RANGE" }, ++ { 2, GL_SMOOTH_LINE_WIDTH_RANGE, "GL_SMOOTH_LINE_WIDTH_RANGE" }, ++ { 2, GL_ALIASED_POINT_SIZE_RANGE, "GL_ALIASED_POINT_SIZE_RANGE" }, ++ { 2, GL_SMOOTH_POINT_SIZE_RANGE, "GL_SMOOTH_POINT_SIZE_RANGE" }, ++#if defined(GL_ARB_texture_cube_map) ++ { 1, GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB, "GL_MAX_CUBE_MAP_TEXTURE_SIZE_ARB" }, ++#endif ++#if defined(GLX_NV_texture_rectangle) ++ { 1, GL_MAX_RECTANGLE_TEXTURE_SIZE_NV, "GL_MAX_RECTANGLE_TEXTURE_SIZE_NV" }, ++#endif ++#if defined(GL_ARB_texture_compression) ++ { 1, GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB, "GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB" }, ++#endif ++#if defined(GL_ARB_multitexture) ++ { 1, GL_MAX_TEXTURE_UNITS_ARB, "GL_MAX_TEXTURE_UNITS_ARB" }, ++#endif ++#if defined(GL_EXT_texture_lod_bias) ++ { 1, GL_MAX_TEXTURE_LOD_BIAS_EXT, "GL_MAX_TEXTURE_LOD_BIAS_EXT" }, ++#endif ++#if defined(GL_EXT_texture_filter_anisotropic) ++ { 1, GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT" }, ++#endif ++#if defined(GL_ARB_draw_buffers) ++ { 1, GL_MAX_DRAW_BUFFERS_ARB, "GL_MAX_DRAW_BUFFERS_ARB" }, ++#endif ++ { 0, (GLenum) 0, NULL } ++ }; ++ GLint i, max[2]; ++ ++ printf("OpenGL limits:\n"); ++ for (i = 0; limits[i].count; i++) { ++ glGetIntegerv(limits[i].token, max); ++ if (glGetError() == GL_NO_ERROR) { ++ if (limits[i].count == 1) ++ printf(" %s = %d\n", limits[i].name, max[0]); ++ else /* XXX fix if we ever query something with more than 2 values */ ++ printf(" %s = %d, %d\n", limits[i].name, max[0], max[1]); ++ } ++ } ++ ++ /* these don't fit into the above mechanism, unfortunately */ ++ glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_WIDTH, max); ++ glGetConvolutionParameteriv(GL_CONVOLUTION_2D, GL_MAX_CONVOLUTION_HEIGHT, max+1); ++ if (glGetError() == GL_NONE) { ++ printf(" GL_MAX_CONVOLUTION_WIDTH/HEIGHT = %d, %d\n", max[0], max[1]); ++ } ++ ++#if defined(GL_ARB_vertex_program) ++ if (strstr(extensions, "GL_ARB_vertex_program")) { ++ print_program_limits(GL_VERTEX_PROGRAM_ARB); ++ } ++#endif ++#if defined(GL_ARB_fragment_program) ++ if (strstr(extensions, "GL_ARB_fragment_program")) { ++ print_program_limits(GL_FRAGMENT_PROGRAM_ARB); ++ } ++#endif ++#if defined(GL_ARB_vertex_shader) ++ if (strstr(extensions, "GL_ARB_vertex_shader")) { ++ print_shader_limits(GL_VERTEX_SHADER_ARB); ++ } ++#endif ++#if defined(GL_ARB_fragment_shader) ++ if (strstr(extensions, "GL_ARB_fragment_shader")) { ++ print_shader_limits(GL_FRAGMENT_SHADER_ARB); ++ } ++#endif ++} ++ ++ ++static void ++print_screen_info(Display *dpy, int scrnum, Bool allowDirect, GLboolean limits) ++{ ++ Window win; ++ int attribSingle[] = { ++ GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ None }; ++ int attribDouble[] = { ++ GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ GLXContext ctx = NULL; ++ XVisualInfo *visinfo; ++ int width = 100, height = 100; ++ ++ root = RootWindow(dpy, scrnum); ++ ++ /* ++ * Find a basic GLX visual. We'll then create a rendering context and ++ * query various info strings. ++ */ ++ visinfo = glXChooseVisual(dpy, scrnum, attribSingle); ++ if (!visinfo) ++ visinfo = glXChooseVisual(dpy, scrnum, attribDouble); ++ ++ if (visinfo) ++ ctx = glXCreateContext( dpy, visinfo, NULL, allowDirect ); ++ ++#ifdef GLX_VERSION_1_3 ++ /* Try glXChooseFBConfig() if glXChooseVisual didn't work. ++ * XXX when would that happen? ++ */ ++ if (!visinfo) { ++ int fbAttribSingle[] = { ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, GL_FALSE, ++ None }; ++ int fbAttribDouble[] = { ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, GL_TRUE, ++ None }; ++ GLXFBConfig *configs = NULL; ++ int nConfigs; ++ ++ configs = glXChooseFBConfig(dpy, scrnum, fbAttribSingle, &nConfigs); ++ if (!configs) ++ configs = glXChooseFBConfig(dpy, scrnum, fbAttribDouble, &nConfigs); ++ ++ if (configs) { ++ visinfo = glXGetVisualFromFBConfig(dpy, configs[0]); ++ ctx = glXCreateNewContext(dpy, configs[0], GLX_RGBA_TYPE, NULL, allowDirect); ++ XFree(configs); ++ } ++ } ++#endif ++ ++ if (!visinfo) { ++ fprintf(stderr, "Error: couldn't find RGB GLX visual or fbconfig\n"); ++ return; ++ } ++ ++ if (!ctx) { ++ fprintf(stderr, "Error: glXCreateContext failed\n"); ++ XFree(visinfo); ++ return; ++ } ++ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap(dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ++ win = XCreateWindow(dpy, root, 0, 0, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr); ++ ++ if (glXMakeCurrent(dpy, win, ctx)) { ++ const char *serverVendor = glXQueryServerString(dpy, scrnum, GLX_VENDOR); ++ const char *serverVersion = glXQueryServerString(dpy, scrnum, GLX_VERSION); ++ const char *serverExtensions = glXQueryServerString(dpy, scrnum, GLX_EXTENSIONS); ++ const char *clientVendor = glXGetClientString(dpy, GLX_VENDOR); ++ const char *clientVersion = glXGetClientString(dpy, GLX_VERSION); ++ const char *clientExtensions = glXGetClientString(dpy, GLX_EXTENSIONS); ++ const char *glxExtensions = glXQueryExtensionsString(dpy, scrnum); ++ const char *glVendor = (const char *) glGetString(GL_VENDOR); ++ const char *glRenderer = (const char *) glGetString(GL_RENDERER); ++ const char *glVersion = (const char *) glGetString(GL_VERSION); ++ const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS); ++ int glxVersionMajor; ++ int glxVersionMinor; ++ char *displayName = NULL; ++ char *colon = NULL, *period = NULL; ++ ++ if (! glXQueryVersion( dpy, & glxVersionMajor, & glxVersionMinor )) { ++ fprintf(stderr, "Error: glXQueryVersion failed\n"); ++ exit(1); ++ } ++ ++ /* Strip the screen number from the display name, if present. */ ++ if (!(displayName = (char *) malloc(strlen(DisplayString(dpy)) + 1))) { ++ fprintf(stderr, "Error: malloc() failed\n"); ++ exit(1); ++ } ++ strcpy(displayName, DisplayString(dpy)); ++ colon = strrchr(displayName, ':'); ++ if (colon) { ++ period = strchr(colon, '.'); ++ if (period) ++ *period = '\0'; ++ } ++ printf("display: %s screen: %d\n", displayName, scrnum); ++ free(displayName); ++ printf("direct rendering: "); ++ if (glXIsDirect(dpy, ctx)) { ++ printf("Yes\n"); ++ } else { ++ if (!allowDirect) { ++ printf("No (-i specified)\n"); ++ } else if (getenv("LIBGL_ALWAYS_INDIRECT")) { ++ printf("No (LIBGL_ALWAYS_INDIRECT set)\n"); ++ } else { ++ printf("No (If you want to find out why, try setting " ++ "LIBGL_DEBUG=verbose)\n"); ++ } ++ } ++ printf("server glx vendor string: %s\n", serverVendor); ++ printf("server glx version string: %s\n", serverVersion); ++ printf("server glx extensions:\n"); ++ print_extension_list(serverExtensions); ++ printf("client glx vendor string: %s\n", clientVendor); ++ printf("client glx version string: %s\n", clientVersion); ++ printf("client glx extensions:\n"); ++ print_extension_list(clientExtensions); ++ printf("GLX version: %u.%u\n", glxVersionMajor, glxVersionMinor); ++ printf("GLX extensions:\n"); ++ print_extension_list(glxExtensions); ++ printf("OpenGL vendor string: %s\n", glVendor); ++ printf("OpenGL renderer string: %s\n", glRenderer); ++ printf("OpenGL version string: %s\n", glVersion); ++#ifdef GL_VERSION_2_0 ++ if (glVersion[0] >= '2' && glVersion[1] == '.') { ++ char *v = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); ++ printf("OpenGL shading language version string: %s\n", v); ++ } ++#endif ++ ++ printf("OpenGL extensions:\n"); ++ print_extension_list(glExtensions); ++ if (limits) ++ print_limits(glExtensions); ++ } ++ else { ++ fprintf(stderr, "Error: glXMakeCurrent failed\n"); ++ } ++ ++ glXDestroyContext(dpy, ctx); ++ XFree(visinfo); ++ XDestroyWindow(dpy, win); ++} ++ ++ ++static const char * ++visual_class_name(int cls) ++{ ++ switch (cls) { ++ case StaticColor: ++ return "StaticColor"; ++ case PseudoColor: ++ return "PseudoColor"; ++ case StaticGray: ++ return "StaticGray"; ++ case GrayScale: ++ return "GrayScale"; ++ case TrueColor: ++ return "TrueColor"; ++ case DirectColor: ++ return "DirectColor"; ++ default: ++ return ""; ++ } ++} ++ ++ ++static const char * ++visual_class_abbrev(int cls) ++{ ++ switch (cls) { ++ case StaticColor: ++ return "sc"; ++ case PseudoColor: ++ return "pc"; ++ case StaticGray: ++ return "sg"; ++ case GrayScale: ++ return "gs"; ++ case TrueColor: ++ return "tc"; ++ case DirectColor: ++ return "dc"; ++ default: ++ return ""; ++ } ++} ++ ++static const char * ++visual_render_type_name(int type) ++{ ++ switch (type) { ++ case GLX_RGBA_BIT: ++ return "rgba"; ++ case GLX_COLOR_INDEX_BIT: ++ return "ci"; ++ case GLX_RGBA_BIT | GLX_COLOR_INDEX_BIT: ++ return "rgba|ci"; ++ default: ++ return ""; ++ } ++} ++ ++static GLboolean ++get_visual_attribs(Display *dpy, XVisualInfo *vInfo, ++ struct visual_attribs *attribs) ++{ ++ const char *ext = glXQueryExtensionsString(dpy, vInfo->screen); ++ int rgba; ++ ++ memset(attribs, 0, sizeof(struct visual_attribs)); ++ ++ attribs->id = vInfo->visualid; ++#if defined(__cplusplus) || defined(c_plusplus) ++ attribs->klass = vInfo->c_class; ++#else ++ attribs->klass = vInfo->class; ++#endif ++ attribs->depth = vInfo->depth; ++ attribs->redMask = vInfo->red_mask; ++ attribs->greenMask = vInfo->green_mask; ++ attribs->blueMask = vInfo->blue_mask; ++ attribs->colormapSize = vInfo->colormap_size; ++ attribs->bitsPerRGB = vInfo->bits_per_rgb; ++ ++ if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 || ++ !attribs->supportsGL) ++ return GL_FALSE; ++ glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize); ++ glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level); ++ glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba); ++ if (rgba) ++ attribs->render_type = GLX_RGBA_BIT; ++ else ++ attribs->render_type = GLX_COLOR_INDEX_BIT; ++ ++ glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); ++ glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo); ++ glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers); ++ glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize); ++ glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize); ++ glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize); ++ glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize); ++ glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize); ++ glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize); ++ glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); ++ glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); ++ glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); ++ glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); ++ ++ /* get transparent pixel stuff */ ++ glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType); ++ if (attribs->transparentType == GLX_TRANSPARENT_RGB) { ++ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); ++ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); ++ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); ++ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); ++ } ++ else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { ++ glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); ++ } ++ ++ /* multisample attribs */ ++#ifdef GLX_ARB_multisample ++ if (ext && strstr(ext, "GLX_ARB_multisample")) { ++ glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample); ++ glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples); ++ } ++#endif ++ else { ++ attribs->numSamples = 0; ++ attribs->numMultisample = 0; ++ } ++ ++#if defined(GLX_EXT_visual_rating) ++ if (ext && strstr(ext, "GLX_EXT_visual_rating")) { ++ glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat); ++ } ++ else { ++ attribs->visualCaveat = GLX_NONE_EXT; ++ } ++#else ++ attribs->visualCaveat = 0; ++#endif ++ ++ return GL_TRUE; ++} ++ ++#ifdef GLX_VERSION_1_3 ++ ++static int ++glx_token_to_visual_class(int visual_type) ++{ ++ switch (visual_type) { ++ case GLX_TRUE_COLOR: ++ return TrueColor; ++ case GLX_DIRECT_COLOR: ++ return DirectColor; ++ case GLX_PSEUDO_COLOR: ++ return PseudoColor; ++ case GLX_STATIC_COLOR: ++ return StaticColor; ++ case GLX_GRAY_SCALE: ++ return GrayScale; ++ case GLX_STATIC_GRAY: ++ return StaticGray; ++ case GLX_NONE: ++ default: ++ return None; ++ } ++} ++ ++static GLboolean ++get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig, ++ struct visual_attribs *attribs) ++{ ++ int visual_type; ++ ++ memset(attribs, 0, sizeof(struct visual_attribs)); ++ ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &attribs->id); ++ ++#if 0 ++ attribs->depth = vInfo->depth; ++ attribs->redMask = vInfo->red_mask; ++ attribs->greenMask = vInfo->green_mask; ++ attribs->blueMask = vInfo->blue_mask; ++ attribs->colormapSize = vInfo->colormap_size; ++ attribs->bitsPerRGB = vInfo->bits_per_rgb; ++#endif ++ ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type); ++ attribs->klass = glx_token_to_visual_class(visual_type); ++ ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers); ++ ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize); ++ ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); ++ ++ /* get transparent pixel stuff */ ++ glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType); ++ if (attribs->transparentType == GLX_TRANSPARENT_RGB) { ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); ++ } ++ else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); ++ } ++ ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples); ++ glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat); ++ ++ return GL_TRUE; ++} ++ ++#endif ++ ++ ++ ++static void ++print_visual_attribs_verbose(const struct visual_attribs *attribs) ++{ ++ printf("Visual ID: %x depth=%d class=%s\n", ++ attribs->id, attribs->depth, visual_class_name(attribs->klass)); ++ printf(" bufferSize=%d level=%d renderType=%s doubleBuffer=%d stereo=%d\n", ++ attribs->bufferSize, attribs->level, ++ visual_render_type_name(attribs->render_type), ++ attribs->doubleBuffer, attribs->stereo); ++ printf(" rgba: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", ++ attribs->redSize, attribs->greenSize, ++ attribs->blueSize, attribs->alphaSize); ++ printf(" auxBuffers=%d depthSize=%d stencilSize=%d\n", ++ attribs->auxBuffers, attribs->depthSize, attribs->stencilSize); ++ printf(" accum: redSize=%d greenSize=%d blueSize=%d alphaSize=%d\n", ++ attribs->accumRedSize, attribs->accumGreenSize, ++ attribs->accumBlueSize, attribs->accumAlphaSize); ++ printf(" multiSample=%d multiSampleBuffers=%d\n", ++ attribs->numSamples, attribs->numMultisample); ++#ifdef GLX_EXT_visual_rating ++ if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0) ++ printf(" visualCaveat=None\n"); ++ else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT) ++ printf(" visualCaveat=Slow\n"); ++ else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT) ++ printf(" visualCaveat=Nonconformant\n"); ++#endif ++ if (attribs->transparentType == GLX_NONE) { ++ printf(" Opaque.\n"); ++ } ++ else if (attribs->transparentType == GLX_TRANSPARENT_RGB) { ++ printf(" Transparent RGB: Red=%d Green=%d Blue=%d Alpha=%d\n",attribs->transparentRedValue,attribs->transparentGreenValue,attribs->transparentBlueValue,attribs->transparentAlphaValue); ++ } ++ else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { ++ printf(" Transparent index=%d\n",attribs->transparentIndexValue); ++ } ++} ++ ++ ++static void ++print_visual_attribs_short_header(void) ++{ ++ printf(" visual x bf lv rg d st colorbuffer ax dp st accumbuffer ms cav\n"); ++ printf(" id dep cl sp sz l ci b ro r g b a bf th cl r g b a ns b eat\n"); ++ printf("----------------------------------------------------------------------\n"); ++} ++ ++ ++static void ++print_visual_attribs_short(const struct visual_attribs *attribs) ++{ ++ char *caveat = NULL; ++#ifdef GLX_EXT_visual_rating ++ if (attribs->visualCaveat == GLX_NONE_EXT || attribs->visualCaveat == 0) ++ caveat = "None"; ++ else if (attribs->visualCaveat == GLX_SLOW_VISUAL_EXT) ++ caveat = "Slow"; ++ else if (attribs->visualCaveat == GLX_NON_CONFORMANT_VISUAL_EXT) ++ caveat = "Ncon"; ++ else ++ caveat = "None"; ++#else ++ caveat = "None"; ++#endif ++ ++ printf("0x%02x %2d %2s %2d %2d %2d %c%c %c %c %2d %2d %2d %2d %2d %2d %2d", ++ attribs->id, ++ attribs->depth, ++ visual_class_abbrev(attribs->klass), ++ attribs->transparentType != GLX_NONE, ++ attribs->bufferSize, ++ attribs->level, ++ (attribs->render_type & GLX_RGBA_BIT) ? 'r' : ' ', ++ (attribs->render_type & GLX_COLOR_INDEX_BIT) ? 'c' : ' ', ++ attribs->doubleBuffer ? 'y' : '.', ++ attribs->stereo ? 'y' : '.', ++ attribs->redSize, attribs->greenSize, ++ attribs->blueSize, attribs->alphaSize, ++ attribs->auxBuffers, ++ attribs->depthSize, ++ attribs->stencilSize ++ ); ++ ++ printf(" %2d %2d %2d %2d %2d %1d %s\n", ++ attribs->accumRedSize, attribs->accumGreenSize, ++ attribs->accumBlueSize, attribs->accumAlphaSize, ++ attribs->numSamples, attribs->numMultisample, ++ caveat ++ ); ++} ++ ++ ++static void ++print_visual_attribs_long_header(void) ++{ ++ printf("Vis Vis Visual Trans buff lev render DB ste r g b a aux dep ste accum buffers MS MS\n"); ++ printf(" ID Depth Type parent size el type reo sz sz sz sz buf th ncl r g b a num bufs\n"); ++ printf("----------------------------------------------------------------------------------------------------\n"); ++} ++ ++ ++static void ++print_visual_attribs_long(const struct visual_attribs *attribs) ++{ ++ printf("0x%2x %2d %-11s %2d %2d %2d %4s %3d %3d %3d %3d %3d %3d", ++ attribs->id, ++ attribs->depth, ++ visual_class_name(attribs->klass), ++ attribs->transparentType != GLX_NONE, ++ attribs->bufferSize, ++ attribs->level, ++ visual_render_type_name(attribs->render_type), ++ attribs->doubleBuffer, ++ attribs->stereo, ++ attribs->redSize, attribs->greenSize, ++ attribs->blueSize, attribs->alphaSize ++ ); ++ ++ printf(" %3d %4d %2d %3d %3d %3d %3d %2d %2d\n", ++ attribs->auxBuffers, ++ attribs->depthSize, ++ attribs->stencilSize, ++ attribs->accumRedSize, attribs->accumGreenSize, ++ attribs->accumBlueSize, attribs->accumAlphaSize, ++ attribs->numSamples, attribs->numMultisample ++ ); ++} ++ ++ ++static void ++print_visual_info(Display *dpy, int scrnum, InfoMode mode) ++{ ++ XVisualInfo theTemplate; ++ XVisualInfo *visuals; ++ int numVisuals, numGlxVisuals; ++ long mask; ++ int i; ++ struct visual_attribs attribs; ++ ++ /* get list of all visuals on this screen */ ++ theTemplate.screen = scrnum; ++ mask = VisualScreenMask; ++ visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals); ++ ++ numGlxVisuals = 0; ++ for (i = 0; i < numVisuals; i++) { ++ if (get_visual_attribs(dpy, &visuals[i], &attribs)) ++ numGlxVisuals++; ++ } ++ ++ if (numGlxVisuals == 0) ++ return; ++ ++ printf("%d GLX Visuals\n", numGlxVisuals); ++ ++ if (mode == Normal) ++ print_visual_attribs_short_header(); ++ else if (mode == Wide) ++ print_visual_attribs_long_header(); ++ ++ for (i = 0; i < numVisuals; i++) { ++ if (!get_visual_attribs(dpy, &visuals[i], &attribs)) ++ continue; ++ ++ if (mode == Verbose) ++ print_visual_attribs_verbose(&attribs); ++ else if (mode == Normal) ++ print_visual_attribs_short(&attribs); ++ else if (mode == Wide) ++ print_visual_attribs_long(&attribs); ++ } ++ printf("\n"); ++ ++ XFree(visuals); ++} ++ ++#ifdef GLX_VERSION_1_3 ++ ++static void ++print_fbconfig_info(Display *dpy, int scrnum, InfoMode mode) ++{ ++ int numFBConfigs = 0; ++ struct visual_attribs attribs; ++ GLXFBConfig *fbconfigs; ++ int i; ++ ++ /* get list of all fbconfigs on this screen */ ++ fbconfigs = glXGetFBConfigs(dpy, scrnum, &numFBConfigs); ++ ++ if (numFBConfigs == 0) { ++ XFree(fbconfigs); ++ return; ++ } ++ ++ printf("%d GLXFBConfigs:\n", numFBConfigs); ++ if (mode == Normal) ++ print_visual_attribs_short_header(); ++ else if (mode == Wide) ++ print_visual_attribs_long_header(); ++ ++ for (i = 0; i < numFBConfigs; i++) { ++ get_fbconfig_attribs(dpy, fbconfigs[i], &attribs); ++ ++ if (mode == Verbose) ++ print_visual_attribs_verbose(&attribs); ++ else if (mode == Normal) ++ print_visual_attribs_short(&attribs); ++ else if (mode == Wide) ++ print_visual_attribs_long(&attribs); ++ } ++ printf("\n"); ++ ++ XFree(fbconfigs); ++} ++ ++#endif ++ ++/* ++ * Stand-alone Mesa doesn't really implement the GLX protocol so it ++ * doesn't really know the GLX attributes associated with an X visual. ++ * The first time a visual is presented to Mesa's pseudo-GLX it ++ * attaches ancilliary buffers to it (like depth and stencil). ++ * But that usually only works if glXChooseVisual is used. ++ * This function calls glXChooseVisual() to sort of "prime the pump" ++ * for Mesa's GLX so that the visuals that get reported actually ++ * reflect what applications will see. ++ * This has no effect when using true GLX. ++ */ ++static void ++mesa_hack(Display *dpy, int scrnum) ++{ ++ static int attribs[] = { ++ GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DEPTH_SIZE, 1, ++ GLX_STENCIL_SIZE, 1, ++ GLX_ACCUM_RED_SIZE, 1, ++ GLX_ACCUM_GREEN_SIZE, 1, ++ GLX_ACCUM_BLUE_SIZE, 1, ++ GLX_ACCUM_ALPHA_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None ++ }; ++ XVisualInfo *visinfo; ++ ++ visinfo = glXChooseVisual(dpy, scrnum, attribs); ++ if (visinfo) ++ XFree(visinfo); ++} ++ ++ ++/* ++ * Examine all visuals to find the so-called best one. ++ * We prefer deepest RGBA buffer with depth, stencil and accum ++ * that has no caveats. ++ */ ++static int ++find_best_visual(Display *dpy, int scrnum) ++{ ++ XVisualInfo theTemplate; ++ XVisualInfo *visuals; ++ int numVisuals; ++ long mask; ++ int i; ++ struct visual_attribs bestVis; ++ ++ /* get list of all visuals on this screen */ ++ theTemplate.screen = scrnum; ++ mask = VisualScreenMask; ++ visuals = XGetVisualInfo(dpy, mask, &theTemplate, &numVisuals); ++ ++ /* init bestVis with first visual info */ ++ get_visual_attribs(dpy, &visuals[0], &bestVis); ++ ++ /* try to find a "better" visual */ ++ for (i = 1; i < numVisuals; i++) { ++ struct visual_attribs vis; ++ ++ get_visual_attribs(dpy, &visuals[i], &vis); ++ ++ /* always skip visuals with caveats */ ++ if (vis.visualCaveat != GLX_NONE_EXT) ++ continue; ++ ++ /* see if this vis is better than bestVis */ ++ if ((!bestVis.supportsGL && vis.supportsGL) || ++ (bestVis.visualCaveat != GLX_NONE_EXT) || ++ (!(bestVis.render_type & GLX_RGBA_BIT) && (vis.render_type & GLX_RGBA_BIT)) || ++ (!bestVis.doubleBuffer && vis.doubleBuffer) || ++ (bestVis.redSize < vis.redSize) || ++ (bestVis.greenSize < vis.greenSize) || ++ (bestVis.blueSize < vis.blueSize) || ++ (bestVis.alphaSize < vis.alphaSize) || ++ (bestVis.depthSize < vis.depthSize) || ++ (bestVis.stencilSize < vis.stencilSize) || ++ (bestVis.accumRedSize < vis.accumRedSize)) { ++ /* found a better visual */ ++ bestVis = vis; ++ } ++ } ++ ++ XFree(visuals); ++ ++ return bestVis.id; ++} ++ ++ ++static void ++usage(void) ++{ ++ printf("Usage: glxinfo [-v] [-t] [-h] [-i] [-b] [-display ]\n"); ++ printf("\t-v: Print visuals info in verbose form.\n"); ++ printf("\t-t: Print verbose table.\n"); ++ printf("\t-display : Print GLX visuals on specified server.\n"); ++ printf("\t-h: This information.\n"); ++ printf("\t-i: Force an indirect rendering context.\n"); ++ printf("\t-b: Find the 'best' visual and print its number.\n"); ++ printf("\t-l: Print interesting OpenGL limits.\n"); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ char *displayName = NULL; ++ Display *dpy; ++ int numScreens, scrnum; ++ InfoMode mode = Normal; ++ GLboolean findBest = GL_FALSE; ++ GLboolean limits = GL_FALSE; ++ Bool allowDirect = True; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) { ++ displayName = argv[i + 1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-t") == 0) { ++ mode = Wide; ++ } ++ else if (strcmp(argv[i], "-v") == 0) { ++ mode = Verbose; ++ } ++ else if (strcmp(argv[i], "-b") == 0) { ++ findBest = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-i") == 0) { ++ allowDirect = False; ++ } ++ else if (strcmp(argv[i], "-l") == 0) { ++ limits = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-h") == 0) { ++ usage(); ++ return 0; ++ } ++ else { ++ printf("Unknown option `%s'\n", argv[i]); ++ usage(); ++ return 0; ++ } ++ } ++ ++ dpy = XOpenDisplay(displayName); ++ if (!dpy) { ++ fprintf(stderr, "Error: unable to open display %s\n", XDisplayName(displayName)); ++ return -1; ++ } ++ ++ if (findBest) { ++ int b; ++ mesa_hack(dpy, 0); ++ b = find_best_visual(dpy, 0); ++ printf("%d\n", b); ++ } ++ else { ++ numScreens = ScreenCount(dpy); ++ print_display_info(dpy); ++ for (scrnum = 0; scrnum < numScreens; scrnum++) { ++ mesa_hack(dpy, scrnum); ++ print_screen_info(dpy, scrnum, allowDirect, limits); ++ printf("\n"); ++ print_visual_info(dpy, scrnum, mode); ++#ifdef GLX_VERSION_1_3 ++ print_fbconfig_info(dpy, scrnum, mode); ++#endif ++ if (scrnum + 1 < numScreens) ++ printf("\n\n"); ++ } ++ } ++ ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxpbdemo.c Mesa-7.8.1.patched/progs/xdemos/glxpbdemo.c +--- Mesa-7.8.1/progs/xdemos/glxpbdemo.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxpbdemo.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,431 @@ ++ ++/* ++ * This program demonstrates how to do "off-screen" rendering using ++ * the GLX pixel buffer extension. ++ * ++ * Written by Brian Paul for the "OpenGL and Window System Integration" ++ * course presented at SIGGRAPH '97. Updated on 5 October 2002. ++ * ++ * Updated on 31 January 2004 to use native GLX by ++ * Andrew P. Lentvorski, Jr. ++ * ++ * Usage: ++ * glxpbdemo width height imgfile ++ * Where: ++ * width is the width, in pixels, of the image to generate. ++ * height is the height, in pixels, of the image to generate. ++ * imgfile is the name of the PPM image file to write. ++ * ++ * ++ * This demo draws 3-D boxes with random orientation. ++ * ++ * On machines such as the SGI Indigo you may have to reconfigure your ++ * display/X server to enable pbuffers. Look in the /usr/gfx/ucode/MGRAS/vof/ ++ * directory for display configurations with the _pbuf suffix. Use ++ * setmon -x to configure your X server and display for pbuffers. ++ * ++ * O2 systems seem to support pbuffers well. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++/* Some ugly global vars */ ++static GLXFBConfig gFBconfig = 0; ++static Display *gDpy = NULL; ++static int gScreen = 0; ++static GLXPbuffer gPBuffer = 0; ++static int gWidth, gHeight; ++ ++ ++/* ++ * Test for appropriate version of GLX to run this program ++ * Input: dpy - the X display ++ * screen - screen number ++ * Return: 0 = GLX not available. ++ * 1 = GLX available. ++ */ ++static int ++RuntimeQueryGLXVersion(Display *dpy, int screen) ++{ ++#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4) ++ char *glxversion; ++ ++ glxversion = (char *) glXGetClientString(dpy, GLX_VERSION); ++ if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4"))) ++ return 0; ++ ++ glxversion = (char *) glXQueryServerString(dpy, screen, GLX_VERSION); ++ if (!(strstr(glxversion, "1.3") || strstr(glxversion, "1.4"))) ++ return 0; ++ ++ return 1; ++#else ++ return 0; ++#endif ++} ++ ++ ++ ++/* ++ * Create the pbuffer and return a GLXPbuffer handle. ++ */ ++static GLXPbuffer ++MakePbuffer( Display *dpy, int screen, int width, int height ) ++{ ++ GLXFBConfig *fbConfigs; ++ GLXFBConfig chosenFBConfig; ++ GLXPbuffer pBuffer = None; ++ ++ int nConfigs; ++ int fbconfigid; ++ ++ int fbAttribs[] = { ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_DEPTH_SIZE, 1, ++ GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT | GLX_PBUFFER_BIT, ++ None ++ }; ++ ++ int pbAttribs[] = { ++ GLX_PBUFFER_WIDTH, 0, ++ GLX_PBUFFER_HEIGHT, 0, ++ GLX_LARGEST_PBUFFER, False, ++ GLX_PRESERVED_CONTENTS, False, ++ None ++ }; ++ ++ pbAttribs[1] = width; ++ pbAttribs[3] = height; ++ ++ fbConfigs = glXChooseFBConfig(dpy, screen, fbAttribs, &nConfigs); ++ ++ if (0 == nConfigs || !fbConfigs) { ++ printf("Error: glxChooseFBConfig failed\n"); ++ XFree(fbConfigs); ++ XCloseDisplay(dpy); ++ return 0; ++ } ++ ++ chosenFBConfig = fbConfigs[0]; ++ ++ glXGetFBConfigAttrib(dpy, chosenFBConfig, GLX_FBCONFIG_ID, &fbconfigid); ++ printf("Chose 0x%x as fbconfigid\n", fbconfigid); ++ ++ /* Create the pbuffer using first fbConfig in the list that works. */ ++ pBuffer = glXCreatePbuffer(dpy, chosenFBConfig, pbAttribs); ++ ++ if (pBuffer) { ++ gFBconfig = chosenFBConfig; ++ gWidth = width; ++ gHeight = height; ++ } ++ ++ XFree(fbConfigs); ++ ++ return pBuffer; ++} ++ ++ ++ ++/* ++ * Do all the X / GLX setup stuff. ++ */ ++static int ++Setup(int width, int height) ++{ ++#if defined(GLX_VERSION_1_3) || defined(GLX_VERSION_1_4) ++ GLXContext glCtx; ++ ++ /* Open the X display */ ++ gDpy = XOpenDisplay(NULL); ++ if (!gDpy) { ++ printf("Error: couldn't open default X display.\n"); ++ return 0; ++ } ++ ++ /* Get default screen */ ++ gScreen = DefaultScreen(gDpy); ++ ++ /* Test that GLX is available */ ++ if (!RuntimeQueryGLXVersion(gDpy, gScreen)) { ++ printf("Error: GLX 1.3 or 1.4 not available\n"); ++ XCloseDisplay(gDpy); ++ return 0; ++ } ++ ++ /* Create Pbuffer */ ++ gPBuffer = MakePbuffer( gDpy, gScreen, width, height ); ++ if (gPBuffer==None) { ++ printf("Error: couldn't create pbuffer\n"); ++ XCloseDisplay(gDpy); ++ return 0; ++ } ++ ++ /* Create GLX context */ ++ glCtx = glXCreateNewContext(gDpy, gFBconfig, GLX_RGBA_TYPE, NULL, True); ++ if (glCtx) { ++ if (!glXIsDirect(gDpy, glCtx)) { ++ printf("Warning: using indirect GLXContext\n"); ++ } ++ } ++ else { ++ printf("Error: Couldn't create GLXContext\n"); ++ XCloseDisplay(gDpy); ++ return 0; ++ } ++ ++ /* Bind context to pbuffer */ ++ if (!glXMakeCurrent(gDpy, gPBuffer, glCtx)) { ++ printf("Error: glXMakeCurrent failed\n"); ++ XCloseDisplay(gDpy); ++ return 0; ++ } ++ ++ return 1; /* Success!! */ ++#else ++ printf("Error: GLX version 1.3 or 1.4 not available at compile time\n"); ++ return 0; ++#endif ++} ++ ++ ++ ++/* One-time GL setup */ ++static void ++InitGL(void) ++{ ++ static GLfloat pos[4] = {0.0, 0.0, 10.0, 0.0}; ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_NORMALIZE); ++ glEnable(GL_DEPTH_TEST); ++ glEnable(GL_CULL_FACE); ++ ++ glViewport(0, 0, gWidth, gHeight); ++ glMatrixMode( GL_PROJECTION ); ++ glLoadIdentity(); ++ glFrustum( -1.0, 1.0, -1.0, 1.0, 5.0, 25.0 ); ++ glMatrixMode( GL_MODELVIEW ); ++ glLoadIdentity(); ++ glTranslatef( 0.0, 0.0, -15.0 ); ++ ++} ++ ++ ++/* Return random float in [0,1] */ ++static float ++Random(void) ++{ ++ int i = rand(); ++ return (float) (i % 1000) / 1000.0; ++} ++ ++ ++static void ++RandomColor(void) ++{ ++ GLfloat c[4]; ++ c[0] = Random(); ++ c[1] = Random(); ++ c[2] = Random(); ++ c[3] = 1.0; ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, c); ++} ++ ++ ++/* This function borrowed from Mark Kilgard's GLUT */ ++static void ++drawBox(GLfloat x0, GLfloat x1, GLfloat y0, GLfloat y1, ++ GLfloat z0, GLfloat z1, GLenum type) ++{ ++ static GLfloat n[6][3] = ++ { ++ {-1.0, 0.0, 0.0}, ++ {0.0, 1.0, 0.0}, ++ {1.0, 0.0, 0.0}, ++ {0.0, -1.0, 0.0}, ++ {0.0, 0.0, 1.0}, ++ {0.0, 0.0, -1.0} ++ }; ++ static GLint faces[6][4] = ++ { ++ {0, 1, 2, 3}, ++ {3, 2, 6, 7}, ++ {7, 6, 5, 4}, ++ {4, 5, 1, 0}, ++ {5, 6, 2, 1}, ++ {7, 4, 0, 3} ++ }; ++ GLfloat v[8][3], tmp; ++ GLint i; ++ ++ if (x0 > x1) { ++ tmp = x0; ++ x0 = x1; ++ x1 = tmp; ++ } ++ if (y0 > y1) { ++ tmp = y0; ++ y0 = y1; ++ y1 = tmp; ++ } ++ if (z0 > z1) { ++ tmp = z0; ++ z0 = z1; ++ z1 = tmp; ++ } ++ v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0; ++ v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1; ++ v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0; ++ v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1; ++ v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0; ++ v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1; ++ ++ for (i = 0; i < 6; i++) { ++ glBegin(type); ++ glNormal3fv(&n[i][0]); ++ glVertex3fv(&v[faces[i][0]][0]); ++ glVertex3fv(&v[faces[i][1]][0]); ++ glVertex3fv(&v[faces[i][2]][0]); ++ glVertex3fv(&v[faces[i][3]][0]); ++ glEnd(); ++ } ++} ++ ++ ++ ++/* Render a scene */ ++static void ++Render(void) ++{ ++ int NumBoxes = 100; ++ int i; ++ ++ InitGL(); ++ glClearColor(0.2, 0.2, 0.9, 0.0); ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ for (i=0;i ++#define GLX_GLXEXT_PROTOTYPES ++#include ++#include ++#include ++#include ++ ++ ++static GLXContext ctx; ++static XVisualInfo *visinfo; ++static GC gc; ++ ++ ++ ++static Window make_rgb_window( Display *dpy, ++ unsigned int width, unsigned int height ) ++{ ++ const int sbAttrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ None }; ++ const int dbAttrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, (int *) sbAttrib ); ++ if (!visinfo) { ++ visinfo = glXChooseVisual( dpy, scrnum, (int *) dbAttrib ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB visual\n"); ++ exit(1); ++ } ++ } ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ /* TODO: share root colormap if possible */ ++ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; ++ ++ win = XCreateWindow( dpy, root, 0, 0, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* make an X GC so we can do XCopyArea later */ ++ gc = XCreateGC( dpy, win, 0, NULL ); ++ ++ /* need indirect context */ ++ ctx = glXCreateContext( dpy, visinfo, NULL, False ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(-1); ++ } ++ ++ printf("Direct rendering: %s\n", glXIsDirect(dpy, ctx) ? "Yes" : "No"); ++ ++ return win; ++} ++ ++ ++static GLXPixmap make_pixmap( Display *dpy, Window win, ++ unsigned int width, unsigned int height, ++ Pixmap *pixmap) ++{ ++ Pixmap pm; ++ GLXPixmap glxpm; ++ XWindowAttributes attr; ++ ++ pm = XCreatePixmap( dpy, win, width, height, visinfo->depth ); ++ if (!pm) { ++ printf("Error: XCreatePixmap failed\n"); ++ exit(-1); ++ } ++ ++ XGetWindowAttributes( dpy, win, &attr ); ++ ++ /* ++ * IMPORTANT: ++ * Use the glXCreateGLXPixmapMESA funtion when using Mesa because ++ * Mesa needs to know the colormap associated with a pixmap in order ++ * to render correctly. This is because Mesa allows RGB rendering ++ * into any kind of visual, not just TrueColor or DirectColor. ++ */ ++#ifdef GLX_MESA_pixmap_colormap ++ if (strstr(glXQueryExtensionsString(dpy, 0), "GLX_MESA_pixmap_colormap")) { ++ /* stand-alone Mesa, specify the colormap */ ++ glxpm = glXCreateGLXPixmapMESA( dpy, visinfo, pm, attr.colormap ); ++ } ++ else { ++ glxpm = glXCreateGLXPixmap( dpy, visinfo, pm ); ++ } ++#else ++ /* This will work with Mesa too if the visual is TrueColor or DirectColor */ ++ glxpm = glXCreateGLXPixmap( dpy, visinfo, pm ); ++#endif ++ ++ if (!glxpm) { ++ printf("Error: GLXCreateGLXPixmap failed\n"); ++ exit(-1); ++ } ++ ++ *pixmap = pm; ++ ++ return glxpm; ++} ++ ++ ++ ++static void event_loop( Display *dpy, GLXPixmap pm ) ++{ ++ XEvent event; ++ ++ while (1) { ++ XNextEvent( dpy, &event ); ++ ++ switch (event.type) { ++ case Expose: ++ printf("Redraw\n"); ++ /* copy the image from GLXPixmap to window */ ++ XCopyArea( dpy, pm, event.xany.window, /* src, dest */ ++ gc, 0, 0, 300, 300, /* gc, src pos, size */ ++ 0, 0 ); /* dest pos */ ++ break; ++ case ConfigureNotify: ++ /* nothing */ ++ break; ++ } ++ } ++} ++ ++ ++ ++int main( int argc, char *argv[] ) ++{ ++ Display *dpy; ++ Window win; ++ Pixmap pm; ++ GLXPixmap glxpm; ++ ++ dpy = XOpenDisplay(NULL); ++ ++ win = make_rgb_window( dpy, 300, 300 ); ++ glxpm = make_pixmap( dpy, win, 300, 300, &pm ); ++ ++ glXMakeCurrent( dpy, glxpm, ctx ); ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ ++ /* Render an image into the pixmap */ ++ glShadeModel( GL_FLAT ); ++ glClearColor( 0.5, 0.5, 0.5, 1.0 ); ++ glClear( GL_COLOR_BUFFER_BIT ); ++ glViewport( 0, 0, 300, 300 ); ++ glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ); ++ glColor3f( 0.0, 1.0, 1.0 ); ++ glRectf( -0.75, -0.75, 0.75, 0.75 ); ++ glFlush(); ++ glXWaitGL(); ++ ++ XMapWindow( dpy, win ); ++ ++ event_loop( dpy, pm ); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxsnoop.c Mesa-7.8.1.patched/progs/xdemos/glxsnoop.c +--- Mesa-7.8.1/progs/xdemos/glxsnoop.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxsnoop.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,377 @@ ++/** ++ * Display/snoop the z/stencil/back/front buffers of another app's window. ++ * Also, an example of the need for shared ancillary renderbuffers. ++ * ++ * Hint: use 'xwininfo' to get a window's ID. ++ * ++ * Brian Paul ++ * 11 Oct 2007 ++ */ ++ ++#define GL_GLEXT_PROTOTYPES ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define Z_BUFFER 1 ++#define STENCIL_BUFFER 2 ++#define BACK_BUFFER 3 ++#define FRONT_BUFFER 4 ++ ++ ++static int Buffer = BACK_BUFFER; ++static int WindowID = 0; ++static const char *DisplayName = NULL; ++static GLXContext Context = 0; ++static int Width, Height; ++ ++ ++/** ++ * Grab the z/stencil/back/front image from the srcWin and display it ++ * (possibly converted to grayscale) in the dstWin. ++ */ ++static void ++redraw(Display *dpy, Window srcWin, Window dstWin ) ++{ ++ GLubyte *image = malloc(Width * Height * 4); ++ ++ glXMakeCurrent(dpy, srcWin, Context); ++ glPixelStorei(GL_PACK_ALIGNMENT, 1); ++ if (Buffer == BACK_BUFFER) { ++ glReadBuffer(GL_BACK); ++ glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); ++ } ++ else if (Buffer == FRONT_BUFFER) { ++ glReadBuffer(GL_FRONT); ++ glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); ++ } ++ else if (Buffer == Z_BUFFER) { ++ GLfloat *z = malloc(Width * Height * sizeof(GLfloat)); ++ int i; ++ glReadPixels(0, 0, Width, Height, GL_DEPTH_COMPONENT, GL_FLOAT, z); ++ for (i = 0; i < Width * Height; i++) { ++ image[i*4+0] = ++ image[i*4+1] = ++ image[i*4+2] = (GLint) (255.0 * z[i]); ++ image[i*4+3] = 255; ++ } ++ free(z); ++ } ++ else if (Buffer == STENCIL_BUFFER) { ++ GLubyte *sten = malloc(Width * Height * sizeof(GLubyte)); ++ int i, min = 100, max = -1; ++ float step; ++ int sz; ++ glGetIntegerv(GL_STENCIL_BITS, &sz); ++ glReadPixels(0, 0, Width, Height, ++ GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, sten); ++ /* find min/max for converting stencil to grayscale */ ++ for (i = 0; i < Width * Height; i++) { ++ if (sten[i] < min) ++ min = sten[i]; ++ if (sten[i] > max) ++ max = sten[i]; ++ } ++ if (min == max) ++ step = 0; ++ else ++ step = 255.0 / (float) (max - min); ++ for (i = 0; i < Width * Height; i++) { ++ image[i*4+0] = ++ image[i*4+1] = ++ image[i*4+2] = (GLint) ((sten[i] - min) * step); ++ image[i*4+3] = 255; ++ } ++ free(sten); ++ } ++ ++ glXMakeCurrent(dpy, dstWin, Context); ++ glWindowPos2iARB(0, 0); ++ glDrawBuffer(GL_FRONT); ++ glDrawPixels(Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, image); ++ glFlush(); ++ ++ free(image); ++} ++ ++ ++static void ++set_window_title(Display *dpy, Window win, const char *title) ++{ ++ XSizeHints sizehints; ++ sizehints.flags = 0; ++ XSetStandardProperties(dpy, win, title, title, ++ None, (char **)NULL, 0, &sizehints); ++} ++ ++ ++static Window ++make_gl_window(Display *dpy, XVisualInfo *visinfo, int width, int height) ++{ ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ int x = 0, y = 0; ++ char *name = NULL; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ /* 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, x, y, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ return win; ++} ++ ++ ++static void ++update_window_title(Display *dpy, Window win) ++{ ++ char title[1000], *buf; ++ ++ switch (Buffer) { ++ case Z_BUFFER: ++ buf = "Z"; ++ break; ++ case STENCIL_BUFFER: ++ buf = "Stencil"; ++ break; ++ case BACK_BUFFER: ++ buf = "Back"; ++ break; ++ case FRONT_BUFFER: ++ buf = "Front"; ++ break; ++ default: ++ buf = ""; ++ } ++ ++ sprintf(title, "glxsnoop window 0x%x (%s buffer)", (int) WindowID, buf); ++ ++ set_window_title(dpy, win, title); ++} ++ ++ ++static void ++keypress(Display *dpy, Window win, char key) ++{ ++ switch (key) { ++ case 27: ++ /* escape */ ++ exit(0); ++ break; ++ case 's': ++ Buffer = STENCIL_BUFFER; ++ break; ++ case 'z': ++ Buffer = Z_BUFFER; ++ break; ++ case 'f': ++ Buffer = FRONT_BUFFER; ++ break; ++ case 'b': ++ Buffer = BACK_BUFFER; ++ break; ++ default: ++ return; ++ } ++ ++ update_window_title(dpy, win); ++ redraw(dpy, WindowID, win); ++} ++ ++ ++static void ++event_loop(Display *dpy, Window win) ++{ ++ XEvent event; ++ ++ while (1) { ++ XNextEvent( dpy, &event ); ++ ++ switch (event.type) { ++ case Expose: ++ redraw(dpy, WindowID, win); ++ break; ++ case ConfigureNotify: ++ /*resize( event.xconfigure.width, event.xconfigure.height );*/ ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ if (code == XK_Left) { ++ } ++ else { ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ keypress(dpy, win, buffer[0]); ++ } ++ } ++ default: ++ /* nothing */ ++ ; ++ } ++ } ++} ++ ++ ++static VisualID ++get_window_visualid(Display *dpy, Window win) ++{ ++ XWindowAttributes attr; ++ ++ if (XGetWindowAttributes(dpy, win, &attr)) { ++ return attr.visual->visualid; ++ } ++ else { ++ return 0; ++ } ++} ++ ++ ++static void ++get_window_size(Display *dpy, Window win, int *w, int *h) ++{ ++ XWindowAttributes attr; ++ ++ if (XGetWindowAttributes(dpy, win, &attr)) { ++ *w = attr.width; ++ *h = attr.height; ++ } ++ else { ++ *w = *h = 0; ++ } ++} ++ ++ ++static XVisualInfo * ++visualid_to_visualinfo(Display *dpy, VisualID vid) ++{ ++ XVisualInfo *vinfo, templ; ++ long mask; ++ int n; ++ ++ templ.visualid = vid; ++ mask = VisualIDMask; ++ ++ vinfo = XGetVisualInfo(dpy, mask, &templ, &n); ++ return vinfo; ++} ++ ++ ++static void ++key_usage(void) ++{ ++ printf("Keyboard:\n"); ++ printf(" z - display Z buffer\n"); ++ printf(" s - display stencil buffer\n"); ++ printf(" f - display front color buffer\n"); ++ printf(" b - display back buffer\n"); ++} ++ ++ ++static void ++usage(void) ++{ ++ printf("Usage: glxsnoop [-display dpy] windowID\n"); ++ key_usage(); ++} ++ ++ ++static void ++parse_opts(int argc, char *argv[]) ++{ ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-h") == 0) { ++ usage(); ++ exit(0); ++ } ++ else if (strcmp(argv[i], "-display") == 0) { ++ DisplayName = argv[i + 1]; ++ i++; ++ } ++ else { ++ if (argv[i][0] == '0' && argv[i][1] == 'x') { ++ /* hex */ ++ WindowID = strtol(argv[i], NULL, 16); ++ } ++ else { ++ WindowID = atoi(argv[i]); ++ } ++ break; ++ } ++ } ++ ++ if (!WindowID) { ++ usage(); ++ exit(0); ++ } ++} ++ ++ ++int ++main( int argc, char *argv[] ) ++{ ++ Display *dpy; ++ VisualID vid; ++ XVisualInfo *visinfo; ++ Window win; ++ ++ parse_opts(argc, argv); ++ ++ key_usage(); ++ ++ dpy = XOpenDisplay(DisplayName); ++ ++ /* find the VisualID for the named window */ ++ vid = get_window_visualid(dpy, WindowID); ++ get_window_size(dpy, WindowID, &Width, &Height); ++ ++ visinfo = visualid_to_visualinfo(dpy, vid); ++ ++ Context = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!Context) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ win = make_gl_window(dpy, visinfo, Width, Height); ++ XMapWindow(dpy, win); ++ update_window_title(dpy, win); ++ ++ event_loop( dpy, win ); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/glxswapcontrol.c Mesa-7.8.1.patched/progs/xdemos/glxswapcontrol.c +--- Mesa-7.8.1/progs/xdemos/glxswapcontrol.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/glxswapcontrol.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,893 @@ ++/* ++ * Copyright (C) 1999-2001 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. ++ */ ++ ++/* ++ * This is a port of the infamous "gears" demo to straight GLX (i.e. no GLUT) ++ * Port by Brian Paul 23 March 2001 ++ * ++ * Modified by Ian Romanick 09 April 2003 to support ++ * GLX_{MESA,SGI}_swap_control and GLX_OML_sync_control. ++ * ++ * Command line options: ++ * -display Name of the display to use. ++ * -info print GL implementation information ++ * -swap N Attempt to set the swap interval to 1/N second ++ * -forcegetrate Get the display refresh rate even if the required GLX ++ * extension is not supported. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#ifndef __VMS ++/*# include */ ++#endif ++# define GLX_GLXEXT_PROTOTYPES ++#include ++#include ++ ++#ifndef GLX_MESA_swap_control ++typedef GLint ( * PFNGLXSWAPINTERVALMESAPROC) (unsigned interval); ++typedef GLint ( * PFNGLXGETSWAPINTERVALMESAPROC) ( void ); ++#endif ++ ++#if !defined( GLX_OML_sync_control ) && defined( _STDINT_H ) ++#define GLX_OML_sync_control 1 ++typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); ++#endif ++ ++#ifndef GLX_MESA_swap_frame_usage ++#define GLX_MESA_swap_frame_usage 1 ++typedef int ( * PFNGLXGETFRAMEUSAGEMESAPROC) (Display *dpy, GLXDrawable drawable, float * usage ); ++#endif ++ ++#define BENCHMARK ++ ++PFNGLXGETFRAMEUSAGEMESAPROC get_frame_usage = NULL; ++ ++#ifdef BENCHMARK ++ ++/* XXX this probably isn't very portable */ ++ ++#include ++#include ++ ++#define NUL '\0' ++ ++/* return current time (in seconds) */ ++static int ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (int) tv.tv_sec; ++} ++ ++#else /*BENCHMARK*/ ++ ++/* dummy */ ++static int ++current_time(void) ++{ ++ return 0; ++} ++ ++#endif /*BENCHMARK*/ ++ ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265 ++#endif ++ ++ ++static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; ++static GLint gear1, gear2, gear3; ++static GLfloat angle = 0.0; ++ ++static GLboolean has_OML_sync_control = GL_FALSE; ++static GLboolean has_SGI_swap_control = GL_FALSE; ++static GLboolean has_MESA_swap_control = GL_FALSE; ++static GLboolean has_MESA_swap_frame_usage = GL_FALSE; ++ ++static char ** extension_table = NULL; ++static unsigned num_extensions; ++ ++static GLboolean use_ztrick = GL_FALSE; ++static GLfloat aspectX = 1.0f, aspectY = 1.0f; ++ ++/* ++ * ++ * Draw a gear wheel. You'll probably want to call this function when ++ * building a display list since we do a lot of trig here. ++ * ++ * Input: inner_radius - radius of hole at center ++ * outer_radius - radius at center of teeth ++ * width - width of gear ++ * teeth - number of teeth ++ * tooth_depth - depth of tooth ++ */ ++static void ++gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, ++ GLint teeth, GLfloat tooth_depth) ++{ ++ GLint i; ++ GLfloat r0, r1, r2; ++ GLfloat angle, da; ++ GLfloat u, v, len; ++ ++ r0 = inner_radius; ++ r1 = outer_radius - tooth_depth / 2.0; ++ r2 = outer_radius + tooth_depth / 2.0; ++ ++ da = 2.0 * M_PI / teeth / 4.0; ++ ++ glShadeModel(GL_FLAT); ++ ++ glNormal3f(0.0, 0.0, 1.0); ++ ++ /* draw front face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw front sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ glEnd(); ++ ++ glNormal3f(0.0, 0.0, -1.0); ++ ++ /* draw back face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw back sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ } ++ glEnd(); ++ ++ /* draw outward faces of teeth */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ u = r2 * cos(angle + da) - r1 * cos(angle); ++ v = r2 * sin(angle + da) - r1 * sin(angle); ++ len = sqrt(u * u + v * v); ++ u /= len; ++ v /= len; ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); ++ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ } ++ ++ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); ++ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); ++ ++ glEnd(); ++ ++ glShadeModel(GL_SMOOTH); ++ ++ /* draw inside radius cylinder */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glNormal3f(-cos(angle), -sin(angle), 0.0); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ } ++ glEnd(); ++} ++ ++ ++static void ++draw(void) ++{ ++ if ( use_ztrick ) { ++ static GLboolean flip = GL_FALSE; ++ static const GLfloat vert[4][3] = { ++ { -1, -1, -0.999 }, ++ { 1, -1, -0.999 }, ++ { 1, 1, -0.999 }, ++ { -1, 1, -0.999 } ++ }; ++ static const GLfloat col[4][3] = { ++ { 1.0, 0.6, 0.0 }, ++ { 1.0, 0.6, 0.0 }, ++ { 0.0, 0.0, 0.0 }, ++ { 0.0, 0.0, 0.0 }, ++ }; ++ ++ if ( flip ) { ++ glDepthRange(0, 0.5); ++ glDepthFunc(GL_LEQUAL); ++ } ++ else { ++ glDepthRange(1.0, 0.4999); ++ glDepthFunc(GL_GEQUAL); ++ } ++ ++ flip = !flip; ++ ++ /* The famous Quake "Z trick" only works when the whole screen is ++ * re-drawn each frame. ++ */ ++ ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1, 1, -1, 1, -1, 1); ++ glDisable(GL_LIGHTING); ++ glShadeModel(GL_SMOOTH); ++ ++ glEnableClientState( GL_VERTEX_ARRAY ); ++ glEnableClientState( GL_COLOR_ARRAY ); ++ glVertexPointer( 3, GL_FLOAT, 0, vert ); ++ glColorPointer( 3, GL_FLOAT, 0, col ); ++ glDrawArrays( GL_POLYGON, 0, 4 ); ++ glDisableClientState( GL_COLOR_ARRAY ); ++ glDisableClientState( GL_VERTEX_ARRAY ); ++ ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0); ++ ++ glEnable(GL_LIGHTING); ++ ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -45.0); ++ } ++ else { ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ } ++ ++ glPushMatrix(); ++ glRotatef(view_rotx, 1.0, 0.0, 0.0); ++ glRotatef(view_roty, 0.0, 1.0, 0.0); ++ glRotatef(view_rotz, 0.0, 0.0, 1.0); ++ ++ glPushMatrix(); ++ glTranslatef(-3.0, -2.0, 0.0); ++ glRotatef(angle, 0.0, 0.0, 1.0); ++ glCallList(gear1); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(3.1, -2.0, 0.0); ++ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); ++ glCallList(gear2); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(-3.1, 4.2, 0.0); ++ glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); ++ glCallList(gear3); ++ glPopMatrix(); ++ ++ glPopMatrix(); ++} ++ ++ ++/* new window size or exposure */ ++static void ++reshape(int width, int height) ++{ ++ if (width > height) { ++ aspectX = (GLfloat) width / (GLfloat) height; ++ aspectY = 1.0; ++ } ++ else { ++ aspectX = 1.0; ++ aspectY = (GLfloat) height / (GLfloat) width; ++ } ++ ++ glViewport(0, 0, (GLint) width, (GLint) height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ ++ glFrustum(-aspectX, aspectX, -aspectY, aspectY, 5.0, 60.0); ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -45.0); ++} ++ ++ ++static void ++init(void) ++{ ++ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; ++ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; ++ static GLfloat green[4] = { 0.0, 0.8, 0.2, 1.0 }; ++ static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 }; ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_CULL_FACE); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ /* make the gears */ ++ gear1 = glGenLists(1); ++ glNewList(gear1, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); ++ gear(1.0, 4.0, 1.0, 20, 0.7); ++ glEndList(); ++ ++ gear2 = glGenLists(1); ++ glNewList(gear2, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); ++ gear(0.5, 2.0, 2.0, 10, 0.7); ++ glEndList(); ++ ++ gear3 = glGenLists(1); ++ glNewList(gear3, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); ++ gear(1.3, 2.0, 0.5, 10, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++} ++ ++ ++/** ++ * Remove window border/decorations. ++ */ ++static void ++no_border( Display *dpy, Window w) ++{ ++ static const unsigned MWM_HINTS_DECORATIONS = (1 << 1); ++ static const int PROP_MOTIF_WM_HINTS_ELEMENTS = 5; ++ ++ typedef struct ++ { ++ unsigned long flags; ++ unsigned long functions; ++ unsigned long decorations; ++ long inputMode; ++ unsigned long status; ++ } PropMotifWmHints; ++ ++ PropMotifWmHints motif_hints; ++ Atom prop, proptype; ++ unsigned long flags = 0; ++ ++ /* setup the property */ ++ motif_hints.flags = MWM_HINTS_DECORATIONS; ++ motif_hints.decorations = flags; ++ ++ /* get the atom for the property */ ++ prop = XInternAtom( dpy, "_MOTIF_WM_HINTS", True ); ++ if (!prop) { ++ /* something went wrong! */ ++ return; ++ } ++ ++ /* not sure this is correct, seems to work, XA_WM_HINTS didn't work */ ++ proptype = prop; ++ ++ XChangeProperty( dpy, w, /* display, window */ ++ prop, proptype, /* property, type */ ++ 32, /* format: 32-bit datums */ ++ PropModeReplace, /* mode */ ++ (unsigned char *) &motif_hints, /* data */ ++ PROP_MOTIF_WM_HINTS_ELEMENTS /* nelements */ ++ ); ++} ++ ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( Display *dpy, const char *name, ++ int x, int y, int width, int height, GLboolean fullscreen, ++ Window *winRet, GLXContext *ctxRet) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ if (fullscreen) { ++ x = y = 0; ++ width = DisplayWidth( dpy, scrnum ); ++ height = DisplayHeight( dpy, scrnum ); ++ } ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attrib ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* 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 ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ if (fullscreen) ++ no_border(dpy, win); ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(visinfo); ++ ++ *winRet = win; ++ *ctxRet = ctx; ++} ++ ++ ++static void ++event_loop(Display *dpy, Window win) ++{ ++ float frame_usage = 0.0; ++ ++ while (1) { ++ while (XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case Expose: ++ /* we'll redraw below */ ++ break; ++ case ConfigureNotify: ++ reshape(event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ if (code == XK_Left) { ++ view_roty += 5.0; ++ } ++ else if (code == XK_Right) { ++ view_roty -= 5.0; ++ } ++ else if (code == XK_Up) { ++ view_rotx += 5.0; ++ } ++ else if (code == XK_Down) { ++ view_rotx -= 5.0; ++ } ++ else { ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return; ++ } ++ } ++ } ++ } ++ } ++ ++ /* next frame */ ++ angle += 2.0; ++ ++ draw(); ++ ++ glXSwapBuffers(dpy, win); ++ ++ if ( get_frame_usage != NULL ) { ++ GLfloat temp; ++ ++ (*get_frame_usage)( dpy, win, & temp ); ++ frame_usage += temp; ++ } ++ ++ /* calc framerate */ ++ { ++ static int t0 = -1; ++ static int frames = 0; ++ int t = current_time(); ++ ++ if (t0 < 0) ++ t0 = t; ++ ++ frames++; ++ ++ if (t - t0 >= 5.0) { ++ GLfloat seconds = t - t0; ++ GLfloat fps = frames / seconds; ++ if ( get_frame_usage != NULL ) { ++ printf("%d frames in %3.1f seconds = %6.3f FPS (%3.1f%% usage)\n", ++ frames, seconds, fps, ++ (frame_usage * 100.0) / (float) frames ); ++ } ++ else { ++ printf("%d frames in %3.1f seconds = %6.3f FPS\n", ++ frames, seconds, fps); ++ } ++ ++ t0 = t; ++ frames = 0; ++ frame_usage = 0.0; ++ } ++ } ++ } ++} ++ ++ ++/** ++ * Display the refresh rate of the display using the GLX_OML_sync_control ++ * extension. ++ */ ++static void ++show_refresh_rate( Display * dpy ) ++{ ++#if defined(GLX_OML_sync_control) && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) ++ PFNGLXGETMSCRATEOMLPROC get_msc_rate; ++ int32_t n; ++ int32_t d; ++ ++ get_msc_rate = (PFNGLXGETMSCRATEOMLPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetMscRateOML" ); ++ if ( get_msc_rate != NULL ) { ++ (*get_msc_rate)( dpy, glXGetCurrentDrawable(), &n, &d ); ++ printf( "refresh rate: %.1fHz\n", (float) n / d ); ++ return; ++ } ++#endif ++ printf( "glXGetMscRateOML not supported.\n" ); ++} ++ ++ ++/** ++ * Fill in the table of extension strings from a supplied extensions string ++ * (as returned by glXQueryExtensionsString). ++ * ++ * \param string String of GLX extensions. ++ * \sa is_extension_supported ++ */ ++static void ++make_extension_table( const char * string ) ++{ ++ char ** string_tab; ++ unsigned num_strings; ++ unsigned base; ++ unsigned idx; ++ unsigned i; ++ ++ /* Count the number of spaces in the string. That gives a base-line ++ * figure for the number of extension in the string. ++ */ ++ ++ num_strings = 1; ++ for ( i = 0 ; string[i] != NUL ; i++ ) { ++ if ( string[i] == ' ' ) { ++ num_strings++; ++ } ++ } ++ ++ string_tab = (char **) malloc( sizeof( char * ) * num_strings ); ++ if ( string_tab == NULL ) { ++ return; ++ } ++ ++ base = 0; ++ idx = 0; ++ ++ while ( string[ base ] != NUL ) { ++ /* Determine the length of the next extension string. ++ */ ++ ++ for ( i = 0 ++ ; (string[ base + i ] != NUL) && (string[ base + i ] != ' ') ++ ; i++ ) { ++ /* empty */ ; ++ } ++ ++ if ( i > 0 ) { ++ /* If the string was non-zero length, add it to the table. We ++ * can get zero length strings if there is a space at the end of ++ * the string or if there are two (or more) spaces next to each ++ * other in the string. ++ */ ++ ++ string_tab[ idx ] = malloc( sizeof( char ) * (i + 1) ); ++ if ( string_tab[ idx ] == NULL ) { ++ return; ++ } ++ ++ (void) memcpy( string_tab[ idx ], & string[ base ], i ); ++ string_tab[ idx ][i] = NUL; ++ idx++; ++ } ++ ++ ++ /* Skip to the start of the next extension string. ++ */ ++ ++ for ( base += i ++ ; (string[ base ] == ' ') && (string[ base ] != NUL) ++ ; base++ ) { ++ /* empty */ ; ++ } ++ } ++ ++ extension_table = string_tab; ++ num_extensions = idx; ++} ++ ++ ++/** ++ * Determine of an extension is supported. The extension string table ++ * must have already be initialized by calling \c make_extension_table. ++ * ++ * \praram ext Extension to be tested. ++ * \return GL_TRUE of the extension is supported, GL_FALSE otherwise. ++ * \sa make_extension_table ++ */ ++static GLboolean ++is_extension_supported( const char * ext ) ++{ ++ unsigned i; ++ ++ for ( i = 0 ; i < num_extensions ; i++ ) { ++ if ( strcmp( ext, extension_table[i] ) == 0 ) { ++ return GL_TRUE; ++ } ++ } ++ ++ return GL_FALSE; ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ Window win; ++ GLXContext ctx; ++ char *dpyName = NULL; ++ int swap_interval = 1; ++ GLboolean do_swap_interval = GL_FALSE; ++ GLboolean force_get_rate = GL_FALSE; ++ GLboolean fullscreen = GL_FALSE; ++ GLboolean printInfo = GL_FALSE; ++ int i; ++ PFNGLXSWAPINTERVALMESAPROC set_swap_interval = NULL; ++ PFNGLXGETSWAPINTERVALMESAPROC get_swap_interval = NULL; ++ int width = 300, height = 300; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0 && i + 1 < argc) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-info") == 0) { ++ printInfo = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-swap") == 0 && i + 1 < argc) { ++ swap_interval = atoi( argv[i+1] ); ++ do_swap_interval = GL_TRUE; ++ i++; ++ } ++ else if (strcmp(argv[i], "-forcegetrate") == 0) { ++ /* This option was put in because some DRI drivers don't support the ++ * full GLX_OML_sync_control extension, but they do support ++ * glXGetMscRateOML. ++ */ ++ force_get_rate = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-fullscreen") == 0) { ++ fullscreen = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-ztrick") == 0) { ++ use_ztrick = GL_TRUE; ++ } ++ else if (strcmp(argv[i], "-help") == 0) { ++ printf("Usage:\n"); ++ printf(" gears [options]\n"); ++ printf("Options:\n"); ++ printf(" -help Print this information\n"); ++ printf(" -display displayName Specify X display\n"); ++ printf(" -info Display GL information\n"); ++ printf(" -swap N Swap no more than once per N vertical refreshes\n"); ++ printf(" -forcegetrate Try to use glXGetMscRateOML function\n"); ++ printf(" -fullscreen Full-screen window\n"); ++ return 0; ++ } ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", XDisplayName(dpyName)); ++ return -1; ++ } ++ ++ make_window(dpy, "glxgears", 0, 0, width, height, fullscreen, &win, &ctx); ++ XMapWindow(dpy, win); ++ glXMakeCurrent(dpy, win, ctx); ++ ++ make_extension_table( (char *) glXQueryExtensionsString(dpy,DefaultScreen(dpy)) ); ++ has_OML_sync_control = is_extension_supported( "GLX_OML_sync_control" ); ++ has_SGI_swap_control = is_extension_supported( "GLX_SGI_swap_control" ); ++ has_MESA_swap_control = is_extension_supported( "GLX_MESA_swap_control" ); ++ has_MESA_swap_frame_usage = is_extension_supported( "GLX_MESA_swap_frame_usage" ); ++ ++ if ( has_MESA_swap_control ) { ++ set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalMESA" ); ++ get_swap_interval = (PFNGLXGETSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetSwapIntervalMESA" ); ++ } ++ else if ( has_SGI_swap_control ) { ++ set_swap_interval = (PFNGLXSWAPINTERVALMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXSwapIntervalSGI" ); ++ } ++ ++ ++ if ( has_MESA_swap_frame_usage ) { ++ get_frame_usage = (PFNGLXGETFRAMEUSAGEMESAPROC) glXGetProcAddressARB( (const GLubyte *) "glXGetFrameUsageMESA" ); ++ } ++ ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ if ( has_OML_sync_control || force_get_rate ) { ++ show_refresh_rate( dpy ); ++ } ++ ++ if ( get_swap_interval != NULL ) { ++ printf("Default swap interval = %d\n", (*get_swap_interval)() ); ++ } ++ } ++ ++ if ( do_swap_interval ) { ++ if ( set_swap_interval != NULL ) { ++ if ( ((swap_interval == 0) && !has_MESA_swap_control) ++ || (swap_interval < 0) ) { ++ printf( "Swap interval must be non-negative or greater than zero " ++ "if GLX_MESA_swap_control is not supported.\n" ); ++ } ++ else { ++ (*set_swap_interval)( swap_interval ); ++ } ++ ++ if ( printInfo && (get_swap_interval != NULL) ) { ++ printf("Current swap interval = %d\n", (*get_swap_interval)() ); ++ } ++ } ++ else { ++ printf("Unable to set swap-interval. Neither GLX_SGI_swap_control " ++ "nor GLX_MESA_swap_control are supported.\n" ); ++ } ++ } ++ ++ init(); ++ ++ /* Set initial projection/viewing transformation. ++ * same as glxgears.c ++ */ ++ reshape(width, height); ++ ++ event_loop(dpy, win); ++ ++ glXDestroyContext(dpy, ctx); ++ XDestroyWindow(dpy, win); ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/ipc.c Mesa-7.8.1.patched/progs/xdemos/ipc.c +--- Mesa-7.8.1/progs/xdemos/ipc.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/ipc.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,264 @@ ++/* Copyright (c) 2003 Tungsten Graphics, Inc. ++ * ++ * 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, the Tungsten ++ * Graphics splash screen, 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 THE AUTHORS OR COPYRIGHT HOLDERS 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. ++ */ ++ ++/* ++ * Simple IPC API ++ * Brian Paul ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ipc.h" ++ ++#if defined(IRIX) || defined(irix) ++typedef int socklen_t; ++#endif ++ ++#define NO_DELAY 1 ++ ++#define DEFAULT_MASTER_PORT 7011 ++ ++ ++/* ++ * Return my hostname in . ++ * Return 1 for success, 0 for error. ++ */ ++int ++MyHostName(char *nameOut, int maxNameLength) ++{ ++ int k = gethostname(nameOut, maxNameLength); ++ return k==0; ++} ++ ++ ++/* ++ * Create a socket attached to a port. Later, we can call AcceptConnection ++ * on the socket returned from this function. ++ * Return the new socket number or -1 if error. ++ */ ++int ++CreatePort(int *port) ++{ ++ char hostname[1000]; ++ struct sockaddr_in servaddr; ++ struct hostent *hp; ++ int so_reuseaddr = 1; ++ int tcp_nodelay = 1; ++ int sock, k; ++ ++ /* create socket */ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ assert(sock > 2); ++ ++ /* get my host name */ ++ k = gethostname(hostname, 1000); ++ assert(k == 0); ++ ++ /* get hostent info */ ++ hp = gethostbyname(hostname); ++ assert(hp); ++ ++ /* initialize the servaddr struct */ ++ memset(&servaddr, 0, sizeof(servaddr) ); ++ servaddr.sin_family = AF_INET; ++ servaddr.sin_port = htons((unsigned short) (*port)); ++ memcpy((char *) &servaddr.sin_addr, hp->h_addr, ++ sizeof(servaddr.sin_addr)); ++ ++ /* deallocate when we exit */ ++ k = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, ++ (char *) &so_reuseaddr, sizeof(so_reuseaddr)); ++ assert(k==0); ++ ++ /* send packets immediately */ ++#if NO_DELAY ++ k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ++ (char *) &tcp_nodelay, sizeof(tcp_nodelay)); ++ assert(k==0); ++#endif ++ ++ if (*port == 0) ++ *port = DEFAULT_MASTER_PORT; ++ ++ k = 1; ++ while (k && (*port < 65534)) { ++ /* bind our address to the socket */ ++ servaddr.sin_port = htons((unsigned short) (*port)); ++ k = bind(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)); ++ if (k) ++ *port = *port + 1; ++ } ++ ++#if 0 ++ printf("###### Real Port: %d\n", *port); ++#endif ++ ++ /* listen for connections */ ++ k = listen(sock, 100); ++ assert(k == 0); ++ ++ return sock; ++} ++ ++ ++/* ++ * Accept a connection on the named socket. ++ * Return a new socket for the new connection, or -1 if error. ++ */ ++int ++AcceptConnection(int socket) ++{ ++ struct sockaddr addr; ++ socklen_t addrLen; ++ int newSock; ++ ++ addrLen = sizeof(addr); ++ newSock = accept(socket, &addr, &addrLen); ++ if (newSock == 1) ++ return -1; ++ else ++ return newSock; ++} ++ ++ ++/* ++ * Contact the server running on the given host on the named port. ++ * Return socket number or -1 if error. ++ */ ++int ++Connect(const char *hostname, int port) ++{ ++ struct sockaddr_in servaddr; ++ struct hostent *hp; ++ int sock, k; ++ int tcp_nodelay = 1; ++ ++ assert(port); ++ ++ sock = socket(AF_INET, SOCK_STREAM, 0); ++ assert(sock >= 0); ++ ++ hp = gethostbyname(hostname); ++ assert(hp); ++ ++ memset(&servaddr, 0, sizeof(servaddr)); ++ servaddr.sin_family = AF_INET; ++ servaddr.sin_port = htons((unsigned short) port); ++ memcpy((char *) &servaddr.sin_addr, hp->h_addr, sizeof(servaddr.sin_addr)); ++ ++ k = connect(sock, (struct sockaddr *) &servaddr, sizeof(servaddr)); ++ if (k != 0) { ++ perror("Connect:"); ++ return -1; ++ } ++ ++#if NO_DELAY ++ /* send packets immediately */ ++ k = setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, ++ (char *) &tcp_nodelay, sizeof(tcp_nodelay)); ++ assert(k==0); ++#endif ++ ++ return sock; ++} ++ ++ ++void ++CloseSocket(int socket) ++{ ++ close(socket); ++} ++ ++ ++int ++SendData(int socket, const void *data, int bytes) ++{ ++ int sent = 0; ++ int b; ++ ++ while (sent < bytes) { ++ b = write(socket, (char *) data + sent, bytes - sent); ++ if (b <= 0) ++ return -1; /* something broke */ ++ sent += b; ++ } ++ return sent; ++} ++ ++ ++int ++ReceiveData(int socket, void *data, int bytes) ++{ ++ int received = 0, b; ++ ++ while (received < bytes) { ++ b = read(socket, (char *) data + received, bytes - received); ++ if (b <= 0) ++ return -1; ++ received += b; ++ } ++ return received; ++} ++ ++ ++int ++SendString(int socket, const char *str) ++{ ++ const int len = strlen(str); ++ int sent, b; ++ ++ /* first, send a 4-byte length indicator */ ++ b = write(socket, &len, sizeof(len)); ++ if (b <= 0) ++ return -1; ++ ++ sent = SendData(socket, str, len); ++ assert(sent == len); ++ return sent; ++} ++ ++ ++int ++ReceiveString(int socket, char *str, int maxLen) ++{ ++ int len, received, b; ++ ++ /* first, read 4 bytes to see how long of string to receive */ ++ b = read(socket, &len, sizeof(len)); ++ if (b <= 0) ++ return -1; ++ ++ assert(len <= maxLen); /* XXX fix someday */ ++ assert(len >= 0); ++ received = ReceiveData(socket, str, len); ++ assert(received != -1); ++ assert(received == len); ++ str[len] = 0; ++ return received; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/ipc.h Mesa-7.8.1.patched/progs/xdemos/ipc.h +--- Mesa-7.8.1/progs/xdemos/ipc.h 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/ipc.h 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,16 @@ ++#ifndef IPC_H ++#define IPC_H ++ ++ ++extern int MyHostName(char *nameOut, int maxNameLength); ++extern int CreatePort(int *port); ++extern int AcceptConnection(int socket); ++extern int Connect(const char *hostname, int port); ++extern void CloseSocket(int socket); ++extern int SendData(int socket, const void *data, int bytes); ++extern int ReceiveData(int socket, void *data, int bytes); ++extern int SendString(int socket, const char *str); ++extern int ReceiveString(int socket, char *str, int maxLen); ++ ++ ++#endif /* IPC_H */ +diff -Naurp Mesa-7.8.1/progs/xdemos/Makefile Mesa-7.8.1.patched/progs/xdemos/Makefile +--- Mesa-7.8.1/progs/xdemos/Makefile 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/Makefile 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,103 @@ ++# progs/xdemos/Makefile ++ ++TOP = ../.. ++include $(TOP)/configs/current ++ ++ ++INCDIR = $(TOP)/include ++ ++LIB_DEP = $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ++ ++# Add X11 and pthread libs to satisfy GNU gold. ++APP_LIB_DEPS += -lX11 -lpthread ++ ++LIBS = -L$(TOP)/$(LIB_DIR) -l$(GL_LIB) -L$(libdir) $(APP_LIB_DEPS) ++ ++PROGS = \ ++ corender \ ++ glsync \ ++ glthreads \ ++ glxdemo \ ++ glxgears \ ++ glxgears_fbconfig \ ++ glxgears_pixmap \ ++ glxcontexts \ ++ glxheads \ ++ glxinfo \ ++ glxpixmap \ ++ glxpbdemo \ ++ glxsnoop \ ++ glxswapcontrol \ ++ manywin \ ++ msctest \ ++ multictx \ ++ offset \ ++ omlsync \ ++ overlay \ ++ pbinfo \ ++ pbdemo \ ++ sharedtex \ ++ sharedtex_mt \ ++ texture_from_pixmap \ ++ wincopy \ ++ xfont \ ++ xrotfontdemo ++ ++# Don't build these by default because of extra library dependencies ++EXTRA_PROGS = \ ++ shape \ ++ yuvrect_client \ ++ xdemo ++ ++ ++ ++##### RULES ##### ++ ++.o: $(LIB_DEP) ++ $(APP_CC) $(CFLAGS) $(LDFLAGS) $< $(LIBS) -o $@ ++ ++.c.o: ++ $(APP_CC) -I$(INCDIR) $(X11_INCLUDES) $(CFLAGS) $< -c -o $@ ++ ++ ++##### TARGETS ##### ++ ++default: $(PROGS) ++ ++$(PROGS): $(PROGS:%=%.o) ++ ++extra: $(EXTRA_PROGS) ++ ++ ++clean: ++ -rm -f $(PROGS) $(EXTRA_PROGS) ++ -rm -f *.o *~ ++ ++ ++# special cases ++pbutil.o: pbutil.h ++pbinfo.o: pbutil.h ++pbinfo: pbinfo.o pbutil.o ++ $(APP_CC) $(CFLAGS) $(LDFLAGS) pbinfo.o pbutil.o $(LIBS) -o $@ ++ ++pbdemo.o: pbutil.h ++pbdemo: pbdemo.o pbutil.o ++ $(APP_CC) $(CFLAGS) $(LDFLAGS) pbdemo.o pbutil.o $(LIBS) -o $@ ++ ++glxgears_fbconfig.o: pbutil.h ++glxgears_fbconfig: glxgears_fbconfig.o pbutil.o ++ $(APP_CC) $(CFLAGS) $(LDFLAGS) glxgears_fbconfig.o pbutil.o $(LIBS) -o $@ ++ ++xuserotfont.o: xuserotfont.h ++xrotfontdemo.o: xuserotfont.h ++xrotfontdemo: xrotfontdemo.o xuserotfont.o ++ $(APP_CC) $(CFLAGS) $(LDFLAGS) xrotfontdemo.o xuserotfont.o $(LIBS) -o $@ ++ ++ipc.o: ipc.h ++corender.o: ipc.h ++corender: corender.o ipc.o ++ $(APP_CC) $(CFLAGS) $(LDFLAGS) corender.o ipc.o $(LIBS) -o $@ ++ ++yuvrect_client: yuvrect_client.o ++ $(APP_CC) $(CFLAGS) $< $(LDFLAGS) $(LIBS) -l$(GLU_LIB) -o $@ ++ +diff -Naurp Mesa-7.8.1/progs/xdemos/manywin.c Mesa-7.8.1.patched/progs/xdemos/manywin.c +--- Mesa-7.8.1/progs/xdemos/manywin.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/manywin.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,421 @@ ++/* ++ * Create N GLX windows/contexts and render to them in round-robin order. ++ * Also, have the contexts share all texture objects. ++ * Press 'd' to delete a texture, 'u' to unbind it. ++ * ++ * Copyright (C) 2000 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. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* ++ * Each display/window/context: ++ */ ++struct head { ++ char DisplayName[1000]; ++ Display *Dpy; ++ Window Win; ++ GLXContext Context; ++ float Angle; ++ char Renderer[1000]; ++ char Vendor[1000]; ++ char Version[1000]; ++}; ++ ++ ++#define MAX_HEADS 200 ++static struct head Heads[MAX_HEADS]; ++static int NumHeads = 0; ++static GLboolean SwapSeparate = GL_TRUE; ++static GLuint TexObj = 0; ++ ++ ++static void ++Error(const char *display, const char *msg) ++{ ++ fprintf(stderr, "Error on display %s - %s\n", XDisplayName(display), msg); ++ exit(1); ++} ++ ++ ++static struct head * ++AddHead(const char *displayName, const char *name) ++{ ++ Display *dpy; ++ Window win; ++ GLXContext ctx; ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ XVisualInfo *visinfo; ++ int width = 90, height = 90; ++ int xpos = 0, ypos = 0; ++ ++ if (NumHeads >= MAX_HEADS) ++ return NULL; ++ ++ dpy = XOpenDisplay(displayName); ++ if (!dpy) { ++ Error(displayName, "Unable to open display"); ++ return NULL; ++ } ++ ++ scrnum = DefaultScreen(dpy); ++ root = RootWindow(dpy, scrnum); ++ ++ visinfo = glXChooseVisual(dpy, scrnum, attrib); ++ if (!visinfo) { ++ Error(displayName, "Unable to find RGB, double-buffered visual"); ++ return NULL; ++ } ++ ++ /* window attributes */ ++ xpos = (NumHeads % 10) * 100; ++ ypos = (NumHeads / 10) * 100; ++ printf("%d, %d\n", xpos, ypos); ++ 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, xpos, ypos, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr); ++ if (!win) { ++ Error(displayName, "Couldn't create window"); ++ return NULL; ++ } ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ if (NumHeads == 0) { ++ ctx = glXCreateContext(dpy, visinfo, NULL, True); ++ } ++ else { ++ /* share textures & dlists with 0th context */ ++ printf("sharing\n"); ++ ctx = glXCreateContext(dpy, visinfo, Heads[0].Context, True); ++ } ++ if (!ctx) { ++ Error(displayName, "Couldn't create GLX context"); ++ return NULL; ++ } ++ ++ XMapWindow(dpy, win); ++ ++ if (!glXMakeCurrent(dpy, win, ctx)) { ++ Error(displayName, "glXMakeCurrent failed"); ++ printf("glXMakeCurrent failed in Redraw()\n"); ++ return NULL; ++ } ++ ++ if (NumHeads == 0) { ++ /* create texture object now */ ++ static const GLubyte checker[2][2][4] = { ++ { {255, 255, 255, 255}, { 0, 0, 0, 255} }, ++ { { 0, 0, 0, 0}, {255, 255, 255, 255} } ++ }; ++ glGenTextures(1, &TexObj); ++ assert(TexObj); ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 2, 2, 0, GL_RGB, ++ GL_UNSIGNED_BYTE, checker); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ } ++ else { ++ /* bind 0th context's texture in this context too */ ++ assert(TexObj); ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ } ++ glEnable(GL_TEXTURE_2D); ++ ++ /* save the info for this head */ ++ { ++ struct head *h = &Heads[NumHeads]; ++ const char * tmp; ++ ++ if (strlen(name) + 1 > sizeof(h->DisplayName)) { ++ Error(displayName, "name string overflow"); ++ return NULL; ++ } ++ strcpy(h->DisplayName, name); ++ ++ h->Dpy = dpy; ++ h->Win = win; ++ h->Context = ctx; ++ h->Angle = 0.0; ++ ++ tmp = (char *) glGetString(GL_VERSION); ++ if (strlen(tmp) + 1 > sizeof(h->Version)) { ++ Error(displayName, "GL_VERSION string overflow"); ++ return NULL; ++ } ++ strcpy(h->Version, tmp); ++ ++ tmp = (char *) glGetString(GL_VENDOR); ++ if (strlen(tmp) + 1 > sizeof(h->Vendor)) { ++ Error(displayName, "GL_VENDOR string overflow"); ++ return NULL; ++ } ++ strcpy(h->Vendor, tmp); ++ ++ tmp = (char *) glGetString(GL_RENDERER); ++ if (strlen(tmp) + 1 > sizeof(h->Renderer)) { ++ Error(displayName, "GL_RENDERER string overflow"); ++ return NULL; ++ } ++ strcpy(h->Renderer, tmp); ++ ++ NumHeads++; ++ return &Heads[NumHeads-1]; ++ } ++ ++} ++ ++ ++static void ++DestroyHeads(void) ++{ ++ int i; ++ for (i = 0; i < NumHeads; i++) { ++ XDestroyWindow(Heads[i].Dpy, Heads[i].Win); ++ glXDestroyContext(Heads[i].Dpy, Heads[i].Context); ++ XCloseDisplay(Heads[i].Dpy); ++ } ++} ++ ++ ++static void ++Redraw(struct head *h) ++{ ++ if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { ++ Error(h->DisplayName, "glXMakeCurrent failed"); ++ printf("glXMakeCurrent failed in Redraw()\n"); ++ return; ++ } ++ ++ h->Angle += 1.0; ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.5, 0.5, 0.5, 1.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ /* draw green triangle */ ++ glColor3f(0.0, 1.0, 0.0); ++ glPushMatrix(); ++ glRotatef(h->Angle, 0, 0, 1); ++ glBegin(GL_TRIANGLES); ++ glTexCoord2f(0.5, 1.0); glVertex2f(0, 0.8); ++ glTexCoord2f(0.0, 0.0); glVertex2f(-0.8, -0.7); ++ glTexCoord2f(1.0, 0.0); glVertex2f(0.8, -0.7); ++ glEnd(); ++ glPopMatrix(); ++ ++ if (!SwapSeparate) ++ glXSwapBuffers(h->Dpy, h->Win); ++} ++ ++ ++static void ++Swap(struct head *h) ++{ ++ glXSwapBuffers(h->Dpy, h->Win); ++} ++ ++ ++static void ++Resize(const struct head *h, unsigned int width, unsigned int height) ++{ ++ if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { ++ Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); ++ return; ++ } ++ glFlush(); ++ glViewport(0, 0, width, height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); ++} ++ ++ ++ ++static void ++EventLoop(void) ++{ ++ while (1) { ++ int i; ++ for (i = 0; i < NumHeads; i++) { ++ struct head *h = &Heads[i]; ++ while (XPending(h->Dpy) > 0) { ++ XEvent event; ++ XNextEvent(h->Dpy, &event); ++ if (event.xany.window == h->Win) { ++ switch (event.type) { ++ case Expose: ++ Redraw(h); ++ if (SwapSeparate) ++ Swap(h); ++ break; ++ case ConfigureNotify: ++ Resize(h, event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buf[100]; ++ KeySym keySym; ++ XComposeStatus stat; ++ XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat); ++ switch (keySym) { ++ case XK_Escape: ++ return; ++ break; ++ case XK_d: ++ case XK_D: ++ printf("Delete Texture in window %d\n", i); ++ glXMakeCurrent(h->Dpy, h->Win, h->Context); ++ glDeleteTextures(1, &TexObj); ++ break; ++ case XK_u: ++ case XK_U: ++ printf("Unbind Texture in window %d\n", i); ++ glXMakeCurrent(h->Dpy, h->Win, h->Context); ++ glBindTexture(GL_TEXTURE_2D, 0); ++ break; ++ } ++ } ++ break; ++ default: ++ /*no-op*/ ; ++ } ++ } ++ else { ++ printf("window mismatch\n"); ++ } ++ } ++ } ++ ++ /* redraw all windows */ ++ for (i = 0; i < NumHeads; i++) { ++ Redraw(&Heads[i]); ++ } ++ /* swapbuffers on all windows, if not already done */ ++ if (SwapSeparate) { ++ for (i = 0; i < NumHeads; i++) { ++ Swap(&Heads[i]); ++ } ++ } ++ usleep(1); ++ } ++} ++ ++ ++ ++static void ++PrintInfo(const struct head *h) ++{ ++ printf("Name: %s\n", h->DisplayName); ++ printf(" Display: %p\n", (void *) h->Dpy); ++ printf(" Window: 0x%x\n", (int) h->Win); ++ printf(" Context: 0x%lx\n", (long) h->Context); ++ printf(" GL_VERSION: %s\n", h->Version); ++ printf(" GL_VENDOR: %s\n", h->Vendor); ++ printf(" GL_RENDERER: %s\n", h->Renderer); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ char *dpyName = NULL; ++ int i; ++ ++ if (argc == 1) { ++ printf("manywin: open N simultaneous glx windows\n"); ++ printf("Usage:\n"); ++ printf(" manywin [-s] numWindows\n"); ++ printf("Options:\n"); ++ printf(" -s = swap immediately after drawing (see src code)\n"); ++ printf("Example:\n"); ++ printf(" manywin 10\n"); ++ return 0; ++ } ++ else { ++ int n = 3; ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-s") == 0) { ++ SwapSeparate = GL_FALSE; ++ } ++ else if (strcmp(argv[i], "-display") == 0 && i < argc) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else { ++ n = atoi(argv[i]); ++ } ++ } ++ if (n < 1) ++ n = 1; ++ if (n > MAX_HEADS) ++ n = MAX_HEADS; ++ ++ printf("%d windows\n", n); ++ for (i = 0; i < n; i++) { ++ char name[100]; ++ struct head *h; ++ sprintf(name, "%d", i); ++ h = AddHead(dpyName, name); ++ if (h) { ++ PrintInfo(h); ++ } ++ } ++ } ++ ++ EventLoop(); ++ DestroyHeads(); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/msctest.c Mesa-7.8.1.patched/progs/xdemos/msctest.c +--- Mesa-7.8.1/progs/xdemos/msctest.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/msctest.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,195 @@ ++/* ++ * Copyright © 2009 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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 ++ * THE AUTHORS OR COPYRIGHT HOLDERS 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. ++ * ++ * Authors: ++ * Jesse Barnes ++ * ++ */ ++ ++/** @file msctest.c ++ * Simple test for MSC functionality. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++void (*get_sync_values)(Display *dpy, Window winGL, int64_t *ust, int64_t *msc, int64_t *sbc); ++void (*wait_sync)(Display *dpy, Window winGL, int64_t target_msc, int64_t divisor, int64_t remainder, int64_t *ust, int64_t *msc, int64_t *sbc); ++ ++static int GLXExtensionSupported(Display *dpy, const char *extension) ++{ ++ const char *extensionsString, *pos; ++ ++ extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); ++ ++ pos = strstr(extensionsString, extension); ++ ++ if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && ++ (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) ++ return 1; ++ ++ return 0; ++} ++ ++extern char *optarg; ++extern int optind, opterr, optopt; ++static char optstr[] = "v"; ++ ++static void usage(char *name) ++{ ++ printf("usage: %s\n", name); ++ exit(-1); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ Display *disp; ++ XVisualInfo *pvi; ++ XSetWindowAttributes swa; ++ int attrib[14]; ++ Window winGL; ++ GLXContext context; ++ int dummy; ++ Atom wmDelete; ++ int verbose = 0, width = 200, height = 200; ++ int c, i = 1; ++ int64_t ust, msc, sbc; ++ ++ opterr = 0; ++ while ((c = getopt(argc, argv, optstr)) != -1) { ++ switch (c) { ++ case 'v': ++ verbose = 1; ++ break; ++ default: ++ usage(argv[0]); ++ break; ++ } ++ } ++ ++ disp = XOpenDisplay(NULL); ++ if (!disp) { ++ fprintf(stderr, "failed to open display\n"); ++ return -1; ++ } ++ ++ if (!glXQueryExtension(disp, &dummy, &dummy)) { ++ fprintf(stderr, "glXQueryExtension failed\n"); ++ return -1; ++ } ++ ++ if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) { ++ fprintf(stderr, "GLX_OML_sync_control not supported, exiting\n"); ++ return -1; ++ } ++ ++ attrib[0] = GLX_RGBA; ++ attrib[1] = 1; ++ attrib[2] = GLX_RED_SIZE; ++ attrib[3] = 1; ++ attrib[4] = GLX_GREEN_SIZE; ++ attrib[5] = 1; ++ attrib[6] = GLX_BLUE_SIZE; ++ attrib[7] = 1; ++ attrib[8] = GLX_DOUBLEBUFFER; ++ attrib[9] = 1; ++ attrib[10] = None; ++ ++ pvi = glXChooseVisual(disp, DefaultScreen(disp), attrib); ++ if (!pvi) { ++ fprintf(stderr, "failed to choose visual, exiting\n"); ++ return -1; ++ } ++ ++ context = glXCreateContext(disp, pvi, None, GL_TRUE); ++ if (!context) { ++ fprintf(stderr, "failed to create glx context\n"); ++ return -1; ++ } ++ ++ pvi->screen = DefaultScreen(disp); ++ ++ swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen), ++ pvi->visual, AllocNone); ++ swa.border_pixel = 0; ++ swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | ++ StructureNotifyMask; ++ winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen), ++ 0, 0, ++ width, height, ++ 0, pvi->depth, InputOutput, pvi->visual, ++ CWBorderPixel | CWColormap | CWEventMask, &swa); ++ if (!winGL) { ++ fprintf(stderr, "window creation failed\n"); ++ return -1; ++ } ++ wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); ++ XSetWMProtocols(disp, winGL, &wmDelete, 1); ++ ++ XSetStandardProperties(disp, winGL, "msc test", "msc text", ++ None, NULL, 0, NULL); ++ ++ XMapRaised(disp, winGL); ++ ++ glXMakeCurrent(disp, winGL, context); ++ ++ get_sync_values = (void *)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML"); ++ wait_sync = (void *)glXGetProcAddress((unsigned char *)"glXWaitForMscOML"); ++ ++ if (!get_sync_values || !wait_sync) { ++ fprintf(stderr, "failed to get sync values function\n"); ++ return -1; ++ } ++ ++ while (i++) { ++ get_sync_values(disp, winGL, &ust, &msc, &sbc); ++ fprintf(stderr, "ust: %llu, msc: %llu, sbc: %llu\n", ust, msc, ++ sbc); ++ ++ /* Alternate colors to make tearing obvious */ ++ if (i & 1) ++ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); ++ else ++ glClearColor(1.0f, 0.0f, 0.0f, 0.0f); ++ glClear(GL_COLOR_BUFFER_BIT); ++ glXSwapBuffers(disp, winGL); ++ wait_sync(disp, winGL, 0, 60, 0, &ust, &msc, &sbc); ++ fprintf(stderr, ++ "wait returned ust: %llu, msc: %llu, sbc: %llu\n", ++ ust, msc, sbc); ++ sleep(1); ++ } ++ ++ XDestroyWindow(disp, winGL); ++ glXDestroyContext(disp, context); ++ XCloseDisplay(disp); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/multictx.c Mesa-7.8.1.patched/progs/xdemos/multictx.c +--- Mesa-7.8.1/progs/xdemos/multictx.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/multictx.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,585 @@ ++/* ++ * Copyright (C) 2009 VMware, Inc. 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 rendering with two contexts into one window. ++ * Setup different rendering state for each context to check that ++ * context switching is handled properly. ++ * ++ * Brian Paul ++ * 6 Aug 2009 ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++ ++#ifndef M_PI ++#define M_PI 3.14159265 ++#endif ++ ++ ++/** Event handler results: */ ++#define NOP 0 ++#define EXIT 1 ++#define DRAW 2 ++ ++static GLfloat view_rotx = 0.0, view_roty = 210.0, view_rotz = 0.0; ++static GLint gear1, gear2; ++static GLfloat angle = 0.0; ++ ++static GLboolean animate = GL_TRUE; /* Animation */ ++ ++ ++static double ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (double) tv.tv_sec + tv.tv_usec / 1000000.0; ++} ++ ++ ++/* ++ * ++ * Draw a gear wheel. You'll probably want to call this function when ++ * building a display list since we do a lot of trig here. ++ * ++ * Input: inner_radius - radius of hole at center ++ * outer_radius - radius at center of teeth ++ * width - width of gear ++ * teeth - number of teeth ++ * tooth_depth - depth of tooth ++ */ ++static void ++gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, ++ GLint teeth, GLfloat tooth_depth) ++{ ++ GLint i; ++ GLfloat r0, r1, r2; ++ GLfloat angle, da; ++ GLfloat u, v, len; ++ ++ r0 = inner_radius; ++ r1 = outer_radius - tooth_depth / 2.0; ++ r2 = outer_radius + tooth_depth / 2.0; ++ ++ da = 2.0 * M_PI / teeth / 4.0; ++ ++ glShadeModel(GL_FLAT); ++ ++ glNormal3f(0.0, 0.0, 1.0); ++ ++ /* draw front face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw front sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ } ++ glEnd(); ++ ++ glNormal3f(0.0, 0.0, -1.0); ++ ++ /* draw back face */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ if (i < teeth) { ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ } ++ } ++ glEnd(); ++ ++ /* draw back sides of teeth */ ++ glBegin(GL_QUADS); ++ da = 2.0 * M_PI / teeth / 4.0; ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ } ++ glEnd(); ++ ++ /* draw outward faces of teeth */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i < teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); ++ glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); ++ u = r2 * cos(angle + da) - r1 * cos(angle); ++ v = r2 * sin(angle + da) - r1 * sin(angle); ++ len = sqrt(u * u + v * v); ++ u /= len; ++ v /= len; ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); ++ glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ width * 0.5); ++ glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), ++ -width * 0.5); ++ u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); ++ v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); ++ glNormal3f(v, -u, 0.0); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ width * 0.5); ++ glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), ++ -width * 0.5); ++ glNormal3f(cos(angle), sin(angle), 0.0); ++ } ++ ++ glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); ++ glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); ++ ++ glEnd(); ++ ++ glShadeModel(GL_SMOOTH); ++ ++ /* draw inside radius cylinder */ ++ glBegin(GL_QUAD_STRIP); ++ for (i = 0; i <= teeth; i++) { ++ angle = i * 2.0 * M_PI / teeth; ++ glNormal3f(-cos(angle), -sin(angle), 0.0); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); ++ glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); ++ } ++ glEnd(); ++} ++ ++ ++static void ++draw(int ctx) ++{ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(view_rotx, 1.0, 0.0, 0.0); ++ glRotatef(view_roty + angle, 0.0, 1.0, 0.0); ++ glRotatef(view_rotz, 0.0, 0.0, 1.0); ++ ++ if (ctx == 0) { ++ glDisable(GL_CULL_FACE); ++ glPushMatrix(); ++ glRotatef(angle, 0.0, 0.0, 1.0); ++ glCallList(gear1); ++ glPopMatrix(); ++ /* This should not effect the other context's rendering */ ++ glEnable(GL_CULL_FACE); ++ glCullFace(GL_FRONT_AND_BACK); ++ } ++ else { ++ glPushMatrix(); ++ glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); ++ glCallList(gear2); ++ glPopMatrix(); ++ } ++ ++ glPopMatrix(); ++ ++ /* this flush is important since we'll be switching contexts next */ ++ glFlush(); ++} ++ ++ ++ ++static void ++draw_frame(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) ++{ ++ static double tRot0 = -1.0; ++ double dt, t = current_time(); ++ ++ if (tRot0 < 0.0) ++ tRot0 = t; ++ dt = t - tRot0; ++ tRot0 = t; ++ ++ if (animate) { ++ /* advance rotation for next frame */ ++ angle += 70.0 * dt; /* 70 degrees per second */ ++ if (angle > 3600.0) ++ angle -= 3600.0; ++ } ++ ++ glXMakeCurrent(dpy, (GLXDrawable) win, ctx1); ++ draw(0); ++ ++ glXMakeCurrent(dpy, (GLXDrawable) win, ctx2); ++ draw(1); ++ ++ glXSwapBuffers(dpy, win); ++} ++ ++ ++/* new window size or exposure */ ++static void ++reshape(Display *dpy, Window win, ++ GLXContext ctx1, GLXContext ctx2, int width, int height) ++{ ++ int i; ++ ++ width /= 2; ++ ++ /* loop: left half of window, right half of window */ ++ for (i = 0; i < 2; i++) { ++ if (i == 0) ++ glXMakeCurrent(dpy, win, ctx1); ++ else ++ glXMakeCurrent(dpy, win, ctx2); ++ ++ glViewport(width * i, 0, width, height); ++ glScissor(width * i, 0, width, height); ++ ++ { ++ GLfloat h = (GLfloat) height / (GLfloat) width; ++ ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); ++ } ++ ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0.0, 0.0, -30.0); ++ } ++} ++ ++ ++ ++static void ++init(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) ++{ ++ static GLfloat pos[4] = { 5.0, 5.0, 10.0, 0.0 }; ++ static GLfloat red[4] = { 0.8, 0.1, 0.0, 1.0 }; ++ static GLfloat green[4] = { 0.0, 0.8, 0.2, 0.5 }; ++ /*static GLfloat blue[4] = { 0.2, 0.2, 1.0, 1.0 };*/ ++ ++ /* first ctx */ ++ { ++ static GLuint stipple[32] = { ++ 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, ++ 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, ++ ++ 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, ++ 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, ++ ++ 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, ++ 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, 0x00ff00ff, ++ ++ 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00, ++ 0xff00ff00, 0xff00ff00, 0xff00ff00, 0xff00ff00 ++ }; ++ ++ glXMakeCurrent(dpy, win, ctx1); ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ gear1 = glGenLists(1); ++ glNewList(gear1, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); ++ gear(1.0, 4.0, 1.0, 20, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++ glEnable(GL_SCISSOR_TEST); ++ glClearColor(0.4, 0.4, 0.4, 1.0); ++ ++ glPolygonStipple((GLubyte *) stipple); ++ glEnable(GL_POLYGON_STIPPLE); ++ } ++ ++ /* second ctx */ ++ { ++ glXMakeCurrent(dpy, win, ctx2); ++ ++ glLightfv(GL_LIGHT0, GL_POSITION, pos); ++ glEnable(GL_LIGHTING); ++ glEnable(GL_LIGHT0); ++ glEnable(GL_DEPTH_TEST); ++ ++ gear2 = glGenLists(1); ++ glNewList(gear2, GL_COMPILE); ++ glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); ++ gear(1.5, 3.0, 1.5, 16, 0.7); ++ glEndList(); ++ ++ glEnable(GL_NORMALIZE); ++ glEnable(GL_SCISSOR_TEST); ++ glClearColor(0.6, 0.6, 0.6, 1.0); ++ ++ glEnable(GL_BLEND); ++ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); ++ } ++} ++ ++ ++/** ++ * Create an RGB, double-buffered window. ++ * Return the window and two context handles. ++ */ ++static void ++make_window_and_contexts( Display *dpy, const char *name, ++ int x, int y, int width, int height, ++ Window *winRet, ++ GLXContext *ctxRet1, ++ GLXContext *ctxRet2) ++{ ++ int attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attribs ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* 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, x, y, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ *winRet = win; ++ *ctxRet1 = glXCreateContext( dpy, visinfo, NULL, True ); ++ *ctxRet2 = glXCreateContext( dpy, visinfo, NULL, True ); ++ ++ if (!*ctxRet1 || !*ctxRet2) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(visinfo); ++} ++ ++ ++/** ++ * Handle one X event. ++ * \return NOP, EXIT or DRAW ++ */ ++static int ++handle_event(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2, ++ XEvent *event) ++{ ++ (void) dpy; ++ (void) win; ++ ++ switch (event->type) { ++ case Expose: ++ return DRAW; ++ case ConfigureNotify: ++ reshape(dpy, win, ctx1, ctx2, ++ event->xconfigure.width, event->xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event->xkey, 0); ++ if (code == XK_Left) { ++ view_roty += 5.0; ++ } ++ else if (code == XK_Right) { ++ view_roty -= 5.0; ++ } ++ else if (code == XK_Up) { ++ view_rotx += 5.0; ++ } ++ else if (code == XK_Down) { ++ view_rotx -= 5.0; ++ } ++ else { ++ r = XLookupString(&event->xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return EXIT; ++ } ++ else if (buffer[0] == 'a' || buffer[0] == 'A') { ++ animate = !animate; ++ } ++ } ++ return DRAW; ++ } ++ } ++ return NOP; ++} ++ ++ ++static void ++event_loop(Display *dpy, Window win, GLXContext ctx1, GLXContext ctx2) ++{ ++ while (1) { ++ int op; ++ while (!animate || XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ op = handle_event(dpy, win, ctx1, ctx2, &event); ++ if (op == EXIT) ++ return; ++ else if (op == DRAW) ++ break; ++ } ++ ++ draw_frame(dpy, win, ctx1, ctx2); ++ } ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ unsigned int winWidth = 800, winHeight = 400; ++ int x = 0, y = 0; ++ Display *dpy; ++ Window win; ++ GLXContext ctx1, ctx2; ++ char *dpyName = NULL; ++ GLboolean printInfo = GL_FALSE; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else { ++ return 1; ++ } ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", ++ dpyName ? dpyName : getenv("DISPLAY")); ++ return -1; ++ } ++ ++ make_window_and_contexts(dpy, "multictx", x, y, winWidth, winHeight, ++ &win, &ctx1, &ctx2); ++ XMapWindow(dpy, win); ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ } ++ ++ init(dpy, win, ctx1, ctx2); ++ ++ /* Set initial projection/viewing transformation. ++ * We can't be sure we'll get a ConfigureNotify event when the window ++ * first appears. ++ */ ++ reshape(dpy, win, ctx1, ctx2, winWidth, winHeight); ++ ++ event_loop(dpy, win, ctx1, ctx2); ++ ++ glDeleteLists(gear1, 1); ++ glDeleteLists(gear2, 1); ++ glXDestroyContext(dpy, ctx1); ++ glXDestroyContext(dpy, ctx2); ++ XDestroyWindow(dpy, win); ++ XCloseDisplay(dpy); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/offset.c Mesa-7.8.1.patched/progs/xdemos/offset.c +--- Mesa-7.8.1/progs/xdemos/offset.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/offset.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,343 @@ ++/**************************************************************************** ++Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California. ++ ++ All Rights Reserved ++ ++Permission to use, copy, modify, and distribute this software and its ++documentation for any purpose and without fee is hereby granted, ++provided that the above copyright notice appear in all copies and that ++both that copyright notice and this permission notice appear in ++supporting documentation, and that the name of Silicon Graphics not be ++used in advertising or publicity pertaining to distribution of the ++software without specific, written prior permission. ++ ++SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, ++INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO ++EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR ++CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF ++USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR ++OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ++PERFORMANCE OF THIS SOFTWARE. ++ ++****************************************************************************/ ++ ++/* ++ * Derived from code written by Kurt Akeley, November 1992 ++ * ++ * Uses PolygonOffset to draw hidden-line images. PolygonOffset ++ * shifts the z values of polygons an amount that is ++ * proportional to their slope in screen z. This keeps ++ * the lines, which are drawn without displacement, from ++ * interacting with their respective polygons, and ++ * thus eliminates line dropouts. ++ * ++ * The left image shows an ordinary antialiased wireframe image. ++ * The center image shows an antialiased hidden-line image without ++ * PolygonOffset. ++ * The right image shows an antialiased hidden-line image using ++ * PolygonOffset to reduce artifacts. ++ * ++ * Drag with a mouse button pressed to rotate the models. ++ * Press the escape key to exit. ++ */ ++ ++/* ++ * Modified for OpenGL 1.1 glPolygonOffset() conventions ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#undef GL_EXT_polygon_offset /* use GL 1.1 version instead of extension */ ++ ++ ++#ifndef EXIT_FAILURE ++# define EXIT_FAILURE 1 ++#endif ++#ifndef EXIT_SUCCESS ++# define EXIT_SUCCESS 0 ++#endif ++ ++#define MAXQUAD 6 ++ ++typedef float Vertex[3]; ++ ++typedef Vertex Quad[4]; ++ ++/* data to define the six faces of a unit cube */ ++Quad quads[MAXQUAD] = { ++ { {0,0,0}, {0,0,1}, {0,1,1}, {0,1,0} }, /* x = 0 */ ++ { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1} }, /* y = 0 */ ++ { {0,0,0}, {1,0,0}, {1,1,0}, {0,1,0} }, /* z = 0 */ ++ { {1,0,0}, {1,0,1}, {1,1,1}, {1,1,0} }, /* x = 1 */ ++ { {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} }, /* y = 1 */ ++ { {0,0,1}, {1,0,1}, {1,1,1}, {0,1,1} } /* z = 1 */ ++}; ++ ++#define WIREFRAME 0 ++#define HIDDEN_LINE 1 ++ ++static void error(const char* prog, const char* msg); ++static void cubes(int mx, int my, int mode); ++static void fill(Quad quad); ++static void outline(Quad quad); ++static void draw_hidden(Quad quad, int mode, int face); ++static void process_input(Display *dpy, Window win); ++static int query_extension(char* extName); ++ ++static int attributeList[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE, 1, None }; ++ ++static int dimension = 3; ++ ++static float Scale = 1.0; ++ ++ ++int main(int argc, char** argv) { ++ Display *dpy; ++ XVisualInfo *vi; ++ XSetWindowAttributes swa; ++ Window win; ++ GLXContext cx; ++ GLint z; ++ ++ dpy = XOpenDisplay(0); ++ if (!dpy) error(argv[0], "can't open display"); ++ ++ vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList); ++ if (!vi) error(argv[0], "no suitable visual"); ++ ++ cx = glXCreateContext(dpy, vi, 0, GL_TRUE); ++ ++ swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), ++ vi->visual, AllocNone); ++ ++ swa.border_pixel = 0; ++ swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask | ++ ButtonPressMask | ButtonMotionMask; ++ win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, 900, 300, ++ 0, vi->depth, InputOutput, vi->visual, ++ CWBorderPixel|CWColormap|CWEventMask, &swa); ++ XStoreName(dpy, win, "hiddenline"); ++ XMapWindow(dpy, win); ++ ++ glXMakeCurrent(dpy, win, cx); ++ ++ /* check for the polygon offset extension */ ++#ifndef GL_VERSION_1_1 ++ if (!query_extension("GL_EXT_polygon_offset")) ++ error(argv[0], "polygon_offset extension is not available"); ++#else ++ (void) query_extension; ++#endif ++ ++ /* set up viewing parameters */ ++ glMatrixMode(GL_PROJECTION); ++ glFrustum(-1, 1, -1, 1, 6, 20); ++ glMatrixMode(GL_MODELVIEW); ++ glTranslatef(0, 0, -15); ++ ++ /* set other relevant state information */ ++ glEnable(GL_DEPTH_TEST); ++ ++ glGetIntegerv(GL_DEPTH_BITS, &z); ++ printf("GL_DEPTH_BITS = %d\n", z); ++ ++#ifdef GL_EXT_polygon_offset ++ printf("using 1.0 offset extension\n"); ++ glPolygonOffsetEXT( 1.0, 0.00001 ); ++#else ++ printf("using 1.1 offset\n"); ++ glPolygonOffset( 1.0, 0.5 ); ++#endif ++ ++ glShadeModel( GL_FLAT ); ++ glDisable( GL_DITHER ); ++ ++ /* process events until the user presses ESC */ ++ while (1) process_input(dpy, win); ++ ++ return 0; ++} ++ ++static void ++draw_scene(int mx, int my) { ++ glClearColor(0.25, 0.25, 0.25, 0); ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glTranslatef(-1.7, 0.0, 0.0); ++ cubes(mx, my, WIREFRAME); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ cubes(mx, my, HIDDEN_LINE); ++ glPopMatrix(); ++ ++ glPushMatrix(); ++ glTranslatef(1.7, 0.0, 0.0); ++#ifdef GL_EXT_polygon_offset ++ glEnable(GL_POLYGON_OFFSET_EXT); ++#else ++ glEnable(GL_POLYGON_OFFSET_FILL); ++#endif ++ glScalef(Scale, Scale, Scale); ++ cubes(mx, my, HIDDEN_LINE); ++#ifdef GL_EXT_polygon_offset ++ glDisable(GL_POLYGON_OFFSET_EXT); ++#else ++ glDisable(GL_POLYGON_OFFSET_FILL); ++#endif ++ glPopMatrix(); ++} ++ ++ ++static void ++cubes(int mx, int my, int mode) { ++ int x, y, z, i; ++ ++ /* track the mouse */ ++ glRotatef(mx / 2.0, 0, 1, 0); ++ glRotatef(my / 2.0, 1, 0, 0); ++ ++ /* draw the lines as hidden polygons */ ++ glTranslatef(-0.5, -0.5, -0.5); ++ glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension); ++ for (z = 0; z < dimension; z++) { ++ for (y = 0; y < dimension; y++) { ++ for (x = 0; x < dimension; x++) { ++ glPushMatrix(); ++ glTranslatef(x, y, z); ++ glScalef(0.8, 0.8, 0.8); ++ for (i = 0; i < MAXQUAD; i++) ++ draw_hidden(quads[i], mode, i); ++ glPopMatrix(); ++ } ++ } ++ } ++} ++ ++static void ++fill(Quad quad) { ++ /* draw a filled polygon */ ++ glBegin(GL_QUADS); ++ glVertex3fv(quad[0]); ++ glVertex3fv(quad[1]); ++ glVertex3fv(quad[2]); ++ glVertex3fv(quad[3]); ++ glEnd(); ++} ++ ++static void ++outline(Quad quad) { ++ /* draw an outlined polygon */ ++ glBegin(GL_LINE_LOOP); ++ glVertex3fv(quad[0]); ++ glVertex3fv(quad[1]); ++ glVertex3fv(quad[2]); ++ glVertex3fv(quad[3]); ++ glEnd(); ++} ++ ++static void ++draw_hidden(Quad quad, int mode, int face) { ++ static const GLfloat colors[3][3] = { ++ {0.5, 0.5, 0.0}, ++ {0.8, 0.5, 0.0}, ++ {0.0, 0.5, 0.8} ++ }; ++ if (mode == HIDDEN_LINE) { ++ glColor3fv(colors[face % 3]); ++ fill(quad); ++ } ++ ++ /* draw the outline using white */ ++ glColor3f(1, 1, 1); ++ outline(quad); ++} ++ ++static void ++process_input(Display *dpy, Window win) { ++ XEvent event; ++ static int prevx, prevy; ++ static int deltax = 90, deltay = 40; ++ ++ do { ++ char buf[31]; ++ KeySym keysym; ++ ++ XNextEvent(dpy, &event); ++ switch(event.type) { ++ case Expose: ++ break; ++ case ConfigureNotify: { ++ /* this approach preserves a 1:1 viewport aspect ratio */ ++ int vX, vY, vW, vH; ++ int eW = event.xconfigure.width, eH = event.xconfigure.height; ++ if (eW >= eH) { ++ vX = 0; ++ vY = (eH - eW) >> 1; ++ vW = vH = eW; ++ } else { ++ vX = (eW - eH) >> 1; ++ vY = 0; ++ vW = vH = eH; ++ } ++ glViewport(vX, vY, vW, vH); ++ } ++ break; ++ case KeyPress: ++ (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL); ++ switch (keysym) { ++ case 'Z': ++ Scale *= 1.1; ++ break; ++ case 'z': ++ Scale *= 0.9; ++ break; ++ case XK_Escape: ++ exit(EXIT_SUCCESS); ++ default: ++ break; ++ } ++ break; ++ case ButtonPress: ++ prevx = event.xbutton.x; ++ prevy = event.xbutton.y; ++ break; ++ case MotionNotify: ++ deltax += (event.xbutton.x - prevx); prevx = event.xbutton.x; ++ deltay += (event.xbutton.y - prevy); prevy = event.xbutton.y; ++ break; ++ default: ++ break; ++ } ++ } while (XPending(dpy)); ++ ++ draw_scene(deltax, deltay); ++ glXSwapBuffers(dpy, win); ++} ++ ++static void ++error(const char *prog, const char *msg) { ++ fprintf(stderr, "%s: %s\n", prog, msg); ++ exit(EXIT_FAILURE); ++} ++ ++static int ++query_extension(char* extName) { ++ char *p = (char *) glGetString(GL_EXTENSIONS); ++ char *end = p + strlen(p); ++ while (p < end) { ++ int n = strcspn(p, " "); ++ if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) ++ return GL_TRUE; ++ p += (n + 1); ++ } ++ return GL_FALSE; ++} ++ +diff -Naurp Mesa-7.8.1/progs/xdemos/omlsync.c Mesa-7.8.1.patched/progs/xdemos/omlsync.c +--- Mesa-7.8.1/progs/xdemos/omlsync.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/omlsync.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,265 @@ ++/* ++ * Copyright © 2007-2010 Intel Corporation ++ * ++ * 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 (including the next ++ * paragraph) 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 ++ * THE AUTHORS OR COPYRIGHT HOLDERS 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. ++ * ++ * Authors: ++ * Jesse Barnes ++ * ++ */ ++ ++/** @file omlsync.c ++ * The program is simple: it paints a window alternating colors (red & ++ * white) either as fast as possible or synchronized to vblank events ++ * ++ * If run normally, the program should display a window that exhibits ++ * significant tearing between red and white colors (e.g. you might get ++ * a "waterfall" effect of red and white horizontal bars). ++ * ++ * If run with the '-s b' option, the program should synchronize the ++ * window color changes with the vertical blank period, resulting in a ++ * window that looks orangish with a high frequency flicker (which may ++ * be invisible). If the window is moved to another screen, this ++ * property should be preserved. If the window spans two screens, it ++ * shouldn't tear on whichever screen most of the window is on; the ++ * portion on the other screen may show some tearing (like the ++ * waterfall effect above). ++ * ++ * Other options include '-w ' and '-h ' to set the ++ * window size. ++ */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++Bool (*glXGetSyncValuesOML)(Display *dpy, GLXDrawable drawable, ++ int64_t *ust, int64_t *msc, int64_t *sbc); ++Bool (*glXGetMscRateOML)(Display *dpy, GLXDrawable drawable, int32_t *numerator, ++ int32_t *denominator); ++int64_t (*glXSwapBuffersMscOML)(Display *dpy, GLXDrawable drawable, ++ int64_t target_msc, int64_t divisor, ++ int64_t remainder); ++Bool (*glXWaitForMscOML)(Display *dpy, GLXDrawable drawable, int64_t target_msc, ++ int64_t divisor, int64_t remainder, int64_t *ust, ++ int64_t *msc, int64_t *sbc); ++Bool (*glXWaitForSbcOML)(Display *dpy, GLXDrawable drawable, int64_t target_sbc, ++ int64_t *ust, int64_t *msc, int64_t *sbc); ++int (*glXSwapInterval)(int interval); ++ ++static int GLXExtensionSupported(Display *dpy, const char *extension) ++{ ++ const char *extensionsString, *pos; ++ ++ extensionsString = glXQueryExtensionsString(dpy, DefaultScreen(dpy)); ++ ++ pos = strstr(extensionsString, extension); ++ ++ if (pos != NULL && (pos == extensionsString || pos[-1] == ' ') && ++ (pos[strlen(extension)] == ' ' || pos[strlen(extension)] == '\0')) ++ return 1; ++ ++ return 0; ++} ++ ++extern char *optarg; ++extern int optind, opterr, optopt; ++static char optstr[] = "w:h:vd:r:n:i:"; ++ ++static void usage(char *name) ++{ ++ printf("usage: %s [-w ] [-h ] ...\n", name); ++ printf("\t-d - divisor for OML swap\n"); ++ printf("\t-r - remainder for OML swap\n"); ++ printf("\t-n - wait interval for OML WaitMSC\n"); ++ printf("\t-i - swap at most once every n frames\n"); ++ printf("\t-v: verbose (print count)\n"); ++ exit(-1); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ Display *disp; ++ XVisualInfo *pvi; ++ XSetWindowAttributes swa; ++ Window winGL; ++ GLXContext context; ++ int dummy; ++ Atom wmDelete; ++ int64_t ust, msc, sbc; ++ int width = 500, height = 500, verbose = 0, divisor = 0, remainder = 0, ++ wait_interval = 0, swap_interval = 1; ++ int c, i = 1; ++ int ret; ++ int db_attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ XSizeHints sizehints; ++ ++ opterr = 0; ++ while ((c = getopt(argc, argv, optstr)) != -1) { ++ switch (c) { ++ case 'w': ++ width = atoi(optarg); ++ break; ++ case 'h': ++ height = atoi(optarg); ++ break; ++ case 'v': ++ verbose = 1; ++ break; ++ case 'd': ++ divisor = atoi(optarg); ++ break; ++ case 'r': ++ remainder = atoi(optarg); ++ break; ++ case 'n': ++ wait_interval = atoi(optarg); ++ break; ++ case 'i': ++ swap_interval = atoi(optarg); ++ break; ++ default: ++ usage(argv[0]); ++ break; ++ } ++ } ++ ++ disp = XOpenDisplay(NULL); ++ if (!disp) { ++ fprintf(stderr, "failed to open display\n"); ++ return -1; ++ } ++ ++ if (!glXQueryExtension(disp, &dummy, &dummy)) { ++ fprintf(stderr, "glXQueryExtension failed\n"); ++ return -1; ++ } ++ ++ if (!GLXExtensionSupported(disp, "GLX_OML_sync_control")) { ++ fprintf(stderr, "GLX_OML_sync_control not supported\n"); ++ return -1; ++ } ++ ++ if (!GLXExtensionSupported(disp, "GLX_MESA_swap_control")) { ++ fprintf(stderr, "GLX_MESA_swap_control not supported\n"); ++ return -1; ++ } ++ ++ pvi = glXChooseVisual(disp, DefaultScreen(disp), db_attribs); ++ ++ if (!pvi) { ++ fprintf(stderr, "failed to choose visual, exiting\n"); ++ return -1; ++ } ++ ++ pvi->screen = DefaultScreen(disp); ++ ++ swa.colormap = XCreateColormap(disp, RootWindow(disp, pvi->screen), ++ pvi->visual, AllocNone); ++ swa.border_pixel = 0; ++ swa.event_mask = ExposureMask | KeyPressMask | ButtonPressMask | ++ StructureNotifyMask; ++ winGL = XCreateWindow(disp, RootWindow(disp, pvi->screen), ++ 0, 0, ++ width, height, ++ 0, pvi->depth, InputOutput, pvi->visual, ++ CWBorderPixel | CWColormap | CWEventMask, &swa); ++ if (!winGL) { ++ fprintf(stderr, "window creation failed\n"); ++ return -1; ++ } ++ wmDelete = XInternAtom(disp, "WM_DELETE_WINDOW", True); ++ XSetWMProtocols(disp, winGL, &wmDelete, 1); ++ ++ sizehints.x = 0; ++ sizehints.y = 0; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ ++ XSetNormalHints(disp, winGL, &sizehints); ++ XSetStandardProperties(disp, winGL, "glsync test", "glsync text", ++ None, NULL, 0, &sizehints); ++ ++ context = glXCreateContext(disp, pvi, NULL, GL_TRUE); ++ if (!context) { ++ fprintf(stderr, "failed to create glx context\n"); ++ return -1; ++ } ++ ++ XMapWindow(disp, winGL); ++ ret = glXMakeCurrent(disp, winGL, context); ++ if (!ret) { ++ fprintf(stderr, "failed to make context current: %d\n", ret); ++ } ++ ++ glXGetSyncValuesOML = (void *)glXGetProcAddress((unsigned char *)"glXGetSyncValuesOML"); ++ glXGetMscRateOML = (void *)glXGetProcAddress((unsigned char *)"glXGetMscRateOML"); ++ glXSwapBuffersMscOML = (void *)glXGetProcAddress((unsigned char *)"glXSwapBuffersMscOML"); ++ glXWaitForMscOML = (void *)glXGetProcAddress((unsigned char *)"glXWaitForMscOML"); ++ glXWaitForSbcOML = (void *)glXGetProcAddress((unsigned char *)"glXWaitForSbcOML"); ++ glXSwapInterval = (void *)glXGetProcAddress((unsigned char *)"glXSwapIntervalMESA"); ++ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glXSwapInterval(swap_interval); ++ fprintf(stderr, "set swap interval to %d\n", swap_interval); ++ ++ glXGetSyncValuesOML(disp, winGL, &ust, &msc, &sbc); ++ while (i++) { ++ /* Alternate colors to make tearing obvious */ ++ if (i & 1) { ++ glClearColor(1.0f, 1.0f, 1.0f, 1.0f); ++ glColor3f(1.0f, 1.0f, 1.0f); ++ } else { ++ glClearColor(1.0f, 0.0f, 0.0f, 0.0f); ++ glColor3f(1.0f, 0.0f, 0.0f); ++ } ++ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ glRectf(0, 0, width, height); ++ ++ glXSwapBuffersMscOML(disp, winGL, 0, divisor, remainder); ++ ++ if (wait_interval) { ++ glXWaitForMscOML(disp, winGL, msc + wait_interval, ++ 0, 0, &ust, &msc, &sbc); ++ } ++ } ++ ++ XDestroyWindow(disp, winGL); ++ glXDestroyContext(disp, context); ++ XCloseDisplay(disp); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/opencloseopen.c Mesa-7.8.1.patched/progs/xdemos/opencloseopen.c +--- Mesa-7.8.1/progs/xdemos/opencloseopen.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/opencloseopen.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,189 @@ ++/* ++ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved. ++ * (C) Copyright IBM Corporation 2003 ++ * ++ * 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. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/** \file opencloseopen.c ++ * Simple test for Mesa bug #508473. Create a window and rendering context. ++ * Draw a single frame. Close the window, destroy the context, and close ++ * the display. Re-open the display, create a new window and context. This ++ * should work, but, at least as of Mesa 5.1, it segfaults. See the bug ++ * report for more details. ++ * ++ * Most of the code here was lifed from various other Mesa xdemos. ++ */ ++ ++static void ++draw(void) ++{ ++ glViewport(0, 0, 300, 300); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); ++ glMatrixMode(GL_MODELVIEW); ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.5, 0.5, 0.5, 1.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ /* draw blue quad */ ++ glLoadIdentity(); ++ glColor3f(0.3, 0.3, 1.0); ++ glPushMatrix(); ++ glRotatef(0, 0, 0, 1); ++ glBegin(GL_POLYGON); ++ glVertex2f(-0.5, -0.25); ++ glVertex2f( 0.5, -0.25); ++ glVertex2f( 0.5, 0.25); ++ glVertex2f(-0.5, 0.25); ++ glEnd(); ++ glPopMatrix();} ++ ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( const char * dpyName, const char *name, ++ int x, int y, int width, int height, ++ Display **dpyRet, Window *winRet, GLXContext *ctxRet) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ Display *dpy; ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", XDisplayName(dpyName)); ++ exit(1); ++ } ++ ++ *dpyRet = dpy; ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attrib ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* 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 ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(visinfo); ++ ++ *winRet = win; ++ *ctxRet = ctx; ++} ++ ++ ++static void ++destroy_window( Display *dpy, Window win, GLXContext ctx ) ++{ ++ glXMakeCurrent(dpy, None, NULL); ++ glXDestroyContext(dpy, ctx); ++ XDestroyWindow(dpy, win); ++ XCloseDisplay(dpy); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ Window win; ++ GLXContext ctx; ++ char *dpyName = NULL; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ } ++ ++ printf("If this program segfaults, then Mesa bug #508473 is probably " ++ "back.\n"); ++ make_window(dpyName, "Open-close-open", 0, 0, 300, 300, &dpy, &win, &ctx); ++ XMapWindow(dpy, win); ++ glXMakeCurrent(dpy, win, ctx); ++ ++ draw(); ++ glXSwapBuffers(dpy, win); ++ sleep(2); ++ ++ destroy_window(dpy, win, ctx); ++ ++ make_window(dpyName, "Open-close-open", 0, 0, 300, 300, &dpy, &win, &ctx); ++ XMapWindow(dpy, win); ++ glXMakeCurrent(dpy, win, ctx); ++ destroy_window(dpy, win, ctx); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/overlay.c Mesa-7.8.1.patched/progs/xdemos/overlay.c +--- Mesa-7.8.1/progs/xdemos/overlay.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/overlay.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,246 @@ ++/* ++ * GLX overlay test/demo. ++ * ++ * Brian Paul ++ * 18 July 2005 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int WinWidth = 300, WinHeight = 300; ++static Window NormalWindow = 0; ++static Window OverlayWindow = 0; ++static GLXContext NormalContext = 0; ++static GLXContext OverlayContext = 0; ++static GLboolean RGBOverlay = GL_FALSE; ++static GLfloat Angle = 0.0; ++ ++ ++static void ++RedrawNormal(Display *dpy) ++{ ++ glXMakeCurrent(dpy, NormalWindow, NormalContext); ++ glViewport(0, 0, WinWidth, WinHeight); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); ++ glMatrixMode(GL_MODELVIEW); ++ glClearColor(0.5, 0.5, 0.5, 1.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ glColor3f(1.0, 1.0, 0.0); ++ glPushMatrix(); ++ glRotatef(Angle, 0, 0, 1); ++ glRectf(-0.8, -0.8, 0.8, 0.8); ++ glPopMatrix(); ++ glXSwapBuffers(dpy, NormalWindow); ++} ++ ++ ++static void ++RedrawOverlay(Display *dpy) ++{ ++ glXMakeCurrent(dpy, OverlayWindow, OverlayContext); ++ glViewport(0, 0, WinWidth, WinHeight); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); ++ glMatrixMode(GL_MODELVIEW); ++ glClear(GL_COLOR_BUFFER_BIT); ++ if (RGBOverlay) { ++ glColor3f(0.0, 1.0, 1.0); ++ } ++ else { ++ glIndexi(2); ++ } ++ glBegin(GL_LINES); ++ glVertex2f(-1, -1); ++ glVertex2f(1, 1); ++ glVertex2f(1, -1); ++ glVertex2f(-1, 1); ++ glEnd(); ++ glXSwapBuffers(dpy, OverlayWindow); ++} ++ ++ ++static Window ++MakeWindow(Display *dpy, XVisualInfo *visinfo, Window parent, ++ unsigned int width, unsigned int height) ++{ ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ ++ scrnum = DefaultScreen(dpy); ++ root = RootWindow(dpy, scrnum); ++ ++ /* 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, parent, 0, 0, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr); ++ return win; ++} ++ ++ ++static void ++MakeNormalWindow(Display *dpy) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ Window root; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen(dpy); ++ root = RootWindow(dpy, scrnum); ++ ++ visinfo = glXChooseVisual(dpy, scrnum, attrib); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ NormalWindow = MakeWindow(dpy, visinfo, root, WinWidth, WinHeight); ++ assert(NormalWindow); ++ ++ NormalContext = glXCreateContext(dpy, visinfo, NULL, True); ++ assert(NormalContext); ++} ++ ++ ++static void ++MakeOverlayWindow(Display *dpy) ++{ ++ int rgbAttribs[] = { ++ GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_LEVEL, 1, ++ None ++ }; ++ int indexAttribs[] = { ++ /*GLX_RGBA, leave this out */ ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_LEVEL, 1, ++ None ++ }; ++ int scrnum; ++ Window root; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen(dpy); ++ root = RootWindow(dpy, scrnum); ++ ++ visinfo = glXChooseVisual(dpy, scrnum, rgbAttribs); ++ if (visinfo) { ++ printf("Found RGB overlay visual 0x%x\n", (int) visinfo->visualid); ++ RGBOverlay = GL_TRUE; ++ } ++ else { ++ visinfo = glXChooseVisual(dpy, scrnum, indexAttribs); ++ if (visinfo) { ++ printf("Found Color Index overlay visual 0x%x\n", ++ (int) visinfo->visualid); ++ /* XXX setup the colormap entries! */ ++ } ++ else { ++ printf("Couldn't get an overlay visual.\n"); ++ printf("Your hardware probably doesn't support framebuffer overlay planes.\n"); ++ exit(1); ++ } ++ } ++ ++ OverlayWindow = MakeWindow(dpy, visinfo, NormalWindow, WinWidth, WinHeight); ++ assert(OverlayWindow); ++ ++ OverlayContext = glXCreateContext(dpy, visinfo, NULL, True); ++ assert(OverlayContext); ++} ++ ++ ++static void ++EventLoop(Display *dpy) ++{ ++ XEvent event; ++ ++ while (1) { ++ XNextEvent(dpy, &event); ++ ++ switch (event.type) { ++ case Expose: ++ RedrawNormal(dpy); ++ RedrawOverlay(dpy); ++ break; ++ case ConfigureNotify: ++ WinWidth = event.xconfigure.width; ++ WinHeight = event.xconfigure.height; ++ if (event.xconfigure.window == NormalWindow) ++ XResizeWindow(dpy, OverlayWindow, WinWidth, WinHeight); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return; ++ } ++ else if (buffer[0] == ' ') { ++ Angle += 5.0; ++ RedrawNormal(dpy); ++ } ++ } ++ break; ++ default: ++ ; /* nothing */ ++ } ++ } ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy = XOpenDisplay(NULL); ++ ++ assert(dpy); ++ ++ MakeNormalWindow(dpy); ++ MakeOverlayWindow(dpy); ++ ++ XMapWindow(dpy, NormalWindow); ++ XMapWindow(dpy, OverlayWindow); ++ ++ EventLoop(dpy); ++ ++ glXDestroyContext(dpy, OverlayContext); ++ glXDestroyContext(dpy, NormalContext); ++ XDestroyWindow(dpy, OverlayWindow); ++ XDestroyWindow(dpy, NormalWindow); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/pbdemo.c Mesa-7.8.1.patched/progs/xdemos/pbdemo.c +--- Mesa-7.8.1/progs/xdemos/pbdemo.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/pbdemo.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,493 @@ ++ ++/* ++ * This program demonstrates how to do "off-screen" rendering using ++ * the GLX pixel buffer extension. ++ * ++ * Written by Brian Paul for the "OpenGL and Window System Integration" ++ * course presented at SIGGRAPH '97. Updated on 5 October 2002. ++ * ++ * Usage: ++ * pbuffers width height imgfile ++ * Where: ++ * width is the width, in pixels, of the image to generate. ++ * height is the height, in pixels, of the image to generate. ++ * imgfile is the name of the PPM image file to write. ++ * ++ * ++ * This demo draws 3-D boxes with random orientation. A pbuffer with ++ * a depth (Z) buffer is prefered but if such a pbuffer can't be created ++ * we use a non-depth-buffered config. ++ * ++ * On machines such as the SGI Indigo you may have to reconfigure your ++ * display/X server to enable pbuffers. Look in the /usr/gfx/ucode/MGRAS/vof/ ++ * directory for display configurationswith the _pbuf suffix. Use ++ * setmon -x to configure your X server and display for pbuffers. ++ * ++ * O2 systems seem to support pbuffers well. ++ * ++ * IR systems (at least 1RM systems) don't have single-buffered, RGBA, ++ * Z-buffered pbuffer configs. BUT, they DO have DOUBLE-buffered, RGBA, ++ * Z-buffered pbuffers. Note how we try four different fbconfig attribute ++ * lists below! ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include "pbutil.h" ++ ++ ++/* Some ugly global vars */ ++static Display *gDpy = NULL; ++static int gScreen = 0; ++static FBCONFIG gFBconfig = 0; ++static PBUFFER gPBuffer = 0; ++static int gWidth, gHeight; ++static GLXContext glCtx; ++ ++ ++ ++/* ++ * Create the pbuffer and return a GLXPbuffer handle. ++ * ++ * We loop over a list of fbconfigs trying to create ++ * a pixel buffer. We return the first pixel buffer which we successfully ++ * create. ++ */ ++static PBUFFER ++MakePbuffer( Display *dpy, int screen, int width, int height ) ++{ ++#define NUM_FB_CONFIGS 4 ++ const char fbString[NUM_FB_CONFIGS][100] = { ++ "Single Buffered, depth buffer", ++ "Double Buffered, depth buffer", ++ "Single Buffered, no depth buffer", ++ "Double Buffered, no depth buffer" ++ }; ++ int fbAttribs[NUM_FB_CONFIGS][100] = { ++ { ++ /* Single buffered, with depth buffer */ ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DEPTH_SIZE, 1, ++ GLX_DOUBLEBUFFER, 0, ++ GLX_STENCIL_SIZE, 0, ++ None ++ }, ++ { ++ /* Double buffered, with depth buffer */ ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DEPTH_SIZE, 1, ++ GLX_DOUBLEBUFFER, 1, ++ GLX_STENCIL_SIZE, 0, ++ None ++ }, ++ { ++ /* Single buffered, without depth buffer */ ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DEPTH_SIZE, 0, ++ GLX_DOUBLEBUFFER, 0, ++ GLX_STENCIL_SIZE, 0, ++ None ++ }, ++ { ++ /* Double buffered, without depth buffer */ ++ GLX_RENDER_TYPE, GLX_RGBA_BIT, ++ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DEPTH_SIZE, 0, ++ GLX_DOUBLEBUFFER, 1, ++ GLX_STENCIL_SIZE, 0, ++ None ++ } ++ }; ++ Bool largest = True; ++ Bool preserve = False; ++ FBCONFIG *fbConfigs; ++ PBUFFER pBuffer = None; ++ int nConfigs; ++ int i; ++ int attempt; ++ ++ for (attempt=0; attempt x1) { ++ tmp = x0; ++ x0 = x1; ++ x1 = tmp; ++ } ++ if (y0 > y1) { ++ tmp = y0; ++ y0 = y1; ++ y1 = tmp; ++ } ++ if (z0 > z1) { ++ tmp = z0; ++ z0 = z1; ++ z1 = tmp; ++ } ++ v[0][0] = v[1][0] = v[2][0] = v[3][0] = x0; ++ v[4][0] = v[5][0] = v[6][0] = v[7][0] = x1; ++ v[0][1] = v[1][1] = v[4][1] = v[5][1] = y0; ++ v[2][1] = v[3][1] = v[6][1] = v[7][1] = y1; ++ v[0][2] = v[3][2] = v[4][2] = v[7][2] = z0; ++ v[1][2] = v[2][2] = v[5][2] = v[6][2] = z1; ++ ++ for (i = 0; i < 6; i++) { ++ glBegin(type); ++ glNormal3fv(&n[i][0]); ++ glVertex3fv(&v[faces[i][0]][0]); ++ glVertex3fv(&v[faces[i][1]][0]); ++ glVertex3fv(&v[faces[i][2]][0]); ++ glVertex3fv(&v[faces[i][3]][0]); ++ glEnd(); ++ } ++} ++ ++ ++ ++/* Render a scene */ ++static void ++Render(void) ++{ ++ int NumBoxes = 100; ++ int i; ++ ++ glClearColor(0.2, 0.2, 0.9, 0.0); ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ for (i=0;i ++#include ++#include ++#include "pbutil.h" ++ ++ ++ ++ ++static void ++PrintConfigs(Display *dpy, int screen, Bool horizFormat) ++{ ++ FBCONFIG *fbConfigs; ++ int nConfigs; ++ int i; ++ ++ fbConfigs = GetAllFBConfigs(dpy, screen, &nConfigs); ++ if (!nConfigs || !fbConfigs) { ++ printf("Error: glxGetFBConfigs failed\n"); ++ XFree(fbConfigs); ++ return; ++ } ++ ++ printf("Number of fbconfigs: %d\n", nConfigs); ++ ++ if (horizFormat) { ++ printf(" ID VisualType Depth Lvl RGB CI DB Stereo R G B A"); ++ printf(" Z S AR AG AB AA MSbufs MSnum Pbuffer Float\n"); ++ } ++ ++ /* Print config info */ ++ for (i = 0; i < nConfigs; i++) { ++ PrintFBConfigInfo(dpy, screen, fbConfigs[i], horizFormat); ++ } ++ ++ /* free the list */ ++ XFree(fbConfigs); ++} ++ ++ ++ ++static void ++PrintUsage(void) ++{ ++ printf("Options:\n"); ++ printf(" -display specify X display name\n"); ++ printf(" -t print in tabular format\n"); ++ printf(" -v print in verbose format\n"); ++ printf(" -help print this information\n"); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ int scrn; ++ char *dpyName = NULL; ++ Bool horizFormat = True; ++ int i; ++ ++ for (i=1; i ++#include ++#include "pbutil.h" ++ ++ ++/** ++ * Test if we pixel buffers are available for a particular X screen. ++ * Input: dpy - the X display ++ * screen - screen number ++ * Return: 0 = fbconfigs not available. ++ * 1 = fbconfigs are available via GLX 1.3. ++ * 2 = fbconfigs and pbuffers are available via GLX_SGIX_fbconfig ++ */ ++int ++QueryFBConfig(Display *dpy, int screen) ++{ ++#if defined(GLX_VERSION_1_3) ++ { ++ /* GLX 1.3 supports pbuffers */ ++ int glxVersionMajor, glxVersionMinor; ++ if (!glXQueryVersion(dpy, &glxVersionMajor, &glxVersionMinor)) { ++ /* GLX not available! */ ++ return 0; ++ } ++ if (glxVersionMajor * 100 + glxVersionMinor >= 103) { ++ return 1; ++ } ++ /* fall-through */ ++ } ++#endif ++ ++ /* Try the SGIX extensions */ ++ { ++ char *extensions; ++ extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS); ++ if (extensions && strstr(extensions,"GLX_SGIX_fbconfig")) { ++ return 2; ++ } ++ } ++ ++ return 0; ++} ++ ++/** ++ * Test if we pixel buffers are available for a particular X screen. ++ * Input: dpy - the X display ++ * screen - screen number ++ * Return: 0 = pixel buffers not available. ++ * 1 = pixel buffers are available via GLX 1.3. ++ * 2 = pixel buffers are available via GLX_SGIX_fbconfig/pbuffer. ++ */ ++int ++QueryPbuffers(Display *dpy, int screen) ++{ ++ int ret; ++ ++ ret = QueryFBConfig(dpy, screen); ++ if (ret == 2) { ++ char *extensions; ++ extensions = (char *) glXQueryServerString(dpy, screen, GLX_EXTENSIONS); ++ if (extensions && strstr(extensions, "GLX_SGIX_pbuffer")) ++ return 2; ++ else ++ return 0; ++ } ++ else ++ return ret; ++} ++ ++FBCONFIG * ++ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs) ++{ ++ int fbcSupport = QueryPbuffers(dpy, screen); ++#if defined(GLX_VERSION_1_3) ++ if (fbcSupport == 1) { ++ return glXChooseFBConfig(dpy, screen, attribs, nConfigs); ++ } ++#endif ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (fbcSupport == 2) { ++ return glXChooseFBConfigSGIX(dpy, screen, (int *) attribs, nConfigs); ++ } ++#endif ++ return NULL; ++} ++ ++ ++FBCONFIG * ++GetAllFBConfigs(Display *dpy, int screen, int *nConfigs) ++{ ++ int fbcSupport = QueryFBConfig(dpy, screen); ++#if defined(GLX_VERSION_1_3) ++ if (fbcSupport == 1) { ++ return glXGetFBConfigs(dpy, screen, nConfigs); ++ } ++#endif ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (fbcSupport == 2) { ++ /* The GLX_SGIX_fbconfig extensions says to pass NULL to get list ++ * of all available configurations. ++ */ ++ return glXChooseFBConfigSGIX(dpy, screen, NULL, nConfigs); ++ } ++#endif ++ return NULL; ++} ++ ++ ++XVisualInfo * ++GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config) ++{ ++ int fbcSupport = QueryFBConfig(dpy, screen); ++#if defined(GLX_VERSION_1_3) ++ if (fbcSupport == 1) { ++ return glXGetVisualFromFBConfig(dpy, config); ++ } ++#endif ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (fbcSupport == 2) { ++ return glXGetVisualFromFBConfigSGIX(dpy, config); ++ } ++#endif ++ return NULL; ++} ++ ++ ++/** ++ * Either use glXGetFBConfigAttrib() or glXGetFBConfigAttribSGIX() ++ * to query an fbconfig attribute. ++ */ ++static int ++GetFBConfigAttrib(Display *dpy, int screen, ++#if defined(GLX_VERSION_1_3) ++ const GLXFBConfig config, ++#elif defined(GLX_SGIX_fbconfig) ++ const GLXFBConfigSGIX config, ++#endif ++ int attrib ++ ) ++{ ++ int fbcSupport = QueryFBConfig(dpy, screen); ++ int value = 0; ++ ++#if defined(GLX_VERSION_1_3) ++ if (fbcSupport == 1) { ++ /* ok */ ++ if (glXGetFBConfigAttrib(dpy, config, attrib, &value) != 0) { ++ value = 0; ++ } ++ return value; ++ } ++ /* fall-through */ ++#endif ++ ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (fbcSupport == 2) { ++ if (glXGetFBConfigAttribSGIX(dpy, config, attrib, &value) != 0) { ++ value = 0; ++ } ++ return value; ++ } ++#endif ++ ++ return value; ++} ++ ++ ++ ++/** ++ * Print parameters for a GLXFBConfig to stdout. ++ * Input: dpy - the X display ++ * screen - the X screen number ++ * fbConfig - the fbconfig handle ++ * horizFormat - if true, print in horizontal format ++ */ ++void ++PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat) ++{ ++ PBUFFER pBuffer; ++ int width=2, height=2; ++ int bufferSize, level, doubleBuffer, stereo, auxBuffers; ++ int redSize, greenSize, blueSize, alphaSize; ++ int depthSize, stencilSize; ++ int accumRedSize, accumBlueSize, accumGreenSize, accumAlphaSize; ++ int sampleBuffers, samples; ++ int drawableType, renderType, xRenderable, xVisual, id; ++ int maxWidth, maxHeight, maxPixels; ++ int optWidth, optHeight; ++ int floatComponents = 0; ++ ++ /* do queries using the GLX 1.3 tokens (same as the SGIX tokens) */ ++ bufferSize = GetFBConfigAttrib(dpy, screen, config, GLX_BUFFER_SIZE); ++ level = GetFBConfigAttrib(dpy, screen, config, GLX_LEVEL); ++ doubleBuffer = GetFBConfigAttrib(dpy, screen, config, GLX_DOUBLEBUFFER); ++ stereo = GetFBConfigAttrib(dpy, screen, config, GLX_STEREO); ++ auxBuffers = GetFBConfigAttrib(dpy, screen, config, GLX_AUX_BUFFERS); ++ redSize = GetFBConfigAttrib(dpy, screen, config, GLX_RED_SIZE); ++ greenSize = GetFBConfigAttrib(dpy, screen, config, GLX_GREEN_SIZE); ++ blueSize = GetFBConfigAttrib(dpy, screen, config, GLX_BLUE_SIZE); ++ alphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ALPHA_SIZE); ++ depthSize = GetFBConfigAttrib(dpy, screen, config, GLX_DEPTH_SIZE); ++ stencilSize = GetFBConfigAttrib(dpy, screen, config, GLX_STENCIL_SIZE); ++ accumRedSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_RED_SIZE); ++ accumGreenSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_GREEN_SIZE); ++ accumBlueSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_BLUE_SIZE); ++ accumAlphaSize = GetFBConfigAttrib(dpy, screen, config, GLX_ACCUM_ALPHA_SIZE); ++ sampleBuffers = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLE_BUFFERS); ++ samples = GetFBConfigAttrib(dpy, screen, config, GLX_SAMPLES); ++ drawableType = GetFBConfigAttrib(dpy, screen, config, GLX_DRAWABLE_TYPE); ++ renderType = GetFBConfigAttrib(dpy, screen, config, GLX_RENDER_TYPE); ++ xRenderable = GetFBConfigAttrib(dpy, screen, config, GLX_X_RENDERABLE); ++ xVisual = GetFBConfigAttrib(dpy, screen, config, GLX_X_VISUAL_TYPE); ++ if (!xRenderable || !(drawableType & GLX_WINDOW_BIT_SGIX)) ++ xVisual = -1; ++ ++ id = GetFBConfigAttrib(dpy, screen, config, GLX_FBCONFIG_ID); ++ maxWidth = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_WIDTH); ++ maxHeight = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_HEIGHT); ++ maxPixels = GetFBConfigAttrib(dpy, screen, config, GLX_MAX_PBUFFER_PIXELS); ++#if defined(GLX_SGIX_pbuffer) ++ optWidth = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_WIDTH_SGIX); ++ optHeight = GetFBConfigAttrib(dpy, screen, config, GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX); ++#else ++ optWidth = optHeight = 0; ++#endif ++#if defined(GLX_NV_float_buffer) ++ floatComponents = GetFBConfigAttrib(dpy, screen, config, GLX_FLOAT_COMPONENTS_NV); ++#endif ++ ++ /* See if we can create a pbuffer with this config */ ++ pBuffer = CreatePbuffer(dpy, screen, config, width, height, False, False); ++ ++ if (horizFormat) { ++ printf("0x%-9x ", id); ++ if (xVisual==GLX_STATIC_GRAY) printf("StaticGray "); ++ else if (xVisual==GLX_GRAY_SCALE) printf("GrayScale "); ++ else if (xVisual==GLX_STATIC_COLOR) printf("StaticColor "); ++ else if (xVisual==GLX_PSEUDO_COLOR) printf("PseudoColor "); ++ else if (xVisual==GLX_TRUE_COLOR) printf("TrueColor "); ++ else if (xVisual==GLX_DIRECT_COLOR) printf("DirectColor "); ++ else printf(" -none- "); ++ printf(" %3d %3d %s %s %s %2s ", bufferSize, level, ++ (renderType & GLX_RGBA_BIT_SGIX) ? "y" : ".", ++ (renderType & GLX_COLOR_INDEX_BIT_SGIX) ? "y" : ".", ++ doubleBuffer ? "y" : ".", ++ stereo ? "y" : "."); ++ printf("%2d %2d %2d %2d ", redSize, greenSize, blueSize, alphaSize); ++ printf("%2d %2d ", depthSize, stencilSize); ++ printf("%2d %2d %2d %2d", accumRedSize, accumGreenSize, accumBlueSize, ++ accumAlphaSize); ++ printf(" %2d %2d", sampleBuffers, samples); ++ printf(" %s %c", pBuffer ? "y" : ".", ++ ".y"[floatComponents]); ++ printf("\n"); ++ } ++ else { ++ printf("Id 0x%x\n", id); ++ printf(" Buffer Size: %d\n", bufferSize); ++ printf(" Level: %d\n", level); ++ printf(" Double Buffer: %s\n", doubleBuffer ? "yes" : "no"); ++ printf(" Stereo: %s\n", stereo ? "yes" : "no"); ++ printf(" Aux Buffers: %d\n", auxBuffers); ++ printf(" Red Size: %d\n", redSize); ++ printf(" Green Size: %d\n", greenSize); ++ printf(" Blue Size: %d\n", blueSize); ++ printf(" Alpha Size: %d\n", alphaSize); ++ printf(" Depth Size: %d\n", depthSize); ++ printf(" Stencil Size: %d\n", stencilSize); ++ printf(" Accum Red Size: %d\n", accumRedSize); ++ printf(" Accum Green Size: %d\n", accumGreenSize); ++ printf(" Accum Blue Size: %d\n", accumBlueSize); ++ printf(" Accum Alpha Size: %d\n", accumAlphaSize); ++ printf(" Sample Buffers: %d\n", sampleBuffers); ++ printf(" Samples/Pixel: %d\n", samples); ++ printf(" Drawable Types: "); ++ if (drawableType & GLX_WINDOW_BIT) printf("Window "); ++ if (drawableType & GLX_PIXMAP_BIT) printf("Pixmap "); ++ if (drawableType & GLX_PBUFFER_BIT) printf("PBuffer"); ++ printf("\n"); ++ printf(" Render Types: "); ++ if (renderType & GLX_RGBA_BIT_SGIX) printf("RGBA "); ++ if (renderType & GLX_COLOR_INDEX_BIT_SGIX) printf("CI "); ++ printf("\n"); ++ printf(" X Renderable: %s\n", xRenderable ? "yes" : "no"); ++ ++ printf(" Pbuffer: %s\n", pBuffer ? "yes" : "no"); ++ printf(" Max Pbuffer width: %d\n", maxWidth); ++ printf(" Max Pbuffer height: %d\n", maxHeight); ++ printf(" Max Pbuffer pixels: %d\n", maxPixels); ++ printf(" Optimum Pbuffer width: %d\n", optWidth); ++ printf(" Optimum Pbuffer height: %d\n", optHeight); ++ ++ printf(" Float Components: %s\n", floatComponents ? "yes" : "no"); ++ } ++ ++ if (pBuffer) { ++ DestroyPbuffer(dpy, screen, pBuffer); ++ } ++} ++ ++ ++ ++GLXContext ++CreateContext(Display *dpy, int screen, FBCONFIG config) ++{ ++ int fbcSupport = QueryFBConfig(dpy, screen); ++#if defined(GLX_VERSION_1_3) ++ if (fbcSupport == 1) { ++ /* GLX 1.3 */ ++ GLXContext c; ++ c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, True); ++ if (!c) { ++ /* try indirect */ ++ c = glXCreateNewContext(dpy, config, GLX_RGBA_TYPE, NULL, False); ++ } ++ return c; ++ } ++#endif ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (fbcSupport == 2) { ++ GLXContext c; ++ c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, True); ++ if (!c) { ++ c = glXCreateContextWithConfigSGIX(dpy, config, GLX_RGBA_TYPE_SGIX, NULL, False); ++ } ++ return c; ++ } ++#endif ++ return 0; ++} ++ ++ ++void ++DestroyContext(Display *dpy, GLXContext ctx) ++{ ++ glXDestroyContext(dpy, ctx); ++} ++ ++ ++/* This is only used by CreatePbuffer() */ ++static int XErrorFlag = 0; ++static int HandleXError(Display *dpy, XErrorEvent *event) ++{ ++ XErrorFlag = 1; ++ return 0; ++} ++ ++ ++/** ++ * Create a Pbuffer. Use an X error handler to deal with potential ++ * BadAlloc errors. ++ * ++ * Input: dpy - the X display ++ * fbConfig - an FBConfig as returned by glXChooseFBConfigSGIX(). ++ * width, height - size of pixel buffer to request, in pixels. ++ * pbAttribs - list of optional pixel buffer attributes ++ * Return: a Pbuffer or None. ++ */ ++PBUFFER ++CreatePbuffer(Display *dpy, int screen, FBCONFIG config, ++ int width, int height, Bool largest, Bool preserve) ++{ ++ int (*oldHandler)(Display *, XErrorEvent *); ++ PBUFFER pBuffer = None; ++ int pbSupport = QueryPbuffers(dpy, screen); ++ ++ /* Catch X protocol errors with our own error handler */ ++ oldHandler = XSetErrorHandler(HandleXError); ++ XErrorFlag = 0; ++ ++#if defined(GLX_VERSION_1_3) ++ if (pbSupport == 1) { ++ /* GLX 1.3 */ ++ int attribs[100], i = 0; ++ attribs[i++] = GLX_PBUFFER_WIDTH; ++ attribs[i++] = width; ++ attribs[i++] = GLX_PBUFFER_HEIGHT; ++ attribs[i++] = height; ++ attribs[i++] = GLX_PRESERVED_CONTENTS; ++ attribs[i++] = preserve; ++ attribs[i++] = GLX_LARGEST_PBUFFER; ++ attribs[i++] = largest; ++ attribs[i++] = 0; ++ pBuffer = glXCreatePbuffer(dpy, config, attribs); ++ } ++ else ++#endif ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (pbSupport == 2) { ++ int attribs[100], i = 0; ++ attribs[i++] = GLX_PRESERVED_CONTENTS; ++ attribs[i++] = preserve; ++ attribs[i++] = GLX_LARGEST_PBUFFER; ++ attribs[i++] = largest; ++ attribs[i++] = 0; ++ pBuffer = glXCreateGLXPbufferSGIX(dpy, config, width, height, attribs); ++ } ++ else ++#endif ++ { ++ pBuffer = None; ++ } ++ ++ XSync(dpy, False); ++ /* Restore original X error handler */ ++ (void) XSetErrorHandler(oldHandler); ++ ++ /* Return pbuffer (may be None) */ ++ if (!XErrorFlag && pBuffer != None) { ++ /*printf("config %d worked!\n", i);*/ ++ return pBuffer; ++ } ++ else { ++ return None; ++ } ++} ++ ++ ++void ++DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer) ++{ ++ int pbSupport = QueryPbuffers(dpy, screen); ++#if defined(GLX_VERSION_1_3) ++ if (pbSupport == 1) { ++ glXDestroyPbuffer(dpy, pbuffer); ++ return; ++ } ++#endif ++#if defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++ if (pbSupport == 2) { ++ glXDestroyGLXPbufferSGIX(dpy, pbuffer); ++ return; ++ } ++#endif ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/pbutil.h Mesa-7.8.1.patched/progs/xdemos/pbutil.h +--- Mesa-7.8.1/progs/xdemos/pbutil.h 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/pbutil.h 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,69 @@ ++/* ++ * OpenGL pbuffers utility functions. ++ * ++ * Brian Paul ++ * April 1997 ++ */ ++ ++ ++#ifndef PBUTIL_H ++#define PBUTIL_H ++ ++ ++#define GLX_GLXEXT_PROTOTYPES ++#include ++ ++ ++#if defined(GLX_VERSION_1_3) ++#define PBUFFER GLXPbuffer ++#define FBCONFIG GLXFBConfig ++#elif defined(GLX_SGIX_fbconfig) && defined(GLX_SGIX_pbuffer) ++#define PBUFFER GLXPbufferSGIX ++#define FBCONFIG GLXFBConfigSGIX ++#else ++#define PBUFFER int ++#define FBCONFIG int ++#endif ++ ++ ++extern int ++QueryFBConfig(Display *dpy, int screen); ++ ++extern int ++QueryPbuffers(Display *dpy, int screen); ++ ++ ++extern void ++PrintFBConfigInfo(Display *dpy, int screen, FBCONFIG config, Bool horizFormat); ++ ++ ++extern FBCONFIG * ++ChooseFBConfig(Display *dpy, int screen, const int attribs[], int *nConfigs); ++ ++ ++extern FBCONFIG * ++GetAllFBConfigs(Display *dpy, int screen, int *nConfigs); ++ ++ ++extern XVisualInfo * ++GetVisualFromFBConfig(Display *dpy, int screen, FBCONFIG config); ++ ++ ++extern GLXContext ++CreateContext(Display *dpy, int screen, FBCONFIG config); ++ ++ ++extern void ++DestroyContext(Display *dpy, GLXContext ctx); ++ ++ ++extern PBUFFER ++CreatePbuffer(Display *dpy, int screen, FBCONFIG config, ++ int width, int height, Bool preserve, Bool largest); ++ ++ ++extern void ++DestroyPbuffer(Display *dpy, int screen, PBUFFER pbuffer); ++ ++ ++#endif /*PBUTIL_H*/ +diff -Naurp Mesa-7.8.1/progs/xdemos/shape.c Mesa-7.8.1.patched/progs/xdemos/shape.c +--- Mesa-7.8.1/progs/xdemos/shape.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/shape.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,393 @@ ++ ++/* ++ * Example of using the X "shape" extension with OpenGL: render a spinning ++ * cube inside of a non-rectangular window. ++ * ++ * Press ESC to exit. Press up/down to change window shape. ++ * ++ * To compile add "shape" to the PROGS list in Makefile. ++ * ++ * Brian Paul ++ * June 16, 1997 ++ * ++ * This program is in the public domain. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#ifndef PI ++#define PI 3.1415926 ++#endif ++ ++ ++static int Width=500, Height=500; ++ ++static float Xangle = 0.0, Yangle = 0.0; ++static int Sides = 5; ++static int MinSides = 3; ++static int MaxSides = 20; ++ ++ ++/* return current time (in seconds) */ ++static double ++current_time(void) ++{ ++ struct timeval tv; ++#ifdef __VMS ++ (void) gettimeofday(&tv, NULL ); ++#else ++ struct timezone tz; ++ (void) gettimeofday(&tv, &tz); ++#endif ++ return (double) tv.tv_sec + tv.tv_usec / 1000000.0; ++} ++ ++ ++/* ++ * Draw the OpenGL stuff and do a SwapBuffers. ++ */ ++static void display(Display *dpy, Window win) ++{ ++ float scale = 1.7; ++ ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glPushMatrix(); ++ ++ glScalef(scale, scale, scale); ++ glRotatef(Xangle, 1.0, 0.0, 0.0); ++ glRotatef(Yangle, 0.0, 1.0, 0.0); ++ ++ /* ++ * wireframe box ++ */ ++ glColor3f(1.0, 1.0, 1.0); ++ glBegin(GL_LINE_LOOP); ++ glVertex3f(-1.0, -1.0, -1.0); ++ glVertex3f( 1.0, -1.0, -1.0); ++ glVertex3f( 1.0, 1.0, -1.0); ++ glVertex3f(-1.0, 1.0, -1.0); ++ glEnd(); ++ ++ glBegin(GL_LINE_LOOP); ++ glVertex3f(-1.0, -1.0, 1.0); ++ glVertex3f( 1.0, -1.0, 1.0); ++ glVertex3f( 1.0, 1.0, 1.0); ++ glVertex3f(-1.0, 1.0, 1.0); ++ glEnd(); ++ ++ glBegin(GL_LINES); ++ glVertex3f(-1.0, -1.0, -1.0); glVertex3f(-1.0, -1.0, 1.0); ++ glVertex3f( 1.0, -1.0, -1.0); glVertex3f( 1.0, -1.0, 1.0); ++ glVertex3f( 1.0, 1.0, -1.0); glVertex3f( 1.0, 1.0, 1.0); ++ glVertex3f(-1.0, 1.0, -1.0); glVertex3f(-1.0, 1.0, 1.0); ++ glEnd(); ++ ++ /* ++ * Solid box ++ */ ++ glPushMatrix(); ++ glScalef(0.75, 0.75, 0.75); ++ ++ glColor3f(1, 0, 0); ++ glBegin(GL_POLYGON); ++ glVertex3f(1, -1, -1); ++ glVertex3f(1, 1, -1); ++ glVertex3f(1, 1, 1); ++ glVertex3f(1, -1, 1); ++ glEnd(); ++ ++ glColor3f(0, 1, 1); ++ glBegin(GL_POLYGON); ++ glVertex3f(-1, -1, -1); ++ glVertex3f(-1, 1, -1); ++ glVertex3f(-1, 1, 1); ++ glVertex3f(-1, -1, 1); ++ glEnd(); ++ ++ glColor3f(0, 1, 0); ++ glBegin(GL_POLYGON); ++ glVertex3f(-1, 1, -1); ++ glVertex3f( 1, 1, -1); ++ glVertex3f( 1, 1, 1); ++ glVertex3f(-1, 1, 1); ++ glEnd(); ++ ++ glColor3f(1, 0, 1); ++ glBegin(GL_POLYGON); ++ glVertex3f(-1, -1, -1); ++ glVertex3f( 1, -1, -1); ++ glVertex3f( 1, -1, 1); ++ glVertex3f(-1, -1, 1); ++ glEnd(); ++ ++ glColor3f(0, 0, 1); ++ glBegin(GL_POLYGON); ++ glVertex3f(-1, -1, 1); ++ glVertex3f( 1, -1, 1); ++ glVertex3f( 1, 1, 1); ++ glVertex3f(-1, 1, 1); ++ glEnd(); ++ ++ glColor3f(1, 1, 0); ++ glBegin(GL_POLYGON); ++ glVertex3f(-1, -1, -1); ++ glVertex3f( 1, -1, -1); ++ glVertex3f( 1, 1, -1); ++ glVertex3f(-1, 1, -1); ++ glEnd(); ++ glPopMatrix(); ++ ++ ++ glPopMatrix(); ++ ++ glXSwapBuffers(dpy, win); ++} ++ ++ ++/* ++ * This is called when we have to recompute the window shape bitmask. ++ * We just generate an n-sided regular polygon here but any other shape ++ * would be possible. ++ */ ++static void make_shape_mask(Display *dpy, Window win, int width, int height, ++ int sides) ++{ ++ Pixmap shapeMask; ++ XGCValues xgcv; ++ GC gc; ++ ++ /* allocate 1-bit deep pixmap and a GC */ ++ shapeMask = XCreatePixmap(dpy, win, width, height, 1); ++ gc = XCreateGC(dpy, shapeMask, 0, &xgcv); ++ ++ /* clear shapeMask to zeros */ ++ XSetForeground(dpy, gc, 0); ++ XFillRectangle(dpy, shapeMask, gc, 0, 0, width, height); ++ ++ /* draw mask */ ++ XSetForeground(dpy, gc, 1); ++ { ++ int cx = width / 2; ++ int cy = height / 2; ++ float angle = 0.0; ++ float step = 2.0 * PI / sides; ++ float radius = width / 2; ++ int i; ++ XPoint points[100]; ++ for (i=0;iMaxSides) Sides = MaxSides; ++ make_shape_mask(dpy, win, Width, Height, Sides); ++ break; ++ case XK_Down: ++ Sides--; ++ if (Sidesvisual); ++ if (!cmap) { ++ fprintf(stderr, "Couln't create colormap\n"); ++ return 1; ++ } ++ ++ winAttribs.border_pixel = 0; ++ winAttribs.colormap = cmap; ++ winAttribs.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ winAttribsMask = CWBorderPixel | CWColormap | CWEventMask; ++ win = XCreateWindow(dpy, root, 0, 0, Width, Height, 0, ++ visInfo->depth, InputOutput, ++ visInfo->visual, ++ winAttribsMask, &winAttribs); ++ ++ { ++ XSizeHints sizehints; ++ /* ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ */ ++ sizehints.flags = 0; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ++ XMapWindow(dpy, win); ++ ++ glXMakeCurrent(dpy, win, glCtx); ++ ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("Press ESC to exit.\n"); ++ printf("Press up/down to change window shape.\n"); ++ ++ event_loop(dpy, win); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/sharedtex.c Mesa-7.8.1.patched/progs/xdemos/sharedtex.c +--- Mesa-7.8.1/progs/xdemos/sharedtex.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/sharedtex.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,324 @@ ++/* ++ * Test sharing of texture objects by two rendering contexts. ++ * In particular, test that changing a texture object in one context ++ * effects the texture in the second context. ++ * ++ * Brian Paul ++ * 30 Apr 2008 ++ * ++ * Copyright (C) 2008 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. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define MAX_CONTEXTS 2 ++ ++#define TEX_SIZE 32 ++ ++static const char *DisplayName = NULL; ++static Display *Dpy; ++static XVisualInfo *VisInfo; ++static Window Win; ++static GLXContext Contexts[MAX_CONTEXTS]; ++static int WinWidth = 300, WinHeight = 300; ++ ++static int DrawContext = 0, TexContext = 1; ++ ++static GLuint TexObj = 0; ++static GLboolean NewTexture = GL_FALSE; ++ ++ ++static void ++Error(const char *msg) ++{ ++ fprintf(stderr, "sharedtex error: %s\n", msg); ++ exit(1); ++} ++ ++ ++static void ++CreateWindow(const char *name) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ int xpos = 0, ypos = 0; ++ static int n = 0; ++ ++ scrnum = DefaultScreen(Dpy); ++ root = RootWindow(Dpy, scrnum); ++ ++ VisInfo = glXChooseVisual(Dpy, scrnum, attrib); ++ if (!VisInfo) { ++ Error("Unable to find RGB, double-buffered visual"); ++ } ++ ++ /* window attributes */ ++ xpos = (n % 10) * 100; ++ ypos = (n / 10) * 100; ++ n++; ++ ++ 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, xpos, ypos, WinWidth, WinHeight, ++ 0, VisInfo->depth, InputOutput, ++ VisInfo->visual, mask, &attr); ++ if (!Win) { ++ Error("Couldn't create window"); ++ } ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = WinWidth; ++ sizehints.height = WinHeight; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(Dpy, Win, &sizehints); ++ XSetStandardProperties(Dpy, Win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ XMapWindow(Dpy, Win); ++} ++ ++ ++/** ++ * Change texture image, using TexContext ++ */ ++static void ++ModifyTexture(void) ++{ ++ GLuint tex[TEX_SIZE][TEX_SIZE]; ++ GLuint c0, c1; ++ int i, j; ++ ++ if (Win && !glXMakeCurrent(Dpy, Win, Contexts[TexContext])) { ++ Error("glXMakeCurrent failed"); ++ } ++ ++ /* choose two random colors */ ++ c0 = rand() & 0xffffffff; ++ c1 = rand() & 0xffffffff; ++ ++ for (i = 0; i < TEX_SIZE; i++) { ++ for (j = 0; j < TEX_SIZE; j++) { ++ if (((i / 4) ^ (j / 4)) & 1) { ++ tex[i][j] = c0; ++ } ++ else { ++ tex[i][j] = c1; ++ } ++ } ++ } ++ ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TEX_SIZE, TEX_SIZE, 0, ++ GL_RGBA, GL_UNSIGNED_BYTE, tex); ++ ++ NewTexture = GL_TRUE; ++} ++ ++ ++static void ++InitContext(void) ++{ ++ glGenTextures(1, &TexObj); ++ assert(TexObj); ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++ glEnable(GL_TEXTURE_2D); ++ ++ printf("GL_RENDERER = %s\n", (char*) glGetString(GL_RENDERER)); ++} ++ ++ ++static void ++Setup(void) ++{ ++ int i; ++ ++ Dpy = XOpenDisplay(DisplayName); ++ if (!Dpy) { ++ Error("Unable to open display"); ++ } ++ ++ CreateWindow("sharedtex"); ++ ++ for (i = 0; i < MAX_CONTEXTS; i++) { ++ GLXContext share = i > 0 ? Contexts[0] : 0; ++ ++ Contexts[i] = glXCreateContext(Dpy, VisInfo, share, True); ++ if (!Contexts[i]) { ++ Error("Unable to create GLX context"); ++ } ++ ++ if (!glXMakeCurrent(Dpy, Win, Contexts[i])) { ++ Error("glXMakeCurrent failed"); ++ } ++ ++ InitContext(); ++ } ++ ++ ModifyTexture(); ++} ++ ++ ++/** ++ * Redraw window, using DrawContext ++ */ ++static void ++Redraw(void) ++{ ++ static float rot = 0.0; ++ float ar; ++ ++ rot += 1.0; ++ ++ if (Win && !glXMakeCurrent(Dpy, Win, Contexts[DrawContext])) { ++ Error("glXMakeCurrent failed"); ++ } ++ ++ glViewport(0, 0, WinWidth, WinHeight); ++ ar = (float) WinWidth / (float) WinHeight; ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-ar, ar, -1.0, 1.0, -1.0, 1.0); ++ glMatrixMode(GL_MODELVIEW); ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.5, 0.5, 0.5, 1.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ glPushMatrix(); ++ glRotatef(rot, 0, 0, 1); ++ glScalef(0.7, 0.7, 0.7); ++ ++ if (NewTexture) { ++ /* rebind to get new contents */ ++ glBindTexture(GL_TEXTURE_2D, TexObj); ++ NewTexture = GL_FALSE; ++ } ++ ++ /* draw textured quad */ ++ glBegin(GL_POLYGON); ++ glTexCoord2f( 0.0, 0.0 ); glVertex2f( -1.0, -1.0 ); ++ glTexCoord2f( 1.0, 0.0 ); glVertex2f( 1.0, -1.0 ); ++ glTexCoord2f( 1.0, 1.0 ); glVertex2f( 1.0, 1.0 ); ++ glTexCoord2f( 0.0, 1.0 ); glVertex2f( -1.0, 1.0 ); ++ glEnd(); ++ ++ glPopMatrix(); ++ ++ if (Win) ++ glXSwapBuffers(Dpy, Win); ++} ++ ++ ++static void ++EventLoop(void) ++{ ++ while (1) { ++ while (XPending(Dpy) > 0) { ++ XEvent event; ++ XNextEvent(Dpy, &event); ++ ++ switch (event.type) { ++ case Expose: ++ Redraw(); ++ break; ++ case ConfigureNotify: ++ WinWidth = event.xconfigure.width; ++ WinHeight = event.xconfigure.height; ++ break; ++ case KeyPress: ++ { ++ char buf[100]; ++ KeySym keySym; ++ XComposeStatus stat; ++ XLookupString(&event.xkey, buf, sizeof(buf), &keySym, &stat); ++ switch (keySym) { ++ case XK_Escape: ++ exit(0); ++ break; ++ case XK_t: ++ case XK_T: ++ ModifyTexture(); ++ break; ++ default: ++ ; ++ } ++ } ++ Redraw(); ++ break; ++ default: ++ /*no-op*/ ; ++ } ++ } ++ ++ Redraw(); ++ usleep(10000); ++ } ++} ++ ++ ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0 && i < argc) { ++ DisplayName = argv[i+1]; ++ i++; ++ } ++ } ++ ++ Setup(); ++ ++ printf("Press 't' to change texture image/colors\n"); ++ ++ EventLoop(); ++ ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/sharedtex_mt.c Mesa-7.8.1.patched/progs/xdemos/sharedtex_mt.c +--- Mesa-7.8.1/progs/xdemos/sharedtex_mt.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/sharedtex_mt.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,490 @@ ++/* $Id: sharedtex.c,v 1.2 2002/01/16 14:32:46 joukj Exp $ */ ++ ++/* ++ * Test sharing of display lists and texture objects between GLX contests. ++ * Brian Paul ++ * Summer 2000 ++ * ++ * ++ * Copyright (C) 2000 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. ++ * ++ * ++ * Modified 2009 for multithreading by Thomas Hellstrom. ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++struct thread_init_arg { ++ int id; ++}; ++ ++struct window { ++ pthread_mutex_t drawMutex; ++ char DisplayName[1000]; ++ Display *Dpy; ++ Window Win; ++ GLXContext Context; ++ float Angle; ++ int Id; ++ XVisualInfo *visInfo; ++}; ++ ++ ++#define MAX_WINDOWS 20 ++static struct window Windows[MAX_WINDOWS]; ++static int NumWindows = 0; ++static int terminate = 0; ++static GLXContext gCtx; ++static Display *gDpy; ++static GLuint Textures[3]; ++ ++ ++ ++static void ++Error(const char *display, const char *msg) ++{ ++ fprintf(stderr, "Error on display %s - %s\n", display, msg); ++ exit(1); ++} ++ ++ ++static int ++initMainthread(Display *dpy, const char *displayName) ++{ ++ int scrnum; ++ XVisualInfo *visinfo; ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ ++ scrnum = DefaultScreen(dpy); ++ visinfo = glXChooseVisual(dpy, scrnum, attrib); ++ if (!visinfo) { ++ Error(displayName, "Unable to find RGB, double-buffered visual"); ++ return -1; ++ } ++ gCtx = glXCreateContext(dpy, visinfo, NULL, True); ++ if (!gCtx) { ++ Error(displayName, "Couldn't create GLX context"); ++ return -1; ++ } ++ return 0; ++} ++ ++static struct window * ++AddWindow(Display *dpy, const char *displayName, int xpos, int ypos, ++ GLXContext sCtx) ++{ ++ Window win; ++ GLXContext ctx; ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ XVisualInfo *visinfo; ++ int width = 300, height = 300; ++ ++ if (NumWindows >= MAX_WINDOWS) ++ return NULL; ++ ++ scrnum = DefaultScreen(dpy); ++ root = RootWindow(dpy, scrnum); ++ ++ visinfo = glXChooseVisual(dpy, scrnum, attrib); ++ if (!visinfo) { ++ Error(displayName, "Unable to find RGB, double-buffered visual"); ++ return NULL; ++ } ++ ++ /* 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 = CWBorderPixel | CWColormap | CWEventMask; ++ ++ win = XCreateWindow(dpy, root, xpos, ypos, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr); ++ if (!win) { ++ Error(displayName, "Couldn't create window"); ++ return NULL; ++ } ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, displayName, displayName, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ++ ctx = glXCreateContext(dpy, visinfo, ++ sCtx ? sCtx : NULL, True); ++ ++ if (!ctx) { ++ Error(displayName, "Couldn't create GLX context"); ++ return NULL; ++ } ++ ++ XMapWindow(dpy, win); ++ ++ /* save the info for this window */ ++ { ++ static int id = 0; ++ struct window *h = &Windows[NumWindows]; ++ if (strlen(displayName) + 1 > sizeof(h->DisplayName)) { ++ Error(displayName, "string overflow"); ++ return NULL; ++ } ++ strcpy(h->DisplayName, displayName); ++ h->Dpy = dpy; ++ h->Win = win; ++ h->Context = ctx; ++ h->Angle = 0.0; ++ h->Id = id++; ++ h->visInfo = visinfo; ++ pthread_mutex_init(&h->drawMutex, NULL); ++ NumWindows++; ++ return &Windows[NumWindows-1]; ++ } ++} ++ ++ ++static void ++InitGLstuff(void) ++ ++{ ++ glGenTextures(3, Textures); ++ ++ /* setup first texture object */ ++ { ++ GLubyte image[16][16][4]; ++ GLint i, j; ++ glBindTexture(GL_TEXTURE_2D, Textures[0]); ++ ++ /* red/white checkerboard */ ++ for (i = 0; i < 16; i++) { ++ for (j = 0; j < 16; j++) { ++ if ((i ^ j) & 1) { ++ image[i][j][0] = 255; ++ image[i][j][1] = 255; ++ image[i][j][2] = 255; ++ image[i][j][3] = 255; ++ } ++ else { ++ image[i][j][0] = 255; ++ image[i][j][1] = 0; ++ image[i][j][2] = 0; ++ image[i][j][3] = 255; ++ } ++ } ++ } ++ ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, ++ GL_UNSIGNED_BYTE, image); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ } ++ ++ /* setup second texture object */ ++ { ++ GLubyte image[8][8][3]; ++ GLint i, j; ++ glBindTexture(GL_TEXTURE_2D, Textures[1]); ++ ++ /* green/yellow checkerboard */ ++ for (i = 0; i < 8; i++) { ++ for (j = 0; j < 8; j++) { ++ if ((i ^ j) & 1) { ++ image[i][j][0] = 0; ++ image[i][j][1] = 255; ++ image[i][j][2] = 0; ++ } ++ else { ++ image[i][j][0] = 255; ++ image[i][j][1] = 255; ++ image[i][j][2] = 0; ++ } ++ } ++ } ++ ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 2); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 8, 8, 0, GL_RGB, ++ GL_UNSIGNED_BYTE, image); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ } ++ ++ /* setup second texture object */ ++ { ++ GLubyte image[4][4][3]; ++ GLint i, j; ++ glBindTexture(GL_TEXTURE_2D, Textures[2]); ++ ++ /* blue/gray checkerboard */ ++ for (i = 0; i < 4; i++) { ++ for (j = 0; j < 4; j++) { ++ if ((i ^ j) & 1) { ++ image[i][j][0] = 0; ++ image[i][j][1] = 0; ++ image[i][j][2] = 255; ++ } ++ else { ++ image[i][j][0] = 200; ++ image[i][j][1] = 200; ++ image[i][j][2] = 200; ++ } ++ } ++ } ++ ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 2); ++ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 4, 4, 0, GL_RGB, ++ GL_UNSIGNED_BYTE, image); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++ } ++ ++ /* Now make the cube object display list */ ++ ++ printf("GL_RENDERER: %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION: %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR: %s\n", (char *) glGetString(GL_VENDOR)); ++} ++ ++static void ++Redraw(struct window *h) ++{ ++ pthread_mutex_lock(&h->drawMutex); ++ if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { ++ Error(h->DisplayName, "glXMakeCurrent failed in Redraw"); ++ pthread_mutex_unlock(&h->drawMutex); ++ return; ++ } ++ ++ h->Angle += 1.0; ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.25, 0.25, 0.25, 1.0); ++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); ++ ++ glEnable(GL_TEXTURE_2D); ++ glEnable(GL_DEPTH_TEST); ++ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); ++ ++ glColor3f(1, 1, 1); ++ ++ glPushMatrix(); ++ if (h->Id == 0) ++ glRotatef(h->Angle, 0, 1, -1); ++ else if (h->Id == 1) ++ glRotatef(-(h->Angle), 0, 1, -1); ++ else if (h->Id == 2) ++ glRotatef(h->Angle, 0, 1, 1); ++ else if (h->Id == 3) ++ glRotatef(-(h->Angle), 0, 1, 1); ++ glBindTexture(GL_TEXTURE_2D, Textures[0]); ++ glBegin(GL_POLYGON); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f(-1, 1, -1); ++ glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); ++ glEnd(); ++ glBegin(GL_POLYGON); ++ glTexCoord2f(0, 0); glVertex3f(1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f(1, 1, -1); ++ glTexCoord2f(1, 1); glVertex3f(1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(1, -1, 1); ++ glEnd(); ++ ++ glBindTexture(GL_TEXTURE_2D, Textures[1]); ++ glBegin(GL_POLYGON); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); ++ glTexCoord2f(1, 1); glVertex3f( 1, -1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); ++ glEnd(); ++ glBegin(GL_POLYGON); ++ glTexCoord2f(0, 0); glVertex3f(-1, 1, -1); ++ glTexCoord2f(1, 0); glVertex3f( 1, 1, -1); ++ glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); ++ glEnd(); ++ ++ glBindTexture(GL_TEXTURE_2D, Textures[2]); ++ glBegin(GL_POLYGON); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); ++ glTexCoord2f(1, 0); glVertex3f( 1, -1, -1); ++ glTexCoord2f(1, 1); glVertex3f( 1, 1, -1); ++ glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); ++ glEnd(); ++ glBegin(GL_POLYGON); ++ glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); ++ glTexCoord2f(1, 0); glVertex3f( 1, -1, 1); ++ glTexCoord2f(1, 1); glVertex3f( 1, 1, 1); ++ glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); ++ glEnd(); ++ ++ glPopMatrix(); ++ ++ glXSwapBuffers(h->Dpy, h->Win); ++ ++ if (!glXMakeCurrent(h->Dpy, None, NULL)) { ++ Error(h->DisplayName, "glXMakeCurrent failed in Redraw"); ++ } ++ pthread_mutex_unlock(&h->drawMutex); ++} ++ ++static void *threadRunner (void *arg) ++{ ++ struct thread_init_arg *tia = (struct thread_init_arg *) arg; ++ struct window *win; ++ ++ win = &Windows[tia->id]; ++ ++ while(!terminate) { ++ usleep(1000); ++ Redraw(win); ++ } ++ ++ return NULL; ++} ++ ++static void ++Resize(struct window *h, unsigned int width, unsigned int height) ++{ ++ pthread_mutex_lock(&h->drawMutex); ++ ++ if (!glXMakeCurrent(h->Dpy, h->Win, h->Context)) { ++ Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); ++ pthread_mutex_unlock(&h->drawMutex); ++ return; ++ } ++ ++ glViewport(0, 0, width, height); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glFrustum(-1, 1, -1, 1, 2, 10); ++ glMatrixMode(GL_MODELVIEW); ++ glLoadIdentity(); ++ glTranslatef(0, 0, -4.5); ++ if (!glXMakeCurrent(h->Dpy, None, NULL)) { ++ Error(h->DisplayName, "glXMakeCurrent failed in Resize()"); ++ } ++ pthread_mutex_unlock(&h->drawMutex); ++} ++ ++ ++static void ++EventLoop(void) ++{ ++ while (1) { ++ int i; ++ XEvent event; ++ XNextEvent(gDpy, &event); ++ for (i = 0; i < NumWindows; i++) { ++ struct window *h = &Windows[i]; ++ if (event.xany.window == h->Win) { ++ switch (event.type) { ++ case Expose: ++ Redraw(h); ++ break; ++ case ConfigureNotify: ++ Resize(h, event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ terminate = 1; ++ return; ++ default: ++ /*no-op*/ ; ++ } ++ } ++ } ++ } ++} ++ ++int ++main(int argc, char *argv[]) ++{ ++ const char *dpyName = XDisplayName(NULL); ++ pthread_t t0, t1, t2, t3; ++ struct thread_init_arg tia0, tia1, tia2, tia3; ++ struct window *h0; ++ ++ XInitThreads(); ++ ++ gDpy = XOpenDisplay(dpyName); ++ if (!gDpy) { ++ Error(dpyName, "Unable to open display"); ++ return -1; ++ } ++ ++ if (initMainthread(gDpy, dpyName)) ++ return -1; ++ ++ /* four windows and contexts sharing display lists and texture objects */ ++ h0 = AddWindow(gDpy, dpyName, 10, 10, gCtx); ++ (void) AddWindow(gDpy, dpyName, 330, 10, gCtx); ++ (void) AddWindow(gDpy, dpyName, 10, 350, gCtx); ++ (void) AddWindow(gDpy, dpyName, 330, 350, gCtx); ++ ++ if (!glXMakeCurrent(gDpy, h0->Win, gCtx)) { ++ Error(dpyName, "glXMakeCurrent failed for init thread."); ++ return -1; ++ } ++ ++ InitGLstuff(); ++ ++ tia0.id = 0; ++ pthread_create(&t0, NULL, threadRunner, &tia0); ++ tia1.id = 1; ++ pthread_create(&t1, NULL, threadRunner, &tia1); ++ tia2.id = 2; ++ pthread_create(&t2, NULL, threadRunner, &tia2); ++ tia3.id = 3; ++ pthread_create(&t3, NULL, threadRunner, &tia3); ++ EventLoop(); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/texture_from_pixmap.c Mesa-7.8.1.patched/progs/xdemos/texture_from_pixmap.c +--- Mesa-7.8.1/progs/xdemos/texture_from_pixmap.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/texture_from_pixmap.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,396 @@ ++/* ++ * 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 = 0, 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; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/wincopy.c Mesa-7.8.1.patched/progs/xdemos/wincopy.c +--- Mesa-7.8.1/progs/xdemos/wincopy.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/wincopy.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,328 @@ ++/* ++ * Mesa 3-D graphics library ++ * Version: 6.5.2 ++ * ++ * Copyright (C) 1999-2006 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. ++ */ ++ ++ ++/* ++ * This program opens two GLX windows, renders into one and uses ++ * glCopyPixels to copy the image from the first window into the ++ * second by means of the GLX 1.3 function glxMakeContextCurrent(). ++ * This function works just like the glXMakeCurrentReadSGI() function ++ * in the GLX_SGI_make_current_read extension. ++ */ ++ ++ ++#define GL_GLEXT_PROTOTYPES ++#define GLX_GLXEXT_PROTOTYPES ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#ifdef GLX_VERSION_1_3 ++ ++ ++static Display *Dpy; ++static int ScrNum; ++static GLXContext Context; ++static Window Win[2]; /* Win[0] = source, Win[1] = dest */ ++static GLint Width[2], Height[2]; ++static GLboolean TestClipping = GL_FALSE; ++static GLfloat Angle = 0.0; ++ ++static GLboolean DrawFront = GL_FALSE; ++ ++PFNGLXMAKECURRENTREADSGIPROC make_context_current = NULL; ++ ++static Window ++CreateWindow(Display *dpy, int scrnum, XVisualInfo *visinfo, ++ int xpos, int ypos, int width, int height, ++ const char *name) ++{ ++ Window win; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ ++ root = RootWindow(dpy, scrnum); ++ ++ /* 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, xpos, ypos, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr); ++ if (win) { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ ++ XMapWindow(dpy, win); ++ } ++ return win; ++} ++ ++ ++static void ++Redraw(void) ++{ ++ /* make the first window the current one */ ++ if (! (*make_context_current)(Dpy, Win[0], Win[0], Context)) { ++ printf("glXMakeContextCurrent failed in Redraw()\n"); ++ return; ++ } ++ ++ Angle += 1.0; ++ ++ if (DrawFront) { ++ glDrawBuffer(GL_FRONT); ++ glReadBuffer(GL_FRONT); ++ } ++ else { ++ glDrawBuffer(GL_BACK); ++ glReadBuffer(GL_BACK); ++ } ++ ++ glViewport(0, 0, Width[0], Height[0]); ++ glMatrixMode(GL_PROJECTION); ++ glLoadIdentity(); ++ glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); ++ glMatrixMode(GL_MODELVIEW); ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.5, 0.5, 0.5, 0.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ /* draw blue quad */ ++ glColor3f(0.3, 0.3, 1.0); ++ glPushMatrix(); ++ glRotatef(Angle, 0, 0, 1); ++ glBegin(GL_POLYGON); ++ glVertex2f(-0.5, -0.25); ++ glVertex2f( 0.5, -0.25); ++ glVertex2f( 0.5, 0.25); ++ glVertex2f(-0.5, 0.25); ++ glEnd(); ++ glPopMatrix(); ++ ++ if (DrawFront) ++ glFinish(); ++ else ++ glXSwapBuffers(Dpy, Win[0]); ++ ++ ++ /* copy image from window 0 to window 1 */ ++ if (!(*make_context_current)(Dpy, Win[1], Win[0], Context)) { ++ printf("glXMakeContextCurrent failed in Redraw()\n"); ++ return; ++ } ++ ++ /* copy the image between windows */ ++ glClearColor(0.0, 0.0, 0.0, 0.0); ++ glClear(GL_COLOR_BUFFER_BIT); ++ ++ if (TestClipping) { ++ glWindowPos2iARB(-2, -2); ++ glCopyPixels(-2, -2, Width[0] + 4, Height[0] + 4, GL_COLOR); ++ } ++ else { ++ glWindowPos2iARB(0, 0); ++ glCopyPixels(0, 0, Width[0], Height[0], GL_COLOR); ++ } ++ ++ if (DrawFront) ++ glFinish(); ++ else ++ glXSwapBuffers(Dpy, Win[1]); ++} ++ ++ ++ ++static void ++Resize(Window win, unsigned int width, unsigned int height) ++{ ++ int i; ++ if (win == Win[0]) { ++ i = 0; ++ } ++ else { ++ i = 1; ++ } ++ Width[i] = width; ++ Height[i] = height; ++ if (!glXMakeCurrent(Dpy, Win[i], Context)) { ++ printf("glXMakeCurrent failed in Resize()\n"); ++ return; ++ } ++} ++ ++ ++ ++static void ++EventLoop(void) ++{ ++ XEvent event; ++ while (1) { ++ if (XPending(Dpy) > 0) { ++ XNextEvent( Dpy, &event ); ++ switch (event.type) { ++ case Expose: ++ Redraw(); ++ 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) { ++ /* exit */ ++ return; ++ } ++ else if (buf[0] == 'f') { ++ DrawFront = !DrawFront; ++ printf("Drawing to %s buffer\n", ++ DrawFront ? "GL_FRONT" : "GL_BACK"); ++ } ++ } ++ break; ++ default: ++ /*no-op*/ ; ++ } ++ } ++ else { ++ /* animate */ ++ Redraw(); ++ } ++ } ++} ++ ++ ++static void ++Init(void) ++{ ++ XVisualInfo *visinfo; ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int major, minor; ++ ++ Dpy = XOpenDisplay(NULL); ++ if (!Dpy) { ++ printf("Couldn't open default display!\n"); ++ exit(1); ++ } ++ ++ ScrNum = DefaultScreen(Dpy); ++ ++ glXQueryVersion(Dpy, &major, &minor); ++ ++ if (major * 100 + minor >= 103) { ++ make_context_current = (PFNGLXMAKECURRENTREADSGIPROC) ++ glXGetProcAddressARB( (GLubyte *) "glXMakeContextCurrent" ); ++ } ++ else { ++ const char * const glxExtensions = glXQueryExtensionsString(Dpy, ScrNum); ++ const char * ext = strstr( glxExtensions, "GLX_SGI_make_current_read" ); ++ const size_t len = strlen( "GLX_SGI_make_current_read" ); ++ ++ if ( (ext != NULL) ++ && ((ext[len] == ' ') || (ext[len] == '\0')) ) { ++ make_context_current = (PFNGLXMAKECURRENTREADSGIPROC) ++ glXGetProcAddressARB( (GLubyte *) "glXMakeCurrentReadSGI" ); ++ } ++ } ++ ++ if (make_context_current == NULL) { ++ fprintf(stderr, "Sorry, this program requires either GLX 1.3 " ++ "or GLX_SGI_make_current_read.\n"); ++ exit(1); ++ } ++ ++ visinfo = glXChooseVisual(Dpy, ScrNum, attrib); ++ if (!visinfo) { ++ printf("Unable to find RGB, double-buffered visual\n"); ++ exit(1); ++ } ++ ++ Context = glXCreateContext(Dpy, visinfo, NULL, True); ++ if (!Context) { ++ printf("Couldn't create GLX context\n"); ++ exit(1); ++ } ++ ++ ++ Win[0] = CreateWindow(Dpy, ScrNum, visinfo, ++ 0, 0, 300, 300, "source window"); ++ ++ Win[1] = CreateWindow(Dpy, ScrNum, visinfo, ++ 350, 0, 300, 300, "dest window"); ++ ++ printf("Press Esc to exit\n"); ++ printf("Press 'f' to toggle front/back buffer drawing\n"); ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ if (argc > 1 && strcmp(argv[1], "-clip") == 0) ++ TestClipping = GL_TRUE; ++ Init(); ++ EventLoop(); ++ return 0; ++} ++ ++ ++#else ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ printf("This program requires GLX 1.3!\n"); ++ return 0; ++} ++ ++ ++#endif /* GLX_VERSION_1_3 */ +diff -Naurp Mesa-7.8.1/progs/xdemos/xdemo.c Mesa-7.8.1.patched/progs/xdemos/xdemo.c +--- Mesa-7.8.1/progs/xdemos/xdemo.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/xdemo.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,334 @@ ++ ++/* ++ * Very simple demo of how to use the Mesa/X11 interface instead of the ++ * glx, tk or aux toolkits. I highly recommend using the GLX interface ++ * instead of the X/Mesa interface, however. ++ * ++ * This program is in the public domain. ++ * ++ * Brian Paul ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include "GL/xmesa.h" ++#include "GL/gl.h" ++ ++ ++ ++static GLint Black, Red, Green, Blue; ++ ++ ++ ++static void make_window( char *title, int color_flag ) ++{ ++ int x = 10, y = 10, width = 400, height = 300; ++ Display *dpy; ++ int scr; ++ Window root, win; ++ Colormap cmap; ++ XColor xcolor; ++ int attr_flags; ++ XVisualInfo *visinfo; ++ XSetWindowAttributes attr; ++ XTextProperty tp; ++ XSizeHints sh; ++ XEvent e; ++ XMesaContext context; ++ XMesaVisual visual; ++ XMesaBuffer buffer; ++ ++ ++ /* ++ * Do the usual X things to make a window. ++ */ ++ ++ dpy = XOpenDisplay(NULL); ++ if (!dpy) { ++ printf("Couldn't open default display!\n"); ++ exit(1); ++ } ++ ++ scr = DefaultScreen(dpy); ++ root = RootWindow(dpy, scr); ++ ++ /* alloc visinfo struct */ ++ visinfo = (XVisualInfo *) malloc( sizeof(XVisualInfo) ); ++ ++ /* Get a visual and colormap */ ++ if (color_flag) { ++ /* Open TrueColor window */ ++ ++/* ++ if (!XMatchVisualInfo( dpy, scr, 24, TrueColor, visinfo )) { ++ printf("Couldn't get 24-bit TrueColor visual!\n"); ++ exit(1); ++ } ++*/ ++ if (!XMatchVisualInfo( dpy, scr, 8, PseudoColor, visinfo )) { ++ printf("Couldn't get 8-bit PseudoColor visual!\n"); ++ exit(1); ++ } ++ ++ cmap = XCreateColormap( dpy, root, visinfo->visual, AllocNone ); ++ Black = Red = Green = Blue = 0; ++ } ++ else { ++ /* Open color index window */ ++ ++ if (!XMatchVisualInfo( dpy, scr, 8, PseudoColor, visinfo )) { ++ printf("Couldn't get 8-bit PseudoColor visual\n"); ++ exit(1); ++ } ++ ++ cmap = XCreateColormap( dpy, root, visinfo->visual, AllocNone ); ++ ++ /* Allocate colors */ ++ xcolor.red = 0x0; ++ xcolor.green = 0x0; ++ xcolor.blue = 0x0; ++ xcolor.flags = DoRed | DoGreen | DoBlue; ++ if (!XAllocColor( dpy, cmap, &xcolor )) { ++ printf("Couldn't allocate black!\n"); ++ exit(1); ++ } ++ Black = xcolor.pixel; ++ ++ xcolor.red = 0xffff; ++ xcolor.green = 0x0; ++ xcolor.blue = 0x0; ++ xcolor.flags = DoRed | DoGreen | DoBlue; ++ if (!XAllocColor( dpy, cmap, &xcolor )) { ++ printf("Couldn't allocate red!\n"); ++ exit(1); ++ } ++ Red = xcolor.pixel; ++ ++ xcolor.red = 0x0; ++ xcolor.green = 0xffff; ++ xcolor.blue = 0x0; ++ xcolor.flags = DoRed | DoGreen | DoBlue; ++ if (!XAllocColor( dpy, cmap, &xcolor )) { ++ printf("Couldn't allocate green!\n"); ++ exit(1); ++ } ++ Green = xcolor.pixel; ++ ++ xcolor.red = 0x0; ++ xcolor.green = 0x0; ++ xcolor.blue = 0xffff; ++ xcolor.flags = DoRed | DoGreen | DoBlue; ++ if (!XAllocColor( dpy, cmap, &xcolor )) { ++ printf("Couldn't allocate blue!\n"); ++ exit(1); ++ } ++ Blue = xcolor.pixel; ++ } ++ ++ /* set window attributes */ ++ attr.colormap = cmap; ++ attr.event_mask = ExposureMask | StructureNotifyMask; ++ attr.border_pixel = BlackPixel( dpy, scr ); ++ attr.background_pixel = BlackPixel( dpy, scr ); ++ attr_flags = CWColormap | CWEventMask | CWBorderPixel | CWBackPixel; ++ ++ /* Create the window */ ++ win = XCreateWindow( dpy, root, x,y, width, height, 0, ++ visinfo->depth, InputOutput, ++ visinfo->visual, ++ attr_flags, &attr); ++ if (!win) { ++ printf("Couldn't open window!\n"); ++ exit(1); ++ } ++ ++ XStringListToTextProperty(&title, 1, &tp); ++ sh.flags = USPosition | USSize; ++ XSetWMProperties(dpy, win, &tp, &tp, 0, 0, &sh, 0, 0); ++ XMapWindow(dpy, win); ++ while (1) { ++ XNextEvent( dpy, &e ); ++ if (e.type == MapNotify && e.xmap.window == win) { ++ break; ++ } ++ } ++ ++ ++ /* ++ * Now do the special Mesa/Xlib stuff! ++ */ ++ ++ visual = XMesaCreateVisual( dpy, visinfo, ++ (GLboolean) color_flag, ++ GL_FALSE, /* alpha_flag */ ++ GL_FALSE, /* db_flag */ ++ GL_FALSE, /* stereo flag */ ++ GL_FALSE, /* ximage_flag */ ++ 0, /* depth size */ ++ 0, /* stencil size */ ++ 0,0,0,0, /* accum_size */ ++ 0, /* num samples */ ++ 0, /* level */ ++ 0 /* caveat */ ++ ); ++ if (!visual) { ++ printf("Couldn't create Mesa/X visual!\n"); ++ exit(1); ++ } ++ ++ /* Create a Mesa rendering context */ ++ context = XMesaCreateContext( visual, ++ NULL /* share_list */ ++ ); ++ if (!context) { ++ printf("Couldn't create Mesa/X context!\n"); ++ exit(1); ++ } ++ ++ buffer = XMesaCreateWindowBuffer( visual, win ); ++ if (!buffer) { ++ printf("Couldn't create Mesa/X buffer!\n"); ++ exit(1); ++ } ++ ++ ++ XMesaMakeCurrent( context, buffer ); ++ ++ /* Ready to render! */ ++} ++ ++ ++ ++static void draw_cube( void ) ++{ ++ /* X faces */ ++ glIndexi( Red ); ++ glColor3f( 1.0, 0.0, 0.0 ); ++ glBegin( GL_POLYGON ); ++ glVertex3f( 1.0, 1.0, 1.0 ); ++ glVertex3f( 1.0, -1.0, 1.0 ); ++ glVertex3f( 1.0, -1.0, -1.0 ); ++ glVertex3f( 1.0, 1.0, -1.0 ); ++ glEnd(); ++ ++ glBegin( GL_POLYGON ); ++ glVertex3f( -1.0, 1.0, 1.0 ); ++ glVertex3f( -1.0, 1.0, -1.0 ); ++ glVertex3f( -1.0, -1.0, -1.0 ); ++ glVertex3f( -1.0, -1.0, 1.0 ); ++ glEnd(); ++ ++ /* Y faces */ ++ glIndexi( Green ); ++ glColor3f( 0.0, 1.0, 0.0 ); ++ glBegin( GL_POLYGON ); ++ glVertex3f( 1.0, 1.0, 1.0 ); ++ glVertex3f( 1.0, 1.0, -1.0 ); ++ glVertex3f( -1.0, 1.0, -1.0 ); ++ glVertex3f( -1.0, 1.0, 1.0 ); ++ glEnd(); ++ ++ glBegin( GL_POLYGON ); ++ glVertex3f( 1.0, -1.0, 1.0 ); ++ glVertex3f( -1.0, -1.0, 1.0 ); ++ glVertex3f( -1.0, -1.0, -1.0 ); ++ glVertex3f( 1.0, -1.0, -1.0 ); ++ glEnd(); ++ ++ /* Z faces */ ++ glIndexi( Blue ); ++ glColor3f( 0.0, 0.0, 1.0 ); ++ glBegin( GL_POLYGON ); ++ glVertex3f( 1.0, 1.0, 1.0 ); ++ glVertex3f( -1.0, 1.0, 1.0 ); ++ glVertex3f( -1.0, -1.0, 1.0 ); ++ glVertex3f( 1.0, -1.0, 1.0 ); ++ glEnd(); ++ ++ glBegin( GL_POLYGON ); ++ glVertex3f( 1.0, 1.0, -1.0 ); ++ glVertex3f( 1.0,-1.0, -1.0 ); ++ glVertex3f( -1.0,-1.0, -1.0 ); ++ glVertex3f( -1.0, 1.0, -1.0 ); ++ glEnd(); ++} ++ ++ ++ ++ ++static void display_loop( void ) ++{ ++ GLfloat xrot, yrot, zrot; ++ ++ xrot = yrot = zrot = 0.0; ++ ++ glClearColor( 0.0, 0.0, 0.0, 0.0 ); ++ glClearIndex( Black ); ++ ++ glMatrixMode( GL_PROJECTION ); ++ glLoadIdentity(); ++ glFrustum( -1.0, 1.0, -1.0, 1.0, 1.0, 10.0 ); ++ glTranslatef( 0.0, 0.0, -5.0 ); ++ ++ glMatrixMode( GL_MODELVIEW ); ++ glLoadIdentity(); ++ ++ glCullFace( GL_BACK ); ++ glEnable( GL_CULL_FACE ); ++ ++ glShadeModel( GL_FLAT ); ++ ++ while (1) { ++ glClear( GL_COLOR_BUFFER_BIT ); ++ glPushMatrix(); ++ glRotatef( xrot, 1.0, 0.0, 0.0 ); ++ glRotatef( yrot, 0.0, 1.0, 0.0 ); ++ glRotatef( zrot, 0.0, 0.0, 1.0 ); ++ ++ draw_cube(); ++ ++ glPopMatrix(); ++ glFinish(); ++ ++ xrot += 10.0; ++ yrot += 7.0; ++ zrot -= 3.0; ++ } ++ ++} ++ ++ ++ ++ ++int main( int argc, char *argv[] ) ++{ ++ int mode = 0; ++ ++ if (argc >= 2) ++ { ++ if (strcmp(argv[1],"-ci")==0) ++ mode = 0; ++ else if (strcmp(argv[1],"-rgb")==0) ++ mode = 1; ++ else ++ { ++ printf("Bad flag: %s\n", argv[1]); ++ printf("Specify -ci for 8-bit color index or -rgb for RGB mode\n"); ++ exit(1); ++ } ++ } ++ else ++ { ++ printf("Specify -ci for 8-bit color index or -rgb for RGB mode\n"); ++ printf("Defaulting to 8-bit color index\n"); ++ } ++ ++ make_window( argv[0], mode ); ++ ++ display_loop(); ++ return 0; ++} ++ +diff -Naurp Mesa-7.8.1/progs/xdemos/xfont.c Mesa-7.8.1.patched/progs/xdemos/xfont.c +--- Mesa-7.8.1/progs/xdemos/xfont.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/xfont.c 2010-06-13 13:45:06.788792936 +0200 +@@ -0,0 +1,206 @@ ++ ++/* ++ * Mesa 3-D graphics library ++ * ++ * Copyright (C) 1999 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. ++ */ ++ ++ ++/* ++ * Example of using glXUseXFont(). ++ * 5 November 1999 ++ * Brian Paul ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++ ++ ++static const char *ProgramName = "xfont"; ++ ++static const char *FontName = "fixed"; ++ ++static GLuint FontBase = 0; ++ ++ ++ ++static void redraw( Display *dpy, Window w ) ++{ ++ static const char *text = "This is glXUseXFont()"; ++ ++ glClear( GL_COLOR_BUFFER_BIT ); ++ ++ /* triangle */ ++ glColor3f( 0.2, 0.2, 1.0 ); ++ glBegin(GL_TRIANGLES); ++ glVertex2f( 0, 0.8 ); ++ glVertex2f( -0.8, -0.7 ); ++ glVertex2f( 0.8, -0.7 ); ++ glEnd(); ++ ++ /* text */ ++ glColor3f( 1, 1, 1 ); ++ glRasterPos2f(-0.8, 0); ++ glListBase(FontBase); ++ glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text); ++ ++ glXSwapBuffers( dpy, w ); ++} ++ ++ ++ ++static void resize( unsigned int width, unsigned int height ) ++{ ++ glViewport( 0, 0, width, height ); ++ glMatrixMode( GL_PROJECTION ); ++ glLoadIdentity(); ++ glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ); ++} ++ ++ ++ ++static void setup_font( Display *dpy ) ++{ ++ XFontStruct *fontInfo; ++ Font id; ++ unsigned int first, last; ++ ++ fontInfo = XLoadQueryFont(dpy, FontName); ++ if (!fontInfo) { ++ printf("Error: font %s not found\n", FontName); ++ exit(0); ++ } ++ ++ id = fontInfo->fid; ++ first = fontInfo->min_char_or_byte2; ++ last = fontInfo->max_char_or_byte2; ++ ++ FontBase = glGenLists((GLuint) last + 1); ++ if (!FontBase) { ++ printf("Error: unable to allocate display lists\n"); ++ exit(0); ++ } ++ glXUseXFont(id, first, last - first + 1, FontBase + first); ++} ++ ++static Window make_rgb_db_window( Display *dpy, int xpos, int ypos, ++ unsigned int width, unsigned int height ) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attrib ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* 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 ); ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, ProgramName, ProgramName, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ ++ glXMakeCurrent( dpy, win, ctx ); ++ ++ return win; ++} ++ ++ ++static void event_loop( Display *dpy ) ++{ ++ XEvent event; ++ ++ while (1) { ++ XNextEvent( dpy, &event ); ++ ++ switch (event.type) { ++ case Expose: ++ redraw( dpy, event.xany.window ); ++ break; ++ case ConfigureNotify: ++ resize( event.xconfigure.width, event.xconfigure.height ); ++ break; ++ case KeyPress: ++ exit(0); ++ default: ++ ; /* no-op */ ++ } ++ } ++} ++ ++ ++ ++int main( int argc, char *argv[] ) ++{ ++ Display *dpy; ++ Window win; ++ ++ dpy = XOpenDisplay(NULL); ++ ++ win = make_rgb_db_window( dpy, 0, 0, 300, 300 ); ++ setup_font( dpy ); ++ ++ glShadeModel( GL_FLAT ); ++ glClearColor( 0.5, 0.5, 1.0, 1.0 ); ++ ++ XMapWindow( dpy, win ); ++ ++ event_loop( dpy ); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/xrotfontdemo.c Mesa-7.8.1.patched/progs/xdemos/xrotfontdemo.c +--- Mesa-7.8.1/progs/xdemos/xrotfontdemo.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/xrotfontdemo.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,220 @@ ++/* ++ * Mesa 3-D graphics library ++ * ++ * Copyright (C) 1999 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. ++ */ ++ ++ ++/* ++ * Example of using glXUseRotatedXFontMESA(). ++ * 24 Jan 2004 ++ * Brian Paul ++ */ ++ ++ ++#include ++#include ++#include ++#include ++#include ++#include "xuserotfont.h" ++ ++ ++static const char *ProgramName = "xfont"; ++ ++static const char *FontName = "fixed"; ++ ++static GLuint FontBase[4]; ++ ++ ++static void redraw( Display *dpy, Window w ) ++{ ++ static const char *text = " Rotated bitmap text"; ++ int i; ++ ++ glClear( GL_COLOR_BUFFER_BIT ); ++ ++ /* triangle */ ++ glColor3f( 0.2, 0.2, 1.0 ); ++ glBegin(GL_TRIANGLES); ++ glVertex2f( -0.8, 0.7 ); ++ glVertex2f( -0.8, -0.7 ); ++ glVertex2f( 0.8, 0.0 ); ++ glEnd(); ++ ++ /* marker */ ++ glColor3f( 0, 1, 0 ); ++ glBegin(GL_POINTS); ++ glVertex2f(0, 0); ++ glEnd(); ++ ++ /* text */ ++ glColor3f( 1, 1, 1 ); ++ ++ for (i = 0; i < 4; i++) { ++ glRasterPos2f(0, 0); ++ glListBase(FontBase[i]); ++ glCallLists(strlen(text), GL_UNSIGNED_BYTE, (GLubyte *) text); ++ } ++ ++ glXSwapBuffers( dpy, w ); ++} ++ ++ ++ ++static void resize( unsigned int width, unsigned int height ) ++{ ++ glViewport( 0, 0, width, height ); ++ glMatrixMode( GL_PROJECTION ); ++ glLoadIdentity(); ++ glOrtho( -1.0, 1.0, -1.0, 1.0, -1.0, 1.0 ); ++} ++ ++ ++ ++static void setup_font( Display *dpy ) ++{ ++ XFontStruct *fontInfo; ++ Font id; ++ unsigned int first, last; ++ int i; ++ ++ fontInfo = XLoadQueryFont(dpy, FontName); ++ if (!fontInfo) { ++ printf("Error: font %s not found\n", FontName); ++ exit(0); ++ } ++ ++ id = fontInfo->fid; ++ first = fontInfo->min_char_or_byte2; ++ last = fontInfo->max_char_or_byte2; ++ ++ for (i = 0; i < 4; i++) { ++ FontBase[i] = glGenLists((GLuint) last + 1); ++ if (!FontBase[i]) { ++ printf("Error: unable to allocate display lists\n"); ++ exit(0); ++ } ++ glXUseRotatedXFontMESA(id, first, last - first + 1, FontBase[i] + first, ++ i * 90); ++ } ++} ++ ++ ++static Window make_rgb_db_window( Display *dpy, int xpos, int ypos, ++ unsigned int width, unsigned int height ) ++{ ++ int attrib[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attrib ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* 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 ); ++ ++ { ++ XSizeHints sizehints; ++ sizehints.x = xpos; ++ sizehints.y = ypos; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, ProgramName, ProgramName, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ ++ glXMakeCurrent( dpy, win, ctx ); ++ ++ return win; ++} ++ ++ ++static void event_loop( Display *dpy ) ++{ ++ XEvent event; ++ ++ while (1) { ++ XNextEvent( dpy, &event ); ++ ++ switch (event.type) { ++ case Expose: ++ redraw( dpy, event.xany.window ); ++ break; ++ case ConfigureNotify: ++ resize( event.xconfigure.width, event.xconfigure.height ); ++ break; ++ case KeyPress: ++ exit(0); ++ default: ++ ; /* no-op */ ++ } ++ } ++} ++ ++ ++ ++int main( int argc, char *argv[] ) ++{ ++ Display *dpy; ++ Window win; ++ ++ dpy = XOpenDisplay(NULL); ++ ++ win = make_rgb_db_window( dpy, 0, 0, 300, 300 ); ++ setup_font( dpy ); ++ ++ glShadeModel( GL_FLAT ); ++ glClearColor( 0.5, 0.5, 1.0, 1.0 ); ++ ++ XMapWindow( dpy, win ); ++ ++ event_loop( dpy ); ++ return 0; ++} +diff -Naurp Mesa-7.8.1/progs/xdemos/xuserotfont.c Mesa-7.8.1.patched/progs/xdemos/xuserotfont.c +--- Mesa-7.8.1/progs/xdemos/xuserotfont.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/xuserotfont.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,399 @@ ++/* ++ * Mesa 3-D graphics library ++ * Version: 6.1 ++ * ++ * Copyright (C) 1999-2004 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. ++ */ ++ ++ ++/* \file xuserotfont.c ++ * ++ * A function like glXUseXFont() but takes a 0, 90, 180 or 270 degree ++ * rotation angle for rotated text display. ++ * ++ * Based on Mesa's glXUseXFont implementation written by Thorsten Ohl. ++ */ ++ ++#include ++#include ++#include ++#include ++#include "xuserotfont.h" ++ ++ ++/** ++ * Generate OpenGL-compatible bitmap by drawing an X character glyph ++ * to an off-screen pixmap, then getting the image and testing pixels. ++ * \param width bitmap width in pixels ++ * \param height bitmap height in pixels ++ */ ++static void ++fill_bitmap(Display *dpy, Pixmap pixmap, GC gc, ++ unsigned int bitmapWidth, unsigned int bitmapHeight, ++ unsigned int charWidth, unsigned int charHeight, ++ int xPos, int yPos, unsigned int c, GLubyte * bitmap, ++ int rotation) ++{ ++ const int bytesPerRow = (bitmapWidth + 7) / 8; ++ XImage *image; ++ XChar2b char2b; ++ ++ /* clear pixmap to 0 */ ++ XSetForeground(dpy, gc, 0); ++ XFillRectangle(dpy, pixmap, gc, 0, 0, charWidth, charHeight); ++ ++ /* The glyph is drawn snug up against the left/top edges of the pixmap */ ++ XSetForeground(dpy, gc, 1); ++ char2b.byte1 = (c >> 8) & 0xff; ++ char2b.byte2 = (c & 0xff); ++ XDrawString16(dpy, pixmap, gc, xPos, yPos, &char2b, 1); ++ ++ /* initialize GL bitmap */ ++ memset(bitmap, 0, bytesPerRow * bitmapHeight); ++ ++ image = XGetImage(dpy, pixmap, 0, 0, charWidth, charHeight, 1, XYPixmap); ++ if (image) { ++ /* Set appropriate bits in the GL bitmap. ++ * Note: X11 and OpenGL are upside down wrt each other). ++ */ ++ unsigned int x, y; ++ if (rotation == 0) { ++ for (y = 0; y < charHeight; y++) { ++ for (x = 0; x < charWidth; x++) { ++ if (XGetPixel(image, x, y)) { ++ int y2 = bitmapHeight - y - 1; ++ bitmap[bytesPerRow * y2 + x / 8] |= (1 << (7 - (x % 8))); ++ } ++ } ++ } ++ } ++ else if (rotation == 90) { ++ for (y = 0; y < charHeight; y++) { ++ for (x = 0; x < charWidth; x++) { ++ if (XGetPixel(image, x, y)) { ++ int x2 = y; ++ int y2 = x; ++ bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8))); ++ } ++ } ++ } ++ } ++ else if (rotation == 180) { ++ for (y = 0; y < charHeight; y++) { ++ for (x = 0; x < charWidth; x++) { ++ if (XGetPixel(image, x, y)) { ++ int x2 = charWidth - x - 1; ++ bitmap[bytesPerRow * y + x2 / 8] |= (1 << (7 - (x2 % 8))); ++ } ++ } ++ } ++ } ++ else { ++ assert(rotation == 270); ++ for (y = 0; y < charHeight; y++) { ++ for (x = 0; x < charWidth; x++) { ++ if (XGetPixel(image, x, y)) { ++ int x2 = charHeight - y - 1; ++ int y2 = charWidth - x - 1; ++ bitmap[bytesPerRow * y2 + x2 / 8] |= (1 << (7 - (x2 % 8))); ++ } ++ } ++ } ++ } ++ XDestroyImage(image); ++ } ++} ++ ++ ++/* ++ * Determine if a given glyph is valid and return the ++ * corresponding XCharStruct. ++ */ ++static const XCharStruct * ++isvalid(const XFontStruct * fs, unsigned int which) ++{ ++ unsigned int rows, pages; ++ unsigned int byte1 = 0, byte2 = 0; ++ int i, valid = 1; ++ ++ rows = fs->max_byte1 - fs->min_byte1 + 1; ++ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; ++ ++ if (rows == 1) { ++ /* "linear" fonts */ ++ if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which)) ++ valid = 0; ++ } ++ else { ++ /* "matrix" fonts */ ++ byte2 = which & 0xff; ++ byte1 = which >> 8; ++ if ((fs->min_char_or_byte2 > byte2) || ++ (fs->max_char_or_byte2 < byte2) || ++ (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1)) ++ valid = 0; ++ } ++ ++ if (valid) { ++ if (fs->per_char) { ++ if (rows == 1) { ++ /* "linear" fonts */ ++ return fs->per_char + (which - fs->min_char_or_byte2); ++ } ++ else { ++ /* "matrix" fonts */ ++ i = ((byte1 - fs->min_byte1) * pages) + ++ (byte2 - fs->min_char_or_byte2); ++ return fs->per_char + i; ++ } ++ } ++ else { ++ return &fs->min_bounds; ++ } ++ } ++ return NULL; ++} ++ ++ ++void ++glXUseRotatedXFontMESA(Font font, int first, int count, int listbase, ++ int rotation) ++{ ++ Display *dpy; ++ Window win; ++ Pixmap pixmap; ++ GC gc; ++ XFontStruct *fs; ++ GLint swapbytes, lsbfirst, rowlength; ++ GLint skiprows, skippixels, alignment; ++ unsigned int maxCharWidth, maxCharHeight; ++ GLubyte *bm; ++ int i; ++ ++ if (rotation != 0 && ++ rotation != 90 && ++ rotation != 180 && ++ rotation != 270) ++ return; ++ ++ dpy = glXGetCurrentDisplay(); ++ if (!dpy) ++ return; /* I guess glXMakeCurrent wasn't called */ ++ win = RootWindow(dpy, DefaultScreen(dpy)); ++ ++ fs = XQueryFont(dpy, font); ++ if (!fs) { ++ /* ++ _mesa_error(NULL, GL_INVALID_VALUE, ++ "Couldn't get font structure information"); ++ */ ++ return; ++ } ++ ++ /* Allocate a GL bitmap that can fit any character */ ++ maxCharWidth = fs->max_bounds.rbearing - fs->min_bounds.lbearing; ++ maxCharHeight = fs->max_bounds.ascent + fs->max_bounds.descent; ++ /* use max, in case we're rotating */ ++ if (rotation == 90 || rotation == 270) { ++ /* swap width/height */ ++ bm = (GLubyte *) malloc((maxCharHeight + 7) / 8 * maxCharWidth); ++ } ++ else { ++ /* normal or upside down */ ++ bm = (GLubyte *) malloc((maxCharWidth + 7) / 8 * maxCharHeight); ++ } ++ if (!bm) { ++ XFreeFontInfo(NULL, fs, 1); ++ /* ++ _mesa_error(NULL, GL_OUT_OF_MEMORY, ++ "Couldn't allocate bitmap in glXUseXFont()"); ++ */ ++ return; ++ } ++ ++#if 0 ++ /* get the page info */ ++ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; ++ firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; ++ lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; ++ rows = fs->max_byte1 - fs->min_byte1 + 1; ++ unsigned int first_char, last_char, pages, rows; ++#endif ++ ++ /* Save the current packing mode for bitmaps. */ ++ glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); ++ glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); ++ glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); ++ glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); ++ glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); ++ glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); ++ ++ /* Enforce a standard packing mode which is compatible with ++ fill_bitmap() from above. This is actually the default mode, ++ except for the (non)alignment. */ ++ glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); ++ glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); ++ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); ++ glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); ++ glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); ++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); ++ ++ /* Create pixmap and GC */ ++ pixmap = XCreatePixmap(dpy, win, maxCharWidth, maxCharHeight, 1); ++ { ++ XGCValues values; ++ unsigned long valuemask; ++ values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); ++ values.background = WhitePixel(dpy, DefaultScreen(dpy)); ++ values.font = fs->fid; ++ valuemask = GCForeground | GCBackground | GCFont; ++ gc = XCreateGC(dpy, pixmap, valuemask, &values); ++ } ++ ++#ifdef DEBUG_XROT ++ if (debug_xfonts) ++ dump_font_struct(fs); ++#endif ++ ++ for (i = 0; i < count; i++) { ++ const unsigned int c = first + i; ++ const int list = listbase + i; ++ unsigned int charWidth, charHeight; ++ unsigned int bitmapWidth = 0, bitmapHeight = 0; ++ GLfloat xOrig, yOrig, xStep, yStep, dtemp; ++ const XCharStruct *ch; ++ int xPos, yPos; ++ int valid; ++ ++ /* check on index validity and get the bounds */ ++ ch = isvalid(fs, c); ++ if (!ch) { ++ ch = &fs->max_bounds; ++ valid = 0; ++ } ++ else { ++ valid = 1; ++ } ++ ++#ifdef DEBUG_XROT ++ if (debug_xfonts) { ++ char s[7]; ++ sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); ++ dump_char_struct(ch, s); ++ } ++#endif ++ ++ /* glBitmap()' parameters: ++ straight from the glXUseXFont(3) manpage. */ ++ charWidth = ch->rbearing - ch->lbearing; ++ charHeight = ch->ascent + ch->descent; ++ xOrig = -ch->lbearing; ++ yOrig = ch->descent; ++ xStep = ch->width; ++ yStep = 0; ++ ++ /* X11's starting point. */ ++ xPos = -ch->lbearing; ++ yPos = ch->ascent; ++ ++ /* Apply rotation */ ++ switch (rotation) { ++ case 0: ++ /* nothing */ ++ bitmapWidth = charWidth; ++ bitmapHeight = charHeight; ++ break; ++ case 90: ++ /* xStep, yStep */ ++ dtemp = xStep; ++ xStep = -yStep; ++ yStep = dtemp; ++ /* xOrig, yOrig */ ++ yOrig = xOrig; ++ xOrig = charHeight - (charHeight - yPos); ++ /* width, height */ ++ bitmapWidth = charHeight; ++ bitmapHeight = charWidth; ++ break; ++ case 180: ++ /* xStep, yStep */ ++ xStep = -xStep; ++ yStep = -yStep; ++ /* xOrig, yOrig */ ++ xOrig = charWidth - xOrig - 1; ++ yOrig = charHeight - yOrig - 1; ++ bitmapWidth = charWidth; ++ bitmapHeight = charHeight; ++ break; ++ case 270: ++ /* xStep, yStep */ ++ dtemp = xStep; ++ xStep = yStep; ++ yStep = -dtemp; ++ /* xOrig, yOrig */ ++ dtemp = yOrig; ++ yOrig = charWidth - xOrig; ++ xOrig = dtemp; ++ /* width, height */ ++ bitmapWidth = charHeight; ++ bitmapHeight = charWidth; ++ break; ++ default: ++ /* should never get here */ ++ ; ++ } ++ ++ glNewList(list, GL_COMPILE); ++ if (valid && bitmapWidth > 0 && bitmapHeight > 0) { ++ ++ fill_bitmap(dpy, pixmap, gc, bitmapWidth, bitmapHeight, ++ charWidth, charHeight, ++ xPos, yPos, c, bm, rotation); ++ ++ glBitmap(bitmapWidth, bitmapHeight, xOrig, yOrig, xStep, yStep, bm); ++ ++#ifdef DEBUG_XROT ++ if (debug_xfonts) { ++ printf("width/height = %u/%u\n", bitmapWidth, bitmapHeight); ++ dump_bitmap(bitmapWidth, bitmapHeight, bm); ++ } ++#endif ++ } ++ else { ++ glBitmap(0, 0, 0.0, 0.0, xStep, yStep, NULL); ++ } ++ glEndList(); ++ } ++ ++ free(bm); ++ XFreeFontInfo(NULL, fs, 1); ++ XFreePixmap(dpy, pixmap); ++ XFreeGC(dpy, gc); ++ ++ /* Restore saved packing modes. */ ++ glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); ++ glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); ++ glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); ++ glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); ++ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); ++ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); ++} ++ ++ +diff -Naurp Mesa-7.8.1/progs/xdemos/xuserotfont.h Mesa-7.8.1.patched/progs/xdemos/xuserotfont.h +--- Mesa-7.8.1/progs/xdemos/xuserotfont.h 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/xuserotfont.h 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,12 @@ ++#ifndef XUSEROTFONT_H ++#define XUSEROTFONT_H ++ ++#include ++ ++ ++extern void ++glXUseRotatedXFontMESA(Font font, int first, int count, int listbase, ++ int rotation); ++ ++ ++#endif +diff -Naurp Mesa-7.8.1/progs/xdemos/yuvrect_client.c Mesa-7.8.1.patched/progs/xdemos/yuvrect_client.c +--- Mesa-7.8.1/progs/xdemos/yuvrect_client.c 1970-01-01 01:00:00.000000000 +0100 ++++ Mesa-7.8.1.patched/progs/xdemos/yuvrect_client.c 2010-06-13 13:45:06.789793146 +0200 +@@ -0,0 +1,326 @@ ++/* ++ * Test the GL_NV_texture_rectangle and GL_MESA_ycrcb_texture extensions and GLX_MESA_allocate-memory ++ * ++ * Dave Airlie - Feb 2005 ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#define GL_GLEXT_PROTOTYPES ++#include ++ ++#include "../util/readtex.c" /* I know, this is a hack. */ ++ ++#define TEXTURE_FILE "../images/girl2.rgb" ++ ++static GLfloat Xrot = 0, Yrot = 0, Zrot = 0; ++static GLint ImgWidth, ImgHeight; ++static GLushort *ImageYUV = NULL; ++static void *glx_memory; ++ ++static void DrawObject(void) ++{ ++ glBegin(GL_QUADS); ++ ++ glTexCoord2f(0, 0); ++ glVertex2f(-1.0, -1.0); ++ ++ glTexCoord2f(ImgWidth, 0); ++ glVertex2f(1.0, -1.0); ++ ++ glTexCoord2f(ImgWidth, ImgHeight); ++ glVertex2f(1.0, 1.0); ++ ++ glTexCoord2f(0, ImgHeight); ++ glVertex2f(-1.0, 1.0); ++ ++ glEnd(); ++} ++ ++ ++static void scr_Display( void ) ++{ ++ glClear( GL_COLOR_BUFFER_BIT ); ++ ++ glPushMatrix(); ++ glRotatef(Xrot, 1.0, 0.0, 0.0); ++ glRotatef(Yrot, 0.0, 1.0, 0.0); ++ glRotatef(Zrot, 0.0, 0.0, 1.0); ++ DrawObject(); ++ glPopMatrix(); ++ ++} ++ ++ ++static void Reshape( int width, int height ) ++{ ++ glViewport( 0, 0, width, height ); ++ glMatrixMode( GL_PROJECTION ); ++ glLoadIdentity(); ++ glFrustum( -1.0, 1.0, -1.0, 1.0, 10.0, 100.0 ); ++ glMatrixMode( GL_MODELVIEW ); ++ glLoadIdentity(); ++ glTranslatef( 0.0, 0.0, -15.0 ); ++} ++ ++static int queryClient(Display *dpy, int screen) ++{ ++#ifdef GLX_MESA_allocate_memory ++ char *extensions; ++ ++ extensions = (char *)glXQueryExtensionsString(dpy, screen); ++ if (!extensions || !strstr(extensions,"GLX_MESA_allocate_memory")) { ++ return 0; ++ } ++ ++ return 1; ++#else ++ return 0; ++#endif ++} ++ ++static int ++query_extension(char* extName) { ++ char *p = (char *) glGetString(GL_EXTENSIONS); ++ char *end = p + strlen(p); ++ while (p < end) { ++ int n = strcspn(p, " "); ++ if ((strlen(extName) == n) && (strncmp(extName, p, n) == 0)) ++ return GL_TRUE; ++ p += (n + 1); ++ } ++ return GL_FALSE; ++} ++ ++static void Init( int argc, char *argv[] , Display *dpy, int screen, Window win) ++{ ++ GLuint texObj = 100; ++ const char *file; ++ void *glx_memory; ++ ++ if (!query_extension("GL_NV_texture_rectangle")) { ++ printf("Sorry, GL_NV_texture_rectangle is required\n"); ++ exit(0); ++ } ++ ++ if (!query_extension("GL_MESA_ycbcr_texture")) { ++ printf("Sorry, GL_MESA_ycbcr_texture is required\n"); ++ exit(0); ++ } ++ ++ if (!queryClient(dpy, screen)) { ++ printf("Sorry, GLX_MESA_allocate_memory is required\n"); ++ exit(0); ++ } ++ ++ glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, 1); ++ glBindTexture(GL_TEXTURE_RECTANGLE_NV, texObj); ++#ifdef LINEAR_FILTER ++ /* linear filtering looks much nicer but is much slower for Mesa */ ++ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); ++ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); ++#else ++ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_NEAREST); ++ glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_NEAREST); ++#endif ++ ++ if (argc > 1) ++ file = argv[1]; ++ else ++ file = TEXTURE_FILE; ++ ++ ImageYUV = LoadYUVImage(file, &ImgWidth, &ImgHeight); ++ if (!ImageYUV) { ++ printf("Couldn't read %s\n", TEXTURE_FILE); ++ exit(0); ++ } ++ ++ glx_memory = glXAllocateMemoryMESA(dpy, screen, ImgWidth * ImgHeight * 2, 0, 0 ,0); ++ if (!glx_memory) ++ { ++ fprintf(stderr,"Failed to allocate MESA memory\n"); ++ exit(-1); ++ } ++ ++ memcpy(glx_memory, ImageYUV, ImgWidth * ImgHeight * 2); ++ ++ printf("Image: %dx%d\n", ImgWidth, ImgHeight); ++ ++ glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, ++ GL_YCBCR_MESA, ImgWidth, ImgHeight, 0, ++ GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_APPLE, glx_memory); ++ ++ assert(glGetError() == GL_NO_ERROR); ++ ++ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); ++ ++ glEnable(GL_TEXTURE_RECTANGLE_NV); ++ ++ glShadeModel(GL_FLAT); ++ glClearColor(0.3, 0.3, 0.4, 1.0); ++ ++} ++ ++/* ++ * Create an RGB, double-buffered window. ++ * Return the window and context handles. ++ */ ++static void ++make_window( Display *dpy, const char *name, ++ int x, int y, int width, int height, ++ Window *winRet, GLXContext *ctxRet) ++{ ++ int attribs[] = { GLX_RGBA, ++ GLX_RED_SIZE, 1, ++ GLX_GREEN_SIZE, 1, ++ GLX_BLUE_SIZE, 1, ++ GLX_DOUBLEBUFFER, ++ GLX_DEPTH_SIZE, 1, ++ None }; ++ int scrnum; ++ XSetWindowAttributes attr; ++ unsigned long mask; ++ Window root; ++ Window win; ++ GLXContext ctx; ++ XVisualInfo *visinfo; ++ ++ scrnum = DefaultScreen( dpy ); ++ root = RootWindow( dpy, scrnum ); ++ ++ visinfo = glXChooseVisual( dpy, scrnum, attribs ); ++ if (!visinfo) { ++ printf("Error: couldn't get an RGB, Double-buffered visual\n"); ++ exit(1); ++ } ++ ++ /* window attributes */ ++ attr.background_pixel = 0; ++ attr.border_pixel = 0; ++ attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone); ++ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; ++ attr.override_redirect = 0; ++ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect; ++ ++ win = XCreateWindow( dpy, root, 0, 0, width, height, ++ 0, visinfo->depth, InputOutput, ++ visinfo->visual, mask, &attr ); ++ ++ /* set hints and properties */ ++ { ++ XSizeHints sizehints; ++ sizehints.x = x; ++ sizehints.y = y; ++ sizehints.width = width; ++ sizehints.height = height; ++ sizehints.flags = USSize | USPosition; ++ XSetNormalHints(dpy, win, &sizehints); ++ XSetStandardProperties(dpy, win, name, name, ++ None, (char **)NULL, 0, &sizehints); ++ } ++ ++ ctx = glXCreateContext( dpy, visinfo, NULL, True ); ++ if (!ctx) { ++ printf("Error: glXCreateContext failed\n"); ++ exit(1); ++ } ++ ++ XFree(visinfo); ++ ++ *winRet = win; ++ *ctxRet = ctx; ++} ++ ++ ++static void ++event_loop(Display *dpy, Window win) ++{ ++ while (1) { ++ while (XPending(dpy) > 0) { ++ XEvent event; ++ XNextEvent(dpy, &event); ++ switch (event.type) { ++ case Expose: ++ /* we'll redraw below */ ++ break; ++ case ConfigureNotify: ++ Reshape(event.xconfigure.width, event.xconfigure.height); ++ break; ++ case KeyPress: ++ { ++ char buffer[10]; ++ int r, code; ++ code = XLookupKeysym(&event.xkey, 0); ++ r = XLookupString(&event.xkey, buffer, sizeof(buffer), ++ NULL, NULL); ++ if (buffer[0] == 27) { ++ /* escape */ ++ return; ++ ++ } ++ } ++ } ++ } ++ ++ } ++} ++ ++ ++int ++main(int argc, char *argv[]) ++{ ++ Display *dpy; ++ Window win; ++ GLXContext ctx; ++ char *dpyName = NULL; ++ GLboolean printInfo = GL_FALSE; ++ int i; ++ ++ for (i = 1; i < argc; i++) { ++ if (strcmp(argv[i], "-display") == 0) { ++ dpyName = argv[i+1]; ++ i++; ++ } ++ else if (strcmp(argv[i], "-info") == 0) { ++ printInfo = GL_TRUE; ++ } ++ else ++ printf("Warrning: unknown parameter: %s\n", argv[i]); ++ } ++ ++ dpy = XOpenDisplay(dpyName); ++ if (!dpy) { ++ printf("Error: couldn't open display %s\n", ++ XDisplayName(dpyName)); ++ return -1; ++ } ++ ++ make_window(dpy, "yuvrect_client", 0, 0, 300, 300, &win, &ctx); ++ XMapWindow(dpy, win); ++ glXMakeCurrent(dpy, win, ctx); ++ ++ if (printInfo) { ++ printf("GL_RENDERER = %s\n", (char *) glGetString(GL_RENDERER)); ++ printf("GL_VERSION = %s\n", (char *) glGetString(GL_VERSION)); ++ printf("GL_VENDOR = %s\n", (char *) glGetString(GL_VENDOR)); ++ printf("GL_EXTENSIONS = %s\n", (char *) glGetString(GL_EXTENSIONS)); ++ } ++ ++ Init(argc, argv, dpy, DefaultScreen(dpy), win); ++ ++ scr_Display(); ++ glXSwapBuffers(dpy, win); ++ event_loop(dpy, win); ++ ++ glXFreeMemoryMESA(dpy, DefaultScreen(dpy), glx_memory); ++ glXDestroyContext(dpy, ctx); ++ XDestroyWindow(dpy, win); ++ XCloseDisplay(dpy); ++ ++ return 0; ++} -- cgit v1.2.3 From dffb97743b7b8c5611f7b5ac24ceaa30c3caa92c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 13 Jun 2010 03:41:50 +0200 Subject: xorg-server: enable glx along with dri --- package/xorg-server/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'package') diff --git a/package/xorg-server/Makefile b/package/xorg-server/Makefile index 17ad6e8b9..07a2c8ed5 100644 --- a/package/xorg-server/Makefile +++ b/package/xorg-server/Makefile @@ -46,7 +46,6 @@ CONFIGURE_ARGS+= \ --enable-dpms \ --disable-aiglx \ --disable-config-hal \ - --disable-glx \ --disable-xace \ --disable-xephyr \ --disable-xf86bigfont \ @@ -65,9 +64,9 @@ CONFIGURE_ARGS+= \ --with-vendor-web="http://openadk.org" ifeq (${ADK_PACKAGE_XORG_SERVER_WITH_DRI},y) -CONFIGURE_ARGS+= --enable-dri --enable-dri2 +CONFIGURE_ARGS+= --enable-dri --enable-dri2 --enable-glx else -CONFIGURE_ARGS+= --disable-dri --disable-dri2 +CONFIGURE_ARGS+= --disable-dri --disable-dri2 --disable-glx endif ifeq (${ADK_LINUX_MIPS64_LEMOTE},y) -- cgit v1.2.3 From 59d394a67db43c38767af9fb496754bbe6dde153 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 13 Jun 2010 03:44:48 +0200 Subject: libdrm: add lemote specific fixes --- .../libdrm/patches/patch-include_drm_drm_sarea_h | 12 +++++++ package/libdrm/patches/patch-xf86drm_h | 42 ++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 package/libdrm/patches/patch-include_drm_drm_sarea_h create mode 100644 package/libdrm/patches/patch-xf86drm_h (limited to 'package') diff --git a/package/libdrm/patches/patch-include_drm_drm_sarea_h b/package/libdrm/patches/patch-include_drm_drm_sarea_h new file mode 100644 index 000000000..d7d557dcf --- /dev/null +++ b/package/libdrm/patches/patch-include_drm_drm_sarea_h @@ -0,0 +1,12 @@ + Fix for lemote. +--- libdrm-2.4.20.orig/include/drm/drm_sarea.h 2010-03-06 00:21:13.000000000 +0100 ++++ libdrm-2.4.20/include/drm/drm_sarea.h 2010-06-12 20:44:24.812809619 +0200 +@@ -37,6 +37,8 @@ + /* SAREA area needs to be at least a page */ + #if defined(__alpha__) + #define SAREA_MAX 0x2000U ++#elif defined(__mips__) ++#define SAREA_MAX 0x4000U + #elif defined(__ia64__) + #define SAREA_MAX 0x10000U /* 64kB */ + #else diff --git a/package/libdrm/patches/patch-xf86drm_h b/package/libdrm/patches/patch-xf86drm_h new file mode 100644 index 000000000..aa3f49cca --- /dev/null +++ b/package/libdrm/patches/patch-xf86drm_h @@ -0,0 +1,42 @@ + Fix for lemote. +--- libdrm-2.4.20.orig/xf86drm.h 2010-03-06 00:21:13.000000000 +0100 ++++ libdrm-2.4.20/xf86drm.h 2010-06-12 20:43:01.324916826 +0200 +@@ -374,6 +374,29 @@ typedef struct _drmSetVersion { + : "memory"); \ + } while (0) + ++#elif defined(__mips__) ++ ++#define DRM_CAS(lock, old, new, ret) \ ++ do { \ ++ __asm__ __volatile__( \ ++ " .set mips3;.set noreorder;\n" \ ++ " sync; \n" \ ++ " ll %1, %0;\n" \ ++ " bne %1, %2, 1f;\n" \ ++ " li %1, 1; \n" \ ++ " move %1, %3; \n" \ ++ " sc %1, %0;\n" \ ++ " xori %1, %1, 1\n" \ ++ "1: \n" \ ++ " .set mips0; .set reorder;\n" \ ++ : "=m" (__drm_dummy_lock(lock)),\ ++ "=&r" (ret) \ ++ : "r" (old), \ ++ "r" (new) \ ++ : "memory","$8" \ ++ ); \ ++ } while(0) ++ + #elif defined(__sparc__) + + #define DRM_CAS(lock,old,new,__ret) \ +@@ -457,7 +480,7 @@ do { register unsigned int __old __asm(" + + #if defined(__alpha__) + #define DRM_CAS_RESULT(_result) long _result +-#elif defined(__powerpc__) ++#elif defined(__powerpc__) || defined(__mips__) + #define DRM_CAS_RESULT(_result) int _result + #else + #define DRM_CAS_RESULT(_result) char _result -- cgit v1.2.3 From 62b3bb88ed3c766badca5304d0e169fc652d856c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 13 Jun 2010 03:45:57 +0200 Subject: port xvinfo --- package/Config.in | 1 + package/xvinfo/Makefile | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 package/xvinfo/Makefile (limited to 'package') diff --git a/package/Config.in b/package/Config.in index 000403d56..969e84b34 100644 --- a/package/Config.in +++ b/package/Config.in @@ -634,6 +634,7 @@ source "package/xauth/Config.in" source "package/xinit/Config.in" source "package/xlsfonts/Config.in" source "package/xterm/Config.in" +source "package/xvinfo/Config.in" endmenu menu "X fonts" diff --git a/package/xvinfo/Makefile b/package/xvinfo/Makefile new file mode 100644 index 000000000..ceebddd9f --- /dev/null +++ b/package/xvinfo/Makefile @@ -0,0 +1,26 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= xvinfo +PKG_VERSION:= 1.1.0 +PKG_RELEASE:= 1 +PKG_MD5SUM:= cc00d609136ecc0b6b571dc42740a675 +PKG_DESCR:= Print out X-Video extension adaptor information +PKG_SECTION:= x11 +PKG_DEPENDS:= xorg-server +KG_BUILDDEP+= xorg-server +PKG_URL:= http://xorg.freedesktop.org/ +PKG_SITES:= http://xorg.freedesktop.org/archive/individual/app/ + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,XVINFO,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +post-install: + $(INSTALL_DIR) $(IDIR_XVINFO)/usr/bin + $(INSTALL_BIN) $(WRKINST)/usr/bin/xvinfo \ + $(IDIR_XVINFO)/usr/bin + +include ${TOPDIR}/mk/pkg-bottom.mk -- cgit v1.2.3 From 1ee28515a05409a80379bf03e8604cef1ab0f473 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 13 Jun 2010 15:15:06 +0200 Subject: do not use ${INSTALL_BIN} for libraries Better use ${CP}, as ${INSTALL_BIN} follows the symlinks and therefore creates duplicate files. While here, also fix the build-deps of libXfixes. --- package/MesaLib/Makefile | 4 ++-- package/libXfixes/Makefile | 2 +- package/libXxf86vm/Makefile | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'package') diff --git a/package/MesaLib/Makefile b/package/MesaLib/Makefile index 5836f994f..043034947 100644 --- a/package/MesaLib/Makefile +++ b/package/MesaLib/Makefile @@ -61,7 +61,7 @@ pre-configure: ); ${MAKE} -C ${WRKBUILD}/src/glsl ${MAKE} -C ${WRKBUILD}/src/glsl/apps - cp ${WRKBUILD}/src/glsl/apps/compile \ + ${CP} ${WRKBUILD}/src/glsl/apps/compile \ ${STAGING_TOOLS}/bin ${MAKE} -C ${WRKBUILD}/src/glsl clean @@ -70,7 +70,7 @@ post-install: $(CP) $(WRKINST)/usr/lib/libGL*.so* \ $(IDIR_MESALIB)/usr/lib ifeq (${ADK_LINUX_MIPS64_LEMOTE},y) - $(INSTALL_BIN) $(WRKINST)/usr/lib/dri/swrast_dri.so \ + ${CP} $(WRKINST)/usr/lib/dri/swrast_dri.so \ ${IDIR_MESALIB}/usr/lib/dri/ endif ${INSTALL_DIR} ${IDIR_GLXINFO}/usr/bin diff --git a/package/libXfixes/Makefile b/package/libXfixes/Makefile index a9e3c7a27..283a043ce 100644 --- a/package/libXfixes/Makefile +++ b/package/libXfixes/Makefile @@ -9,7 +9,7 @@ PKG_RELEASE:= 1 PKG_MD5SUM:= 86eb4b916cd5948c0e20d279107b3331 PKG_DESCR:= X Fixes Library PKG_SECTION:= libs -PKG_BUILDDEP+= fixesproto +PKG_BUILDDEP+= fixesproto xextproto xproto libX11 PKG_URL:= http://xorg.freedesktop.org PKG_SITES:= http://xorg.freedesktop.org/archive/individual/lib/ diff --git a/package/libXxf86vm/Makefile b/package/libXxf86vm/Makefile index 41816b575..1465ee1ac 100644 --- a/package/libXxf86vm/Makefile +++ b/package/libXxf86vm/Makefile @@ -20,7 +20,7 @@ CONFIGURE_ARGS+= --disable-malloc0returnsnull post-install: $(INSTALL_DIR) $(IDIR_LIBXXF86VM)/usr/lib - $(INSTALL_BIN) $(WRKINST)/usr/lib/libXxf86vm*.so* \ + ${CP} $(WRKINST)/usr/lib/libXxf86vm*.so* \ $(IDIR_LIBXXF86VM)/usr/lib include ${TOPDIR}/mk/pkg-bottom.mk -- cgit v1.2.3 From 811342f7eb50ed9fa34ef2684a0a0e8650628fd8 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Mon, 14 Jun 2010 01:42:40 +0200 Subject: port qingy and it's dependencies DirectFB and libXScrnSaver --- package/Config.in | 5 ++ package/DirectFB/Makefile | 55 +++++++++++++++++++ package/DirectFB/files/DirectFB.conffiles | 1 + package/DirectFB/files/directfbrc | 4 ++ package/libXScrnSaver/Makefile | 27 ++++++++++ package/qingy/Makefile | 39 ++++++++++++++ package/qingy/files/post_GUI.sh | 10 ++++ package/qingy/files/pre_GUI.sh | 11 ++++ package/qingy/files/qingy.conffiles | 4 ++ package/qingy/files/qingy.postinst | 12 +++++ package/qingy/files/settings | 90 +++++++++++++++++++++++++++++++ package/qingy/files/welcomes | 1 + 12 files changed, 259 insertions(+) create mode 100644 package/DirectFB/Makefile create mode 100644 package/DirectFB/files/DirectFB.conffiles create mode 100644 package/DirectFB/files/directfbrc create mode 100644 package/libXScrnSaver/Makefile create mode 100644 package/qingy/Makefile create mode 100644 package/qingy/files/post_GUI.sh create mode 100644 package/qingy/files/pre_GUI.sh create mode 100644 package/qingy/files/qingy.conffiles create mode 100644 package/qingy/files/qingy.postinst create mode 100644 package/qingy/files/settings create mode 100644 package/qingy/files/welcomes (limited to 'package') diff --git a/package/Config.in b/package/Config.in index 969e84b34..9d29f7f11 100644 --- a/package/Config.in +++ b/package/Config.in @@ -174,6 +174,8 @@ source "package/cxxtools/Config.in" source "package/dbus/Config.in" source "package/dbus-glib/Config.in" source "package/dbus-glib/Config.in.lib" +source "package/DirectFB/Config.in" +source "package/DirectFB/Config.in.lib" source "package/e2fsprogs/Config.in.lib" source "package/fltk/Config.in" source "package/fltk/Config.in.lib" @@ -628,6 +630,7 @@ source "package/dillo/Config.in" source "package/evilwm/Config.in" source "package/firefox/Config.in" source "package/font-util/Config.in" +source "package/qingy/Config.in" source "package/rxvt-unicode/Config.in" source "package/twm/Config.in" source "package/xauth/Config.in" @@ -692,6 +695,8 @@ source "package/libXpm/Config.in" source "package/libXpm/Config.in.lib" source "package/libXrender/Config.in" source "package/libXrender/Config.in.lib" +source "package/libXScrnSaver/Config.in" +source "package/libXScrnSaver/Config.in.lib" source "package/libXt/Config.in" source "package/libXt/Config.in.lib" source "package/libXft/Config.in" diff --git a/package/DirectFB/Makefile b/package/DirectFB/Makefile new file mode 100644 index 000000000..e6da5984a --- /dev/null +++ b/package/DirectFB/Makefile @@ -0,0 +1,55 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= DirectFB +PKG_VERSION:= 1.4.3 +PKG_RELEASE:= 1 +PKG_MD5SUM:= 223e036da906ceb4bd44708026839ff1 +PKG_DESCR:= Thin library on top of the Linux framebuffer devices +PKG_SECTION:= libs +PKG_BUILDDEP:= libpng +PKG_DEPENDS:= libpng +PKG_URL:= http://www.directfb.org/ +PKG_SITES:= http://directfb.org/downloads/Core/DirectFB-1.4/ + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,DIRECTFB,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +CONFIGURE_ARGS+= --with-inputdrivers=linuxinput,keyboard,ps2mouse \ + --with-gfxdrivers=none \ + --disable-osx + +# This is to overcome libtool fuckup - when building without, +# libtool calls (the correct) ld directly without parameters, +# which then chooses the wrong default emulation (which is +# probably the real problem here). LDEMULATION overrides ld's +# wrong choice. +ifeq (${ADK_LINUX_MIPS64_LEMOTE},y) +XAKE_FLAGS+= LDEMULATION=elf64ltsmip +endif + +post-install: + ${INSTALL_DIR} ${IDIR_DIRECTFB}/etc + ${INSTALL_DATA} ./files/directfbrc ${IDIR_DIRECTFB}/etc/ + $(INSTALL_DIR) $(IDIR_DIRECTFB)/usr/lib/directfb-1.4-0/{inputdrivers,systems,wm} + ${CP} $(WRKINST)/usr/lib/lib{direct,fusion}*.so* \ + $(IDIR_DIRECTFB)/usr/lib/ + ${CP} ${WRKINST}/usr/lib/directfb-1.4-0/inputdrivers/libdirectfb_linux_input.so \ + ${IDIR_DIRECTFB}/usr/lib/directfb-1.4-0/inputdrivers/ + ${CP} ${WRKINST}/usr/lib/directfb-1.4-0/systems/*.so \ + ${IDIR_DIRECTFB}/usr/lib/directfb-1.4-0/systems/ + ${CP} ${WRKINST}/usr/lib/directfb-1.4-0/wm/*.so \ + ${IDIR_DIRECTFB}/usr/lib/directfb-1.4-0/wm/ + $(INSTALL_DIR) $(IDIR_DIRECTFB)/usr/lib/directfb-1.4-0/interfaces/IDirectFB{Font,ImageProvider,VideoProvider} + ${CP} ${WRKINST}/usr/lib/directfb-1.4-0/interfaces/IDirectFBFont/*.so \ + ${IDIR_DIRECTFB}/usr/lib/directfb-1.4-0/interfaces/IDirectFBFont/ + ${CP} ${WRKINST}/usr/lib/directfb-1.4-0/interfaces/IDirectFBImageProvider/*.so \ + ${IDIR_DIRECTFB}/usr/lib/directfb-1.4-0/interfaces/IDirectFBImageProvider/ + ${CP} ${WRKINST}/usr/lib/directfb-1.4-0/interfaces/IDirectFBVideoProvider/*.so \ + ${IDIR_DIRECTFB}/usr/lib/directfb-1.4-0/interfaces/IDirectFBVideoProvider/ + + +include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/DirectFB/files/DirectFB.conffiles b/package/DirectFB/files/DirectFB.conffiles new file mode 100644 index 000000000..d4d8e0024 --- /dev/null +++ b/package/DirectFB/files/DirectFB.conffiles @@ -0,0 +1 @@ +/etc/directfbrc diff --git a/package/DirectFB/files/directfbrc b/package/DirectFB/files/directfbrc new file mode 100644 index 000000000..c0e563e86 --- /dev/null +++ b/package/DirectFB/files/directfbrc @@ -0,0 +1,4 @@ +#mode=1024x600 +#depth=16 +mouse-protocol=IMPS/2 +mouse-source=/dev/psaux diff --git a/package/libXScrnSaver/Makefile b/package/libXScrnSaver/Makefile new file mode 100644 index 000000000..06ef24ebd --- /dev/null +++ b/package/libXScrnSaver/Makefile @@ -0,0 +1,27 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= libXScrnSaver +PKG_VERSION:= 1.2.0 +PKG_RELEASE:= 1 +PKG_MD5SUM:= 72ca7f37e4a1794acbdd9ab047821e8b +PKG_DESCR:= X.Org XScrnSaver library +PKG_SECTION:= libs +PKG_BUILDDEP:= scrnsaverproto +PKG_URL:= http://xorg.freedesktop.org/ +PKG_SITES:= ${MASTER_SITE_XORG} + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,LIBXSCRNSAVER,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +CONFIGURE_ARGS+= --enable-malloc0returnsnull + +post-install: + $(INSTALL_DIR) $(IDIR_LIBXSCRNSAVER)/usr/lib + ${CP} $(WRKINST)/usr/lib/libXss.so* \ + $(IDIR_LIBXSCRNSAVER)/usr/lib/ + +include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/qingy/Makefile b/package/qingy/Makefile new file mode 100644 index 000000000..e78b94d1a --- /dev/null +++ b/package/qingy/Makefile @@ -0,0 +1,39 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= qingy +PKG_VERSION:= 0.9.9 +PKG_RELEASE:= 1 +PKG_MD5SUM:= 34f40172a71e9a6c2c77ddce11d2a63a +PKG_DESCR:= a DirectFB getty replacement +PKG_SECTION:= x11 +PKG_DEPENDS:= DirectFB libXScrnSaver +PKG_BUILDDEP+= DirectFB libXScrnSaver +PKG_URL:= http://qingy.sourceforge.net/ +PKG_SITES:= ${MASTER_SITE_SOURCEFORGE:=qingy/} + +DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.bz2 + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,QINGY,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +CONFIGURE_ARGS+= --disable-screen-savers \ + --disable-pam \ + --disable-crypto + +post-install: + $(INSTALL_DIR) $(IDIR_QINGY)/etc/qingy/sessions + ${INSTALL_BIN} ./files/{pre,post}_GUI.sh ${IDIR_QINGY}/etc/qingy/ + ${INSTALL_DATA} ./files/{settings,welcomes} ${IDIR_QINGY}/etc/qingy/ + touch ${IDIR_QINGY}/etc/qingy/sessions/.keep_me + $(INSTALL_DIR) $(IDIR_QINGY)/usr/lib/qingy + ${CP} $(WRKINST)/usr/lib/qingy/libqingy*.so ${IDIR_QINGY}/usr/lib/qingy/ + $(INSTALL_DIR) $(IDIR_QINGY)/usr/sbin + ${INSTALL_BIN} $(WRKINST)/usr/sbin/qingy* ${IDIR_QINGY}/usr/sbin/ + $(INSTALL_DIR) $(IDIR_QINGY)/usr/share/qingy + ${CP} $(WRKINST)/usr/share/qingy/themes ${IDIR_QINGY}/usr/share/ + +include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/qingy/files/post_GUI.sh b/package/qingy/files/post_GUI.sh new file mode 100644 index 000000000..fa46d024a --- /dev/null +++ b/package/qingy/files/post_GUI.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +filename="/tmp/qingy_restart_gpm" + +if [ -f $filename ]; then + + /etc/init.d/gpm start >/dev/null 2>/dev/null + rm $filename + +fi diff --git a/package/qingy/files/pre_GUI.sh b/package/qingy/files/pre_GUI.sh new file mode 100644 index 000000000..2c0fff1fb --- /dev/null +++ b/package/qingy/files/pre_GUI.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +filename="/tmp/qingy_restart_gpm" +status=`pgrep gpm` + +if [ "$status" != "" ]; then + + /etc/init.d/gpm stop >/dev/null 2>/dev/null + touch $filename + +fi diff --git a/package/qingy/files/qingy.conffiles b/package/qingy/files/qingy.conffiles new file mode 100644 index 000000000..332648b28 --- /dev/null +++ b/package/qingy/files/qingy.conffiles @@ -0,0 +1,4 @@ +/etc/qingy/settings +/etc/qingy/welcomes +/etc/qingy/pre_GUI.sh +/etc/qingy/post_GUI.sh diff --git a/package/qingy/files/qingy.postinst b/package/qingy/files/qingy.postinst new file mode 100644 index 000000000..a68f5fe90 --- /dev/null +++ b/package/qingy/files/qingy.postinst @@ -0,0 +1,12 @@ +#!/bin/sh + +cat < Date: Mon, 14 Jun 2010 01:58:12 +0200 Subject: mplayer: add DirectFB video out flavour --- package/mplayer/Makefile | 24 +++++++++++++++++++++++- package/mplayer/patches/patch-configure | 11 +++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 package/mplayer/patches/patch-configure (limited to 'package') diff --git a/package/mplayer/Makefile b/package/mplayer/Makefile index 791908d23..bf6279350 100644 --- a/package/mplayer/Makefile +++ b/package/mplayer/Makefile @@ -14,9 +14,16 @@ PKG_DEPENDS+= libogg libpng libpthread libvorbis PKG_DEPENDS+= libx11 libxau libxdmcp libxext libxv zlib PKG_BUILDDEP+= alsa-lib libmad libvorbis faad2 ncurses zlib PKG_BUILDDEP+= libX11 libXv libpng libXext +ifeq (${ADK_PACKAGE_MPD_WITH_DIRECTFB},y) +PKG_DEPENDS+= DirectFB +PKG_BUILDDEP+= DirectFB +endif PKG_URL:= http://www.mplayerhq.hu PKG_SITES:= http://openadk.org/distfiles/ +PKG_FLAVOURS:= WITH_DIRECTFB +PKGFD_WITH_DIRECTFB:= enable DirectFB video output support + PKG_TARGET_DEPENDS:= alix1c x86_qemu x86_64_qemu shuttle lemote include ${TOPDIR}/mk/package.mk @@ -31,6 +38,14 @@ ifeq (${ADK_LINUX_MIPS64_LOONGSON},y) XAKE_FLAGS+= -DHAVE_LOONGSON -DARCH_MIPS64 endif +# Somehow this include path is missing here, although other +# applications build fine against DirectFB. There is also a +# related patch to allow configure to find out the DirectFB +# version number. +ifeq (${ADK_PACKAGE_MPD_WITH_DIRECTFB},y) +TCFLAGS+= -I${STAGING_DIR}/usr/include/directfb +endif + ifeq (${ADK_LINUX_X86_ALIX1C},y) CONFIGURE_CPU_OPTS:= \ --disable-ssse3 \ @@ -55,6 +70,12 @@ ifeq ($(ADK_DEBUG),y) CONFIGURE_DEBUG= --enable-debug endif +ifeq (${ADK_PACKAGE_MPD_WITH_DIRECTFB},y) +CONFIGURE_DIRECTFB=--enable-directfb +else +CONFIGURE_DIRECTFB=--disable-directfb +endif + pre-configure: (cd ${WRKBUILD}; rm -rf config.{cache,status} ; \ ./configure \ @@ -105,8 +126,9 @@ pre-configure: --disable-vidix \ ${CONFIGURE_CPU_OPTS} \ ${CONFIGURE_DEBUG} \ + ${CONFIGURE_DIRECTFB} \ ); - + post-install: ${INSTALL_DIR} ${IDIR_MPLAYER}/usr/bin ${CP} ${WRKINST}/usr/bin/mplayer ${IDIR_MPLAYER}/usr/bin diff --git a/package/mplayer/patches/patch-configure b/package/mplayer/patches/patch-configure new file mode 100644 index 000000000..aabaf8282 --- /dev/null +++ b/package/mplayer/patches/patch-configure @@ -0,0 +1,11 @@ +--- mplayer-1.0-29987.orig/configure 2009-12-10 13:18:20.000000000 +0100 ++++ mplayer-1.0-29987/configure 2010-06-13 22:58:34.756925268 +0200 +@@ -4141,7 +4141,7 @@ dfb_version() { + + if test "$_directfb" = yes; then + cat > $TMPC << EOF +-#include ++#include + int + dfb_ver = DIRECTFB_MAJOR_VERSION.DIRECTFB_MINOR_VERSION.DIRECTFB_MICRO_VERSION + ; -- cgit v1.2.3 From 85bb2caf7878cee50b323efdf3d6d69668294e4a Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 15 Jun 2010 22:25:42 +0200 Subject: alsa-utils: add flavour for alsamixer --- package/alsa-utils/Makefile | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'package') diff --git a/package/alsa-utils/Makefile b/package/alsa-utils/Makefile index 63ce6faf5..00920a740 100644 --- a/package/alsa-utils/Makefile +++ b/package/alsa-utils/Makefile @@ -11,20 +11,35 @@ PKG_DESCR:= ALSA mixer utility PKG_SECTION:= utils PKG_DEPENDS:= alsa-lib libpthread PKG_BUILDDEP+= alsa-lib +ifeq (${ADK_PACKAGE_ALSA_UTILS_WITH_ALSAMIXER},y) +PKG_DEPENDS+= libncurses +PKG_BUILDDEP+= libncurses +endif PKG_URL:= http://www.alsa-project.org PKG_SITES:= ftp://ftp.task.gda.pl/pub/linux/misc/alsa/utils/ \ ftp://ftp.alsa-project.org/pub/utils/ +PKG_FLAVOURS:= WITH_ALSAMIXER +PKGFD_WITH_ALSAMIXER:= include alsamixer ncurses applet + DISTFILES:= ${PKG_NAME}-${PKG_VERSION}.tar.bz2 include ${TOPDIR}/mk/package.mk $(eval $(call PKG_template,ALSA_UTILS,${PKG_NAME},${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +ifeq (${ADK_PACKAGE_ALSA_UTILS_WITH_ALSAMIXER},y) +CONFIGURE_ARGS+= --enable-alsamixer +else CONFIGURE_ARGS+= --disable-alsamixer +endif post-install: - ${INSTALL_DIR} ${IDIR_ALSA_UTILS}/usr/bin + ${INSTALL_DIR} ${IDIR_ALSA_UTILS}/usr/bin/ ${CP} ${WRKINST}/usr/bin/amixer ${IDIR_ALSA_UTILS}/usr/bin/ +ifeq (${ADK_PACKAGE_ALSA_UTILS_WITH_ALSAMIXER},y) + ${INSTALL_BIN} ${WRKINST}/usr/bin/alsamixer \ + ${IDIR_ALSA_UTILS}/usr/bin/ +endif include ${TOPDIR}/mk/pkg-bottom.mk -- cgit v1.2.3 From 8d0f44c0762a52bbe5d3313382295dbc2e1fcb35 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 15 Jun 2010 22:33:40 +0200 Subject: fonts: hack font-util so I can compile font-misc-misc --- package/font-misc-misc/Makefile | 2 ++ package/font-misc-misc/patches/patch-configure | 11 +++++++++++ package/font-util/Makefile | 12 +++++++++++- 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 package/font-misc-misc/patches/patch-configure (limited to 'package') diff --git a/package/font-misc-misc/Makefile b/package/font-misc-misc/Makefile index f60f867ad..2487a68c8 100644 --- a/package/font-misc-misc/Makefile +++ b/package/font-misc-misc/Makefile @@ -19,6 +19,8 @@ include $(TOPDIR)/mk/package.mk $(eval $(call PKG_template,FONT_MISC_MISC,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +CONFIGURE_ENV+= MAPFILES_PATH=${STAGING_DIR}/usr/share/fonts/X11/util + post-install: $(INSTALL_DIR) $(IDIR_FONT_MISC_MISC)/usr/share/fonts/X11/misc $(CP) ${WRKINST}/usr/share/fonts/X11/misc/* \ diff --git a/package/font-misc-misc/patches/patch-configure b/package/font-misc-misc/patches/patch-configure new file mode 100644 index 000000000..acbc7f8ce --- /dev/null +++ b/package/font-misc-misc/patches/patch-configure @@ -0,0 +1,11 @@ +--- font-misc-misc-1.1.0.orig/configure 2009-10-11 03:23:03.000000000 +0200 ++++ font-misc-misc-1.1.0/configure 2010-06-15 00:35:59.189800221 +0200 +@@ -5544,7 +5544,7 @@ $as_echo "yes" >&6; } + fi + { $as_echo "$as_me:$LINENO: checking for ucs2any encoding data files" >&5 + $as_echo_n "checking for ucs2any encoding data files... " >&6; } +- MAPFILES_PATH=`pkg-config --variable=mapdir fontutil` ++# MAPFILES_PATH=`pkg-config --variable=mapdir fontutil` + + { $as_echo "$as_me:$LINENO: result: ${MAPFILES_PATH}" >&5 + $as_echo "${MAPFILES_PATH}" >&6; } diff --git a/package/font-util/Makefile b/package/font-util/Makefile index cdd1632b2..b3faf7f7e 100644 --- a/package/font-util/Makefile +++ b/package/font-util/Makefile @@ -16,7 +16,17 @@ include ${TOPDIR}/mk/package.mk $(eval $(call PKG_template,FONT_UTIL,${PKG_NAME},${PKG_VERSION}-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION},${PKG_OPTS})) -post-install: +# XXX: Push the mapping files to a place where we can find them +# again when compiling the actual fonts. This is ugly as hell, +# especially as all font packages still need patching to avoid +# calling pkg-config (which we don't provide) in order to +# automatically find the mappings. +fonts-hack: + ${INSTALL_DIR} ${STAGING_DIR}/usr/share/fonts/X11/util + ${CP} ${WRKINST}/usr/share/fonts/X11/util/* \ + ${STAGING_DIR}/usr/share/fonts/X11/util + +post-install: fonts-hack ${INSTALL_DIR} ${IDIR_FONT_UTIL}/usr/share/fonts/X11/util ${CP} ${WRKINST}/usr/share/fonts/X11/util/* \ ${IDIR_FONT_UTIL}/usr/share/fonts/X11/util -- cgit v1.2.3 From 70891937006fcfe387e4a1ba5d03acd6f5f37662 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 15 Jun 2010 22:39:36 +0200 Subject: port fluxbox and it's (optional) dependency imlib2 --- package/Config.in | 2 ++ package/fluxbox/Makefile | 41 +++++++++++++++++++++++++++++++++++++++++ package/imlib2/Makefile | 29 +++++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 package/fluxbox/Makefile create mode 100644 package/imlib2/Makefile (limited to 'package') diff --git a/package/Config.in b/package/Config.in index 9d29f7f11..8922d7900 100644 --- a/package/Config.in +++ b/package/Config.in @@ -186,6 +186,7 @@ source "package/glib/Config.in" source "package/gtk+/Config.in" source "package/heimdal/Config.in.lib" source "package/id3lib/Config.in" +source "package/imlib2/Config.in" source "package/libao/Config.in" source "package/libao/Config.in.lib" source "package/libaudiofile/Config.in" @@ -629,6 +630,7 @@ menu "X applications" source "package/dillo/Config.in" source "package/evilwm/Config.in" source "package/firefox/Config.in" +source "package/fluxbox/Config.in" source "package/font-util/Config.in" source "package/qingy/Config.in" source "package/rxvt-unicode/Config.in" diff --git a/package/fluxbox/Makefile b/package/fluxbox/Makefile new file mode 100644 index 000000000..89c3df5ed --- /dev/null +++ b/package/fluxbox/Makefile @@ -0,0 +1,41 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= fluxbox +PKG_VERSION:= 1.1.1 +PKG_RELEASE:= 1 +PKG_MD5SUM:= e0be927617be4ffc1ddc79513f4eb0f9 +PKG_DESCR:= Fluxbox is an X11 window manager featuring tabs and an iconbar +PKG_SECTION:= x11 +PKG_DEPENDS:= libstdcxx +PKG_BUILDDEP:= libXpm +ifeq (${ADK_PACKAGE_FLUXBOX_WITH_IMLIB2},y) +PKG_DEPENDS+= imlib2 +PKG_BUILDDEP+= imlib2 +endif +PKG_URL:= http://www.fluxbox.org +PKG_SITES:= ${MASTER_SITE_SOURCEFORGE:=fluxbox/} + +PKG_FLAVOURS:= WITH_IMLIB2 +PKGFD_WITH_IMLIB2:= enable imlib2 support + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,FLUXBOX,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +ifeq (${ADK_PACKAGE_FLUXBOX_WITH_IMLIB2},y) +CONFIGURE_ARGS+= --enable-imlib2 +else +#CONFIGURE_ARGS+= --disable-imlib2 +CONFIGURE_ARGS+= --enable-imlib2 +endif + +post-install: + $(INSTALL_DIR) $(IDIR_FLUXBOX)/usr/{bin,share} + $(INSTALL_BIN) $(WRKINST)/usr/bin/* \ + $(IDIR_FLUXBOX)/usr/bin + ${CP} ${WRKINST}/usr/share/fluxbox ${IDIR_FLUXBOX}/usr/share/ + +include ${TOPDIR}/mk/pkg-bottom.mk diff --git a/package/imlib2/Makefile b/package/imlib2/Makefile new file mode 100644 index 000000000..bc7f6ea14 --- /dev/null +++ b/package/imlib2/Makefile @@ -0,0 +1,29 @@ +# This file is part of the OpenADK project. OpenADK is copyrighted +# material, please see the LICENCE file in the top-level directory. + +include $(TOPDIR)/rules.mk + +PKG_NAME:= imlib2 +PKG_VERSION:= 1.4.4 +PKG_RELEASE:= 1 +PKG_MD5SUM:= 20d59c7cda06742015baade6f5975415 +PKG_DESCR:= Version 2 of an advanced replacement library for libraries like libXpm +PKG_SECTION:= libs +PKG_DEPENDS:= libfreetype +PKG_BUILDDEP:= libfreetype +PKG_URL:= http://www.enlightenment.org/ +PKG_SITES:= ${MASTER_SITE_SOURCEFORGE:=enlightenment/} + +include $(TOPDIR)/mk/package.mk + +$(eval $(call PKG_template,IMLIB2,$(PKG_NAME),$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) + +post-install: + $(INSTALL_DIR) $(IDIR_IMLIB2)/usr/lib/imlib2/{filters,loaders} + ${CP} $(WRKINST)/usr/lib/libImlib2.so* $(IDIR_IMLIB2)/usr/lib + ${CP} $(WRKINST)/usr/lib/imlib2/filters/*.so \ + $(IDIR_IMLIB2)/usr/lib/imlib2/filters/ + ${CP} $(WRKINST)/usr/lib/imlib2/loaders/*.so \ + $(IDIR_IMLIB2)/usr/lib/imlib2/loaders/ + +include ${TOPDIR}/mk/pkg-bottom.mk -- cgit v1.2.3 From 18d98330bdc4891b4a04de2492e6542f601cdc3c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sat, 19 Jun 2010 15:54:54 +0200 Subject: pkgmaker: warn on unreachable dependency This is what actually should have happened whenever you saw 'cannot open $() input' error message, which was quite useless when it comes to tracking the source of the error down. --- package/pkgmaker | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'package') diff --git a/package/pkgmaker b/package/pkgmaker index 4cf2181ef..677a44d08 100644 --- a/package/pkgmaker +++ b/package/pkgmaker @@ -216,6 +216,10 @@ for dn in */Makefile; do (*) # produce dependency on regular package # where the symbol is cached (see above) + if [[ ! -f ../pkglist.d/"$dep" ]]; then + print -u2 "Warning: $PKG_NAME: unreachable dependency '$dep'" + continue + fi print -u$h '\tselect' \ ADK_PACKAGE_$(<../pkglist.d/"$dep") ;; -- cgit v1.2.3 From d3576611f3c7811bc0dd29ec92b953dbccded3cc Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 20 Jun 2010 14:01:24 +0200 Subject: xorg-server: fix dri dependencies These *proto packages may be used as PKG_BUILDDEP only, as they actually don't define a real package (missing PKG_template in Makefile). This wasn't a fatal bug, just pkgmaker complaining about it. --- package/xorg-server/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'package') diff --git a/package/xorg-server/Makefile b/package/xorg-server/Makefile index 07a2c8ed5..554f84ba3 100644 --- a/package/xorg-server/Makefile +++ b/package/xorg-server/Makefile @@ -19,7 +19,7 @@ PKG_BUILDDEP+= libX11 randrproto renderproto fixesproto damageproto \ libpciaccess openssl xf86dgaproto ifeq (${ADK_PACKAGE_XORG_SERVER_WITH_DRI},y) PKG_BUILDDEP+= xf86driproto glproto dri2proto MesaLib -PKG_DEPENDS+= xf86driproto glproto dri2proto mesalib +PKG_DEPENDS+= mesalib endif PKG_URL:= http://www.x.org PKG_SITES:= http://xorg.freedesktop.org/archive/individual/xserver/ -- cgit v1.2.3 From 19d35b947f30b2b3ac98ff039832ae46df7fee8c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 20 Jun 2010 15:58:00 +0200 Subject: libXi: minor fixup (use MASTER_SITE_SOURCEFORGE and PKG_NAME) --- package/dillo/Makefile | 2 +- package/libXi/Makefile | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'package') diff --git a/package/dillo/Makefile b/package/dillo/Makefile index 07e2de442..618346234 100644 --- a/package/dillo/Makefile +++ b/package/dillo/Makefile @@ -9,7 +9,7 @@ PKG_RELEASE:= 1 PKG_MD5SUM:= f8bcd62093f178bed81e46cc54e73f42 PKG_DESCR:= small graphical web browser PKG_SECTION:= x11 -PKG_DEPENDS:= libfltk libxi libiconv libpng zlib libjpeg +PKG_DEPENDS:= libfltk libXi libiconv libpng zlib libjpeg PKG_BUILDDEP+= fltk libiconv jpeg libpng zlib PKG_URL:= http://www.dillo.org/ PKG_SITES:= http://www.dillo.org/download/ diff --git a/package/libXi/Makefile b/package/libXi/Makefile index 097b902d3..e3c97b139 100644 --- a/package/libXi/Makefile +++ b/package/libXi/Makefile @@ -11,13 +11,13 @@ PKG_DESCR:= X Window System client interface to the XINPUT extension to the X p PKG_SECTION:= x11 PKG_BUILDDEP+= xproto xextproto libXext PKG_URL:= http://xorg.freedesktop.org/ -PKG_SITES:= http://xorg.freedesktop.org/releases/individual/lib/ +PKG_SITES:= ${MASTER_SITE_XORG} include $(TOPDIR)/mk/package.mk -$(eval $(call PKG_template,LIBXI,libxi,$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) +$(eval $(call PKG_template,LIBXI,${PKG_NAME},$(PKG_VERSION)-${PKG_RELEASE},${PKG_DEPENDS},${PKG_DESCR},${PKG_SECTION})) -CONFIGURE_ARGS+= --disable-malloc0returnsnull +CONFIGURE_ARGS+= --disable-malloc0returnsnull post-install: $(INSTALL_DIR) $(IDIR_LIBXI)/usr/lib -- cgit v1.2.3