]> git.hungrycats.org Git - xscreensaver/commitdiff
From https://www.jwz.org/xscreensaver/xscreensaver-6.14.tar.gz
authorZygo Blaxell <zblaxell@waya.furryterror.org>
Fri, 16 Jan 2026 16:28:07 +0000 (11:28 -0500)
committerZygo Blaxell <xss@mirrors.furryterror.org>
Fri, 16 Jan 2026 16:28:32 +0000 (11:28 -0500)
-rw-rw-r-- 1 zblaxell zblaxell 25206667 Jan 15 17:31 xscreensaver-6.14.tar.gz
e559f0135bdcc81e4582a650984e8624edc20125  xscreensaver-6.14.tar.gz

310 files changed:
Makefile.in
OSX/Makefile
OSX/README
OSX/Randomizer.plist
OSX/SaverRunner.m
OSX/SaverRunner.plist
OSX/Sparkle.framework/Versions/B/Autoupdate
OSX/Sparkle.framework/Versions/B/Headers/SPUStandardUpdaterController.h
OSX/Sparkle.framework/Versions/B/Headers/SPUStandardUserDriver.h
OSX/Sparkle.framework/Versions/B/Headers/SPUUpdater.h
OSX/Sparkle.framework/Versions/B/Headers/SPUUpdaterDelegate.h
OSX/Sparkle.framework/Versions/B/Headers/SPUUpdaterSettings.h
OSX/Sparkle.framework/Versions/B/Headers/SPUUserDriver.h
OSX/Sparkle.framework/Versions/B/Headers/SUAppcastItem.h
OSX/Sparkle.framework/Versions/B/Headers/SUErrors.h
OSX/Sparkle.framework/Versions/B/Headers/SUUpdater.h
OSX/Sparkle.framework/Versions/B/Headers/SUUpdaterDelegate.h
OSX/Sparkle.framework/Versions/B/Modules/module.modulemap
OSX/Sparkle.framework/Versions/B/Modules/module.private.modulemap [new file with mode: 0644]
OSX/Sparkle.framework/Versions/B/PrivateHeaders/SPUInstallationType.h
OSX/Sparkle.framework/Versions/B/PrivateHeaders/SUAppcastItem+Private.h
OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdateAlert.nib [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/Info.plist
OSX/Sparkle.framework/Versions/B/Resources/SUStatus.nib
OSX/Sparkle.framework/Versions/B/Resources/SUUpdateAlert.nib [new file with mode: 0644]
OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib [new file with mode: 0644]
OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib [new file with mode: 0644]
OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/ca.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ca.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/da.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/da.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/da.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/de.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/de.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/de.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/el.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/el.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/el.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/en.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/en.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/es.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/es.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/es.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/fa.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/he.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/he.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/is.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/is.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/is.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/it.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/it.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/it.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/nn.lproj/Sparkle.strings [new file with mode: 0644]
OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/th.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/th.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/th.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/SUUpdateAlert.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.strings [deleted file]
OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/Sparkle.strings
OSX/Sparkle.framework/Versions/B/Sparkle
OSX/Sparkle.framework/Versions/B/Updater.app/Contents/Info.plist
OSX/Sparkle.framework/Versions/B/Updater.app/Contents/MacOS/Updater
OSX/Sparkle.framework/Versions/B/Updater.app/Contents/Resources/SUStatus.nib
OSX/Sparkle.framework/Versions/B/Updater.app/Contents/_CodeSignature/CodeResources
OSX/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc/Contents/Info.plist
OSX/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc/Contents/MacOS/Downloader
OSX/Sparkle.framework/Versions/B/XPCServices/Installer.xpc/Contents/Info.plist
OSX/Sparkle.framework/Versions/B/XPCServices/Installer.xpc/Contents/MacOS/Installer
OSX/Sparkle.framework/Versions/B/_CodeSignature/CodeResources
OSX/Updater.plist
OSX/XScreenSaver.plist
OSX/XScreenSaverConfigSheet.m
OSX/XScreenSaverGLView.m
OSX/XScreenSaverView.m
OSX/bindist.rtf
OSX/build-fntable.pl
OSX/iSaverRunner.plist
OSX/installer.sh
OSX/ios-function-table.m
OSX/perl-minimize.pl
OSX/sparkle-bin/BinaryDelta
OSX/sparkle-bin/generate_appcast
OSX/sparkle-bin/generate_keys
OSX/sparkle-bin/sign_update
OSX/tvSaverRunner.plist
OSX/update-info-plist.pl
OSX/updates.xml
OSX/xscreensaver.xcodeproj/project.pbxproj
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/AlienBeacon.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/BatteredPlanet.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/ElementalRing.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/FluxCore.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/GimbalHarmonics.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/HexPlasma.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/LogarithmicCircles.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/NeonGravity.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/NeonTriangulator.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Protophore.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/SelfReflect.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Skyline.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StarDome.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StarNest.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StripeyTorus.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/SynthwaveCity.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Topologica.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/TruchetZoom.xcscheme [new file with mode: 0644]
OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/XShadertoy.xcscheme [new file with mode: 0644]
README
android/Makefile
android/README
android/xscreensaver/jni/Android.mk
android/xscreensaver/src/org/jwz/xscreensaver/jwxyz.java
config.h.in
configure
configure.ac
debian/changelog
debian/control
debian/postinst
debian/prerm
debian/rules
driver/Makefile.in
driver/XScreenSaver.ad.in
driver/XScreenSaver_ad.h
driver/demo-Gtk.c
driver/fade.c
driver/passwd-pam.c
driver/screens.c
driver/subprocs.c
driver/windows.c
driver/xscreensaver.man
driver/xscreensaver.pam [new file with mode: 0644]
driver/xscreensaver.pam.in [deleted file]
driver/xscreensaver.service.in
hacks/Makefile.in
hacks/check-configs.pl
hacks/config/README
hacks/config/alienbeacon.xml [new file with mode: 0644]
hacks/config/batteredplanet.xml [new file with mode: 0644]
hacks/config/elementalring.xml [new file with mode: 0644]
hacks/config/fluxcore.xml [new file with mode: 0644]
hacks/config/gimbalharmonics.xml [new file with mode: 0644]
hacks/config/glslideshow.xml
hacks/config/hexplasma.xml [new file with mode: 0644]
hacks/config/logarithmiccircles.xml [new file with mode: 0644]
hacks/config/neongravity.xml [new file with mode: 0644]
hacks/config/neontriangulator.xml [new file with mode: 0644]
hacks/config/protophore.xml [new file with mode: 0644]
hacks/config/selfreflect.xml [new file with mode: 0644]
hacks/config/skyline.xml [new file with mode: 0644]
hacks/config/stardome.xml [new file with mode: 0644]
hacks/config/starnest.xml [new file with mode: 0644]
hacks/config/stripeytorus.xml [new file with mode: 0644]
hacks/config/synthwavecity.xml [new file with mode: 0644]
hacks/config/topologica.xml [new file with mode: 0644]
hacks/config/truchetzoom.xml [new file with mode: 0644]
hacks/flame.c
hacks/fonts/Makefile.in
hacks/glx/Makefile.in
hacks/glx/alienbeacon.man [new file with mode: 0644]
hacks/glx/batteredplanet.man [new file with mode: 0644]
hacks/glx/carousel.c
hacks/glx/cubocteversion.c
hacks/glx/elementalring.man [new file with mode: 0644]
hacks/glx/etruscanvenus.c
hacks/glx/flurry-texture.c
hacks/glx/fluxcore.man [new file with mode: 0644]
hacks/glx/gimbalharmonics.man [new file with mode: 0644]
hacks/glx/glhanoi.c
hacks/glx/glsl-utils.c
hacks/glx/glsl-utils.h
hacks/glx/glsl/README [new file with mode: 0644]
hacks/glx/glsl/alienbeacon.glsl [new file with mode: 0644]
hacks/glx/glsl/batteredplanet.glsl [new file with mode: 0644]
hacks/glx/glsl/elementalring.glsl [new file with mode: 0644]
hacks/glx/glsl/fluxcore.glsl [new file with mode: 0644]
hacks/glx/glsl/gimbalharmonics.glsl [new file with mode: 0644]
hacks/glx/glsl/hexplasma.glsl [new file with mode: 0644]
hacks/glx/glsl/logarithmiccircles.glsl [new file with mode: 0644]
hacks/glx/glsl/neongravity-0.glsl [new file with mode: 0644]
hacks/glx/glsl/neongravity-1.glsl [new file with mode: 0644]
hacks/glx/glsl/neontriangulator.glsl [new file with mode: 0644]
hacks/glx/glsl/protophore.glsl [new file with mode: 0644]
hacks/glx/glsl/selfreflect.glsl [new file with mode: 0644]
hacks/glx/glsl/skyline.glsl [new file with mode: 0644]
hacks/glx/glsl/stardome.glsl [new file with mode: 0644]
hacks/glx/glsl/starnest.glsl [new file with mode: 0644]
hacks/glx/glsl/stripeytorus.glsl [new file with mode: 0644]
hacks/glx/glsl/synthwavecity.glsl [new file with mode: 0644]
hacks/glx/glsl/topologica.glsl [new file with mode: 0644]
hacks/glx/glsl/truchetzoom.glsl [new file with mode: 0644]
hacks/glx/glslideshow.c
hacks/glx/hexplasma.man [new file with mode: 0644]
hacks/glx/hopffibration.c
hacks/glx/hypertorus.c
hacks/glx/klein.c
hacks/glx/logarithmiccircles.man [new file with mode: 0644]
hacks/glx/molecules.sh
hacks/glx/neongravity.man [new file with mode: 0644]
hacks/glx/neontriangulator.man [new file with mode: 0644]
hacks/glx/photopile.c
hacks/glx/platonicfolding.c
hacks/glx/projectiveplane.c
hacks/glx/protophore.man [new file with mode: 0644]
hacks/glx/romanboy.c
hacks/glx/selfreflect.man [new file with mode: 0644]
hacks/glx/skyline.man [new file with mode: 0644]
hacks/glx/sphereeversion-analytic.c
hacks/glx/sphereeversion-corrugations.c
hacks/glx/sphereeversion.c
hacks/glx/sphereeversion.h
hacks/glx/stardome.man [new file with mode: 0644]
hacks/glx/starnest.man [new file with mode: 0644]
hacks/glx/stripeytorus.man [new file with mode: 0644]
hacks/glx/synthwavecity.man [new file with mode: 0644]
hacks/glx/texfont.c
hacks/glx/texfont.h
hacks/glx/topologica.man [new file with mode: 0644]
hacks/glx/truchetzoom.man [new file with mode: 0644]
hacks/glx/xshadertoy-compile.pl [new file with mode: 0755]
hacks/glx/xshadertoy-download.pl [new file with mode: 0755]
hacks/glx/xshadertoy.c [new file with mode: 0644]
hacks/glx/xshadertoy.man [new file with mode: 0644]
hacks/images/Makefile
hacks/images/Makefile.in
hacks/m6502.sh
hacks/munge-ad.pl
hacks/recanim.c
hacks/recanim.h
hacks/screenhackI.h
hacks/xml2man.pl
hacks/xscreensaver-getimage.c
jwxyz/Makefile.in
jwxyz/jwxyz-android.c
jwxyz/jwxyz.h
po/POTFILES.in
utils/Makefile.in
utils/bin2c
utils/version.h
utils/visual-gl.c
utils/xftwrap.c
xscreensaver.spec

index fbac48c6046bd1ebd306dc65518ad86a4b32df5e..e5d9a86596e999f1323db0fdf3a5ad48c3bf8c46 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in --- xscreensaver, Copyright © 1999-2025 Jamie Zawinski.
+# Makefile.in --- xscreensaver, Copyright © 1999-2026 Jamie Zawinski.
 # the `../configure' script generates `Makefile' from this file.
 
 @SET_MAKE@
@@ -93,39 +93,38 @@ _tar:
   VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h |   \
        head -1` ;                                                          \
   NAME="xscreensaver-$$VERS" ;                                             \
-  rm -rf $$NAME ; ln -s . $$NAME ;                                         \
+  rm -rf "$$NAME" ; ln -s . "$$NAME" ;                                     \
   LIST="tar$$$$.txt" ;                                                     \
   ADIR="$(TAR_DIR)" ;                                                      \
   [ -d "$$ADIR" ] || mkdir "$$ADIR" ;                                      \
   rm -f "$$LIST" ;                                                         \
   for subdir in . $(SUBDIRS2) ; do                                         \
-    ( cd $$subdir ;                                                        \
+    ( cd "$$subdir" || exit 1 ;                                                    \
       $(MAKE2) list_tarfiles                                               \
         | grep -v '^.*make\['                                              \
         | sed -e "s@^@$$NAME/$$subdir/@g"                                  \
         | sed -e "s@/\./@/@g"                                              \
     ) >> "$$LIST" ;                                                        \
   done ;                                                                   \
-  echo creating tar file $$ADIR/$$NAME.tar.gz... ;                         \
+  echo "creating tar file $$ADIR/$$NAME.tar.gz..." ;                       \
   export COPYFILE_DISABLE=true ;                                           \
   export GZIP="-9v" ;                                                      \
-  $(TAR) -czf $$ADIR/$$NAME.tar.gz -T "$$LIST" $(TAR_ARGS) ;               \
+  $(TAR) -czf "$$ADIR/$$NAME.tar.gz" -T "$$LIST" $(TAR_ARGS) ;             \
   rm "$$LIST" "$$NAME"
 
+# Getting a warning about "GZIP environment variable is deprecated";
+# maybe use tar --options='compression-level=9'
+
 
-# This also makes me sick...
-# autoconf generates a configure script that begins with a very hard to read,
-# nearly impossible to customize --help blurb.  This horrid set of regexps
-# go through and clean up the help text, by inserting whitespace and ripping
-# out options we don't use.  Odds are good that this will fail with any version
-# of autoconf other than the ones I've tried (2.12 and 2.13.)
-#
 configure::
        rm -f configure
        aclocal
        autoconf
        autoheader
 
+# Remove inapplicable lines from the "configure --help" message,
+# to make it less confusing.
+#
 configure::
        @TMP=configure.$$$$ ;                                                \
        echo "munging configure's --help message..." ;                       \
@@ -134,20 +133,32 @@ configure::
                while (<>) { $$file .= $$_; }                                \
                $$_ = $$file;                                                \
                                                                             \
-               s/\nInstallation directories:.*?\n\n/\n/s;                   \
+               s/\nFine tuning .*?:.*?\n\n/\n/si;                           \
+               s/\nBy default, .*?:.*?\n\n/\n/si;                           \
                s/\nOptional Features:.*?\n\n/\n/s;                          \
                s/\nOptional Packages:.*?\n\n/\n/s;                          \
                                                                             \
+               s/^ +--help=short.*\n//m;                                    \
+               s/^ +--help=recursive.*\n//m;                                \
                s/^ +--sbindir=.*\n//m;                                      \
                s/^ +--sysconfdir.*\n//m;                                    \
                s/^ +--sharedstatedir.*\n.*\n//m;                            \
                s/^ +--oldincludedir.*\n//m;                                 \
+               s/^ +--includedir.*\n//m;                                    \
                s/^ +--infodir.*\n//m;                                       \
                s/^ +--htmldir.*\n//m;                                       \
                s/^ +--dvidir.*\n//m;                                        \
                s/^ +--pdfdir.*\n//m;                                        \
                s/^ +--psdir.*\n//m;                                         \
+               s/^ +--runstatedir.*\n//m;                                   \
+               s/^ +--docdir.*\n//m;                                        \
+               s/^ +--libdir.*\n//m;                                        \
+               s/^ +--localedir.*\n//m;                                     \
                s/^ +--with-x .*\n//m;                                       \
+               s/^ +--enable-year2038.*\n//m;                               \
+               s/^ +--with-xinput.*\n//m;                                   \
+               s/^ +XMKMF.*\n//m;                                           \
+               s/^ *Report bugs to.*\n//m;                                  \
                                                                             \
                s/(\n\n)\n+/$$1/gs;                                          \
                                                                             \
@@ -155,9 +166,9 @@ configure::
                                                                             \
                print;'                                                      \
        < configure                                                          \
-       > $$TMP &&                                                           \
-       cat $$TMP > configure ) ;                                            \
-       rm -f $$TMP
+       > "$$TMP" &&                                                         \
+       cat "$$TMP" > configure ) ;                                          \
+       rm -f "$$TMP"
 
 # WARNING: This stands a good chance of breaking the world.
 # Be prepared to roll back all of /opt/local/ from Time Machine.
@@ -182,13 +193,13 @@ bump-version::
   if [ -z "$$SUF" ]; then                                                  \
     MINOR=`echo $$((MINOR + 1)) | sed 's/^\(.\)$$/0\1/'` ;                 \
   else                                                                     \
-    set - `echo $$SUF | sed 's/^\([^0-9]*\)/\1 /'` ;                       \
+    set - `echo "$$SUF" | sed 's/^\([^0-9]*\)/\1 /'` ;                     \
     AA="$$1"; BB="$$2";                                                            \
     BB=$$((BB + 1)) ;                                                      \
     SUF="$$AA$$BB" ;                                                       \
   fi ;                                                                     \
   VERS2="$$MAJOR.$$MINOR$$SUF" ;                                           \
-  ADIR=archive/ ;                                                          \
+  ADIR="archive/" ;                                                        \
   if [ ! -f "$${ADIR}xscreensaver-$$VERS.tar.gz" ]; then                   \
    echo "WARNING: $${ADIR}xscreensaver-$$VERS.tar.gz does not exist.";     \
   fi ;                                                                     \
@@ -196,8 +207,8 @@ bump-version::
     echo "WARNING: $${ADIR}xscreensaver-$$VERS2.tar.gz already exists.";    \
   fi ;                                                                     \
   /bin/echo -n "Bumping $$VERS to $$VERS2, ok? ";                          \
-  read line;                                                               \
-  if [ "x$$line" != "xyes" -a  "x$$line" != "xy" ]; then                   \
+  read -r line;                                                                    \
+  if [ "$$line" != "yes" ] &&  [ "$$line" != "y" ]; then                   \
     exit 1 ;                                                               \
   fi ;                                                                     \
                                                                            \
@@ -213,7 +224,7 @@ bump-version::
                                                                            \
   VERS3=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. \"]*\).*/\1/p' < $$SRC |       \
         tail -1`;                                                          \
-  if [ x"$$VERS2" != x"$$VERS3" ]; then                                            \
+  if [ "$$VERS2" != "$$VERS3" ]; then                                      \
     echo "ERROR! \"$$VERS2\" vs \"$$VERS3\"!" ;                                    \
     exit 1 ;                                                               \
   fi ;                                                                     \
@@ -238,12 +249,12 @@ version-date::
   sed -e "s/\([0-9]\.[0-9][^. \"]*\)/$$VERS/"                              \
       -e "s/([0-9][^()]*)/($$D)/"                                          \
       -e "s/\(_RELEASED  *\)[0-9][0-9]*/\1$$TIME_T/"                       \
-    < $$SRC > $$TMP ;                                                      \
-  if ! cmp -s $$SRC $$TMP ; then                                           \
-    cat $$TMP > $$SRC ;                                                            \
+    < "$$SRC" > "$$TMP" ;                                                  \
+  if ! cmp -s "$$SRC" "$$TMP" ; then                                       \
+    cat "$$TMP" > "$$SRC" ;                                                \
     echo "Updated $$SRC date to \"$$D\"" ;                                 \
   fi ;                                                                     \
-  rm -f $$TMP
+  rm -f "$$TMP"
 
 
 update_spec_version::
@@ -253,7 +264,7 @@ update_spec_version::
        U=$(srcdir)/utils/version.h ;                                       \
        VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' < $$U |       \
          head -1` ;                                                        \
-       T=/tmp/xs.$$$$ ;                                                    \
+       T="/tmp/xs.$$$$" ;                                                  \
        for F in "$$S1" "$$S2" ; do                                         \
          /bin/echo -n "Updating $$F to \"$$VERS\"... " ;                   \
          sed -e "s/^\(%define.version[^0-9]*\)\(.*\)/\1$$VERS/"            \
@@ -266,7 +277,7 @@ update_spec_version::
            echo "done." ;                                                  \
          fi ;                                                              \
        done ;                                                              \
-       rm $$T
+       rm "$$T"
 
 rpm::
        @                                                                  \
@@ -275,17 +286,19 @@ rpm::
   DIR=`pwd`/rpm_build ;                                                           \
   ARCH=`rpm --showrc | sed -n 's/^build arch *: //p'` ;                           \
   ADIR=archive/ ;                                                         \
-  TGZ=xscreensaver-$$VERS.tar.gz ;                                        \
-  if [ ! -f $${ADIR}$$TGZ ]; then                                         \
+  TGZ="xscreensaver-$$VERS.tar.gz" ;                                      \
+  if [ ! -f "$${ADIR}$$TGZ" ]; then                                       \
     echo "$${ADIR}$$TGZ does not exist: do 'make tar' first." ;                   \
     exit 1 ;                                                              \
   fi ;                                                                    \
-  rm -rf /var/tmp/xscreensaver-$$VERS-root ;                              \
-  rm -rf $$DIR ;                                                          \
-  mkdir $$DIR ;                                                                   \
-  ( cd $$DIR; mkdir BUILD RPMS RPMS/$$ARCH SOURCES SPECS SRPMS ) ;        \
-  cp -p $${ADIR}$$TGZ $$DIR/SOURCES/ ;                                    \
+  rm -rf "/var/tmp/xscreensaver-$$VERS-root" ;                            \
+  rm -rf "$$DIR" ;                                                        \
+  mkdir "$$DIR" ;                                                         \
+  ( cd "$$DIR" || exit 1 ;                                                \
+    mkdir BUILD RPMS RPMS/"$$ARCH" SOURCES SPECS SRPMS ) ;                \
+  cp -p "$${ADIR}$$TGZ" "$$DIR/SOURCES/" ;                                \
   set -x ;                                                                \
+  set -e ;                                                                \
   rpmbuild --define "_topdir $$DIR"                                       \
            --define "USE_GL yes"                                          \
            --nodeps                                                       \
@@ -294,13 +307,11 @@ rpm::
   echo '' ;                                                               \
   echo 'RPM build complete' ;                                             \
   echo '' ;                                                               \
-  rm -f $$DIR/$$TGZ ;                                                     \
-  rm -rf $$DIR/BUILD/xscreensaver-$$VERS ;                                \
-  mv $$DIR/SRPMS/xscreensaver*-$$VERS-*.rpm . ;                                   \
-  mv $$DIR/RPMS/$$ARCH/xscreensaver*-$$VERS-*.rpm . ;                     \
-  rm -rf $$DIR ;                                                          \
+  mv "$$DIR/SRPMS/xscreensaver"*-"$$VERS"-*.rpm . ;                       \
+  mv "$$DIR/RPMS/$$ARCH/xscreensaver"*-"$$VERS"-*.rpm . ;                 \
+  rm -rf "$$DIR" ;                                                        \
   echo '' ;                                                               \
-  ls -lFG xscreensaver*-$$VERS-*.rpm
+  ls -lFG xscreensaver*-"$$VERS"-*.rpm
 
 deb::
        @                                                                  \
@@ -308,22 +319,22 @@ deb::
          head -1` ;                                                       \
   DIR=debian/build ;                                                      \
   ADIR=archive/ ;                                                         \
-  TGZ=xscreensaver-$$VERS.tar.gz ;                                        \
-  TGZ2=xscreensaver_$$VERS.orig.tar.gz ;                                  \
-  if [ ! -f $${ADIR}$$TGZ ]; then                                         \
+  TGZ="xscreensaver-$$VERS.tar.gz" ;                                      \
+  TGZ2="xscreensaver_$$VERS.orig.tar.gz" ;                                \
+  if [ ! -f "$${ADIR}$$TGZ" ]; then                                       \
     echo "$${ADIR}$$TGZ does not exist: do 'make tar' first." ;                   \
     exit 1 ;                                                              \
   fi ;                                                                    \
                                                                           \
   set -e ;                                                                \
   set -x ;                                                                \
-  rm -rf $$DIR ;                                                          \
-  mkdir $$DIR ;                                                                   \
+  rm -rf "$$DIR" ;                                                        \
+  mkdir "$$DIR" ;                                                         \
   cp -p "$${ADIR}$$TGZ" "$$DIR/$$TGZ2" ;                                  \
                                                                           \
-  ( cd $$DIR ;                                                            \
+  ( cd "$$DIR" || exit 1 ;                                                \
     $(TAR) -zxf "$$TGZ2" ;                                                \
-    cd xscreensaver-$$VERS ;                                              \
+    cd "xscreensaver-$$VERS" ;                                            \
     dpkg-buildpackage -us -uc ;                                                   \
   ) ;                                                                     \
   set +x ;                                                                \
@@ -347,7 +358,7 @@ www_versions::
   VERS=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^. ]*\).*/\1/p' utils/version.h |   \
          head -1` ;                                                        \
   TMP=/tmp/xd.$$$$ ;                                                       \
-  for f in $$DEST/*.html ; do                                              \
+  for f in "$$DEST"/*.html ; do                                                    \
     sed "s/\(CLASS=.latest.>\)[^<>]*\(<\)/\1$$VERS\2/gi" < "$$f" > "$$TMP" ;\
     if ! cmp -s "$$f" "$$TMP" ; then                                       \
       diff -U0 "$$f" "$$TMP" ;                                             \
@@ -381,37 +392,37 @@ www::
   $(MAKE2) www_versions ;                                                  \
   $(MAKE2) -C OSX updates.xml ;                                                    \
                                                                            \
-  if [ ! -f $$NAME ]; then                                                 \
+  if [ ! -f "$$NAME" ]; then                                               \
     echo "$$NAME does not exist!  Did you forget to \`make tar'?" ;        \
     exit 1 ;                                                               \
   fi ;                                                                     \
-  if [ ! -f $$NAME2 ]; then                                                \
+  if [ ! -f "$$NAME2" ]; then                                              \
     echo "$$NAME2 does not exist!  Did you forget to \`make dmg'?" ;       \
     exit 1 ;                                                               \
   fi ;                                                                     \
-  if [ ! -f $$NAME3 ]; then                                                \
+  if [ ! -f "$$NAME3" ]; then                                              \
     echo "$$NAME3 does not exist!  Did you forget to \`make apk'?" ;       \
     exit 1 ;                                                               \
   fi ;                                                                     \
-  chmod a-w $$NAME ;                                                       \
-  if [ -f $$DNAME ]; then                                                  \
+  chmod a-w "$$NAME" ;                                                     \
+  if [ -f "$$DNAME" ]; then                                                \
     /bin/echo -n "WARNING: $$DNAME already exists!  Overwrite? ";          \
-    read line;                                                             \
-    if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then                  \
+    read -r line;                                                          \
+    if [ "$$line" != "yes" ] && [ "$$line" != "y" ]; then                  \
       exit 1 ;                                                                     \
     fi ;                                                                   \
   fi ;                                                                     \
-  if [ -f $$DNAME2 ]; then                                                 \
+  if [ -f "$$DNAME2" ]; then                                               \
     /bin/echo -n "WARNING: $$DNAME2 already exists!  Overwrite? ";         \
-    read line;                                                             \
-    if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then                  \
+    read -r line;                                                          \
+    if [ "$$line" != "yes" ] && [ "$$line" != "y" ]; then                  \
       exit 1 ;                                                                     \
     fi ;                                                                   \
   fi ;                                                                     \
-  if [ -f $$DNAME3 ]; then                                                 \
+  if [ -f "$$DNAME3" ]; then                                               \
     /bin/echo -n "WARNING: $$DNAME3 already exists!  Overwrite? ";         \
-    read line;                                                             \
-    if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then                  \
+    read -r line;                                                          \
+    if [ "$$line" != "yes" ] && [ "$$line" != "y" ]; then                  \
       exit 1 ;                                                                     \
     fi ;                                                                   \
   fi ;                                                                     \
@@ -419,49 +430,49 @@ www::
   git tag -a "v$$VERS" -m "$$VERS" ;                                       \
   git commit -m "$$VERS" . ;                                               \
                                                                            \
-  ( cd $$DEST ;        git pull ) ;                                                \
+  ( cd "$$DEST" || exit 1 ; git pull ) ;                                   \
                                                                            \
-  cp -p $$NAME $$DNAME ;                                                   \
-  cp -p $$NAME2 $$DNAME2 ;                                                 \
-  cp -p $$NAME3 $$DNAME3 ;                                                 \
-  chmod u+w $$DNAME $$DNAME2 $$DNAME3 ;                                            \
-  cp -p OSX/updates.xml $$DEST ;                                           \
-  cd $$DEST ;                                                              \
+  cp -p "$$NAME" "$$DNAME" ;                                               \
+  cp -p "$$NAME2" "$$DNAME2" ;                                             \
+  cp -p "$$NAME3" "$$DNAME3" ;                                             \
+  chmod u+w "$$DNAME" "$$DNAME2" "$$DNAME3" ;                              \
+  cp -p OSX/updates.xml "$$DEST" ;                                         \
+  cd "$$DEST" || exit 1 ;                                                  \
                                                                            \
-  TMP=/tmp/xd.$$$$ ;                                                       \
-  sed "s/xscreensaver-[56]\.[0-9][0-9ab]*/$$HEAD/g" download.html > $$TMP ; \
+  TMP="/tmp/xd.$$$$" ;                                                     \
+  sed "s/xscreensaver-[56]\.[0-9][0-9ab]*/$$HEAD/g" download.html > "$$TMP" ; \
   echo '' ;                                                                \
-  diff -U0 download.html $$TMP ;                                           \
+  diff -U0 download.html "$$TMP" ;                                         \
   echo '' ;                                                                \
                                                                            \
   for EXT in tar.gz dmg apk ; do                                           \
     OLDEST=`ls xscreensaver*.$$EXT |                                       \
-      fgrep -v 5.14 |                                                      \
-      fgrep -v 5.34 |                                                      \
-      fgrep -v 6.00 |                                                      \
+      grep -F -v 5.14 |                                                            \
+      grep -F -v 5.34 |                                                            \
+      grep -F -v 6.00 |                                                            \
       head -n 1` ;                                                         \
     /bin/echo -n "Delete $$DEST/$$OLDEST? ";                               \
-    read line;                                                             \
-    if [ "x$$line" = "xyes" -o "x$$line" = "xy" ]; then                            \
+    read -r line;                                                          \
+    if [ "$$line" = "yes" ] || [ "$$line" = "y" ]; then                            \
       set -x ;                                                             \
-      rm $$OLDEST ;                                                        \
-      git rm $$OLDEST ;                                                            \
+      rm "$$OLDEST" ;                                                      \
+      git rm "$$OLDEST" ;                                                  \
       set +x ;                                                             \
     fi ;                                                                   \
   done ;                                                                   \
   set -x ;                                                                 \
-  cat $$TMP > download.html ;                                              \
-  rm -f $$TMP ;                                                                    \
+  cat "$$TMP" > download.html ;                                                    \
+  rm -f "$$TMP" ;                                                          \
                                                                            \
-  git add $$BNAME $$BNAME2 $$BNAME3 ;                                      \
+  git add "$$BNAME" "$$BNAME2" "$$BNAME3" ;                                \
                                                                            \
   $(MAKE2) -C ../ xscreensaver/changelog.html xscreensaver/screenshots/index.html; \
   git diff changelog.html ;                                                \
   set +x ;                                                                 \
                                                                            \
   /bin/echo -n "Ok? ";                                                     \
-  read line;                                                               \
-  if [ "x$$line" != "xyes" -a "x$$line" != "xy" ]; then                            \
+  read -r line;                                                                    \
+  if [ "$$line" != "yes" ] && [ "$$line" != "y" ]; then                            \
     exit 1 ;                                                               \
   fi ;                                                                     \
                                                                            \
@@ -473,11 +484,11 @@ www::
 count::
        @ \
   echo "Current hack count: " ;                                                \
-  A=`cd hacks ;     ( make -s INSTALL=true install-man |               \
-    grep true | grep -v helper | grep -v ljlatest | wc -l )` ;         \
+  A=`make -C hacks     -s INSTALL=true install-man |                   \
+    grep -F .man | grep -v xscreensaver- | wc -l` ;                    \
   echo "    X11:" $$A ;                                                        \
-  B=`cd hacks/glx ; ( make -s INSTALL=true install-man |               \
-    grep true | grep -v helper | grep -v ljlatest | wc -l )` ;         \
+  B=`make -C hacks/glx -s INSTALL=true install-man |                   \
+    grep -F .man | grep -v xscreensaver- | wc -l` ;                    \
   echo "    GLX:" $$B ;                                                        \
   C=$$((A + B)) ;                                                      \
   echo "  Total:" $$C ;                                                        \
@@ -492,9 +503,9 @@ install_links::
          set -e ;                                                      \
          $(MAKE2) install -k INSTALL=true INSTALL_DATA=true            \
               INSTALL_DIRS=false SUID_FLAGS= 2>&- |                    \
-         while read s ; do                                             \
+         while read -r s ; do                                          \
            set - $$s ;                                                 \
-           if [ $$1 = true ]; then                                     \
+           if [ "$$1" = true ]; then                                   \
              a="$$cwd/$$d/$$2" ;                                       \
              b="$$3" ;                                                 \
              d2=`dirname "$$b"` ;                                      \
@@ -509,12 +520,13 @@ install_links::
 
 
 cerebrum::
-       rsync -vax . 10.0.1.42:xscreensaver/ \
+       rsync -vax . 10.0.1.37:xscreensaver/ \
        --omit-dir-times \
        --delete-during \
        --exclude .git \
        --exclude archive \
        --exclude build \
+       --exclude rpm_build \
        --exclude gen \
        --exclude videos \
        --exclude config.h \
@@ -531,6 +543,7 @@ cerebrum::
        --exclude '*~' \
        --include '*.asm' \
        --include '*.c' \
+       --include '*.glsl' \
        --include '*.gif' \
        --include '*.h' \
        --include '*.in' \
@@ -550,6 +563,7 @@ cerebrum::
        --include '*.pl' \
        --include '*.spec' \
        --include '*.ad' \
+       --include '*.pam' \
        --include 'configure*' \
        --include 'config.sub' \
        --include 'config.guess' \
@@ -560,6 +574,7 @@ cerebrum::
        --include 'vidwhacker' \
        --include 'webcollage' \
        --include 'debian/*' \
+       --include 'debian/*/*' \
        --include 'README' \
        --include 'README.hacking' \
        --include 'INSTALL' \
index 394ec5ad765d36dcf08838055f6fd1cd963be298..25fd756922440f3986852ef99f9413d116cd1b47 100644 (file)
@@ -50,7 +50,7 @@ release::
 
 Sparkle.framework:
        rm -rf bin sparkle-bin
-       tar -vxjf ../archive/Sparkle-2.5.0.tar.xz \
+       tar -vxjf ../archive/Sparkle-2.8.1.tar.xz \
          --exclude __MACOSX \
          --exclude CHANGELOG \
          --exclude LICENSE \
index ab027b0a9fef5bfee46209786a2c7101bf7e3009..52009222c81096305cdc4bfac411bde278b96098 100644 (file)
@@ -99,7 +99,8 @@ Building for older operating systems:
   my benefit.  I tried to automate some of this with Applescript but that
   appears to be impossible.
 
-  1: Duplicate a target (Dangerball for GL, or Attraction for X11).
+  1: Duplicate a target (Dangerball for GL, Attraction for X11,
+     StarNest for Shadertoy).
   2: Rename it, and drag it to the right spot in the list.
   3: Delete the "DangerBall copy-Info.plist" file that got created.
   4: Delete the dangerball.c and dangerball.xml files from Build Phases.
@@ -109,20 +110,21 @@ Building for older operating systems:
   8. Scheme / Profile / Info: Executable: SaverTester.app.
      Scheme / Run / Info: Executable: SaverTester.app.
   9: Scheme / Run / Arguments: set SELECTED_SAVER environment variable.
- 10: File / Add Files / [x] Reference In Place / the new .c and .xml.
+ 10: File / Add Files / [x] Reference In Place / the new .c, .xml and .glsl.
      Add To Targets: the new target, and "XScreenSaver-iOS" and "-tvOS".
- 11: Re-order the two files in the file list on the left.
- 12: The files might not have moved. This means Xcode is gonna crash soon.
-     It will repair itself after.
- 13: In target "All Savers (OpenGL)" add the new target as Build Phases /
+ 11: Re-order the new files in the file list on the left.
+ 12: In target "All Savers (OpenGL)" add the new target as Build Phases /
      Target Dependency.
- 14: In target "XScreenSaver-iOS", reorder new files in Build Phases /
+ 13: In target "XScreenSaver-iOS", reorder new files in Build Phases /
      "Copy" and "Compile", since they showed up in a random place.
- 15: In target "XScreenSaver-iOS", add "-DUSE_GL" to the new file's options.
- 16: Put a 720p screen shot in ~/www/xscreensaver/screenshots/
- 17: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \
+ 14: In target "XScreenSaver-iOS", add "-DUSE_GL" to the new file's options.
+ 15: Put a 720p screen shot in ~/www/xscreensaver/screenshots/
+     convert -crop 2560x1440+0+44 -resize 1280x \
+       grab-NNNNNN.png ~/www/xscreensaver/screenshots/NEW.jpg
+ 16: ln -s ../../src/xscreensaver/OSX/build/Debug/NEW.saver \
            ~/Library/Screen\ Savers/
- 18: git add xscreensaver.xcodeproj/xcshareddata/xcschemes/*.xcscheme
- 19: Create a man page from the XML with xml2man.pl, and update Makefile.in.
- 20: Upload a YouTube video: -record-animation 2min -geom 1920x1080+128+64
+ 17: git add xscreensaver.xcodeproj/xcshareddata/xcschemes/*.xcscheme
+ 18: Create a man page from the XML with xml2man.pl, and update Makefile.in.
+ 19: Upload a YouTube video:
+     --record-animation 2min --delay 0 -geom 1920x1080+128+64
      ./upload-video.pl NAME
index e00b033815116849f366e423be35cf27adaf25b4..fc777d6d2c6af72b6c8b2ec6afd2e760e2f0b0d8 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.13</string>
+       <string>6.14</string>
 </dict>
 </plist>
index c281396376bc5fc23fe68383bda8444592e809b9..1ad8053d6760002cae119e8d3366cb015e91627b 100644 (file)
@@ -1078,7 +1078,7 @@ relabel_menus (NSObject *v, NSString *old_str, NSString *new_str)
     p = [dir stringByAppendingPathComponent: p];
 
     NSString *classname = [[p lastPathComponent] stringByDeletingPathExtension];
-    NSString *title;
+    NSString *title = 0;
 
     // Get the title's capitalization right by reading the XML file.
 
index 3c5a81eab8eba8157c5bb9859303b26edf65fd8c..24738a1b00fa60031ae2c1fba876756e1bd615f9 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
        <key>CFBundleIconFile</key>
index a4d07ca640fb5c7c0e109316d5b4d256e1c7a7bc..bea793f2933fe2b8d034f2de044907a1c63b39cd 100755 (executable)
Binary files a/OSX/Sparkle.framework/Versions/B/Autoupdate and b/OSX/Sparkle.framework/Versions/B/Autoupdate differ
index 2ebce1aaa75391edb7320d4a46859a24c04b205e..43774e1cf994fc8ee53c35e7945edd4c16d8f079 100644 (file)
@@ -28,15 +28,17 @@ NS_ASSUME_NONNULL_BEGIN
 /**
  A controller class that instantiates a `SPUUpdater` and allows binding UI to its updater settings.
  
- This class can be instantiated in a nib or created programatically using `-initWithUpdaterDelegate:userDriverDelegate:` or `-initWithStartingUpdater:updaterDelegate:userDriverDelegate:`.
+ This class can be instantiated in a nib or created programmatically using `-initWithUpdaterDelegate:userDriverDelegate:` or `-initWithStartingUpdater:updaterDelegate:userDriverDelegate:`.
  
  The controller's updater targets the application's main bundle and uses Sparkle's standard user interface.
- Typically, this class is used by sticking it as a custom NSObject subclass in an Interface Builder nib (probably in MainMenu) but it works well programatically too.
+ Typically, this class is used by sticking it as a custom NSObject subclass in an Interface Builder nib (probably in MainMenu) but it works well programmatically too.
  
  The controller creates an `SPUUpdater` instance using a `SPUStandardUserDriver` and allows hooking up the check for updates action and handling menu item validation.
  It also allows hooking up the updater's and user driver's delegates.
  
  If you need more control over what bundle you want to update, or you want to provide a custom user interface (via `SPUUserDriver`), please use `SPUUpdater` directly instead.
+ 
+ This class must be used on the main thread.
   */
 SU_EXPORT @interface SPUStandardUpdaterController : NSObject
 {
@@ -71,7 +73,7 @@ SU_EXPORT @interface SPUStandardUpdaterController : NSObject
  
  You cannot call this initializer directly. You must instantiate a `SPUStandardUpdaterController` inside of a nib (typically the MainMenu nib) to use it.
  
- To create a `SPUStandardUpdaterController` programatically, use `-initWithUpdaterDelegate:userDriverDelegate:` or `-initWithStartingUpdater:updaterDelegate:userDriverDelegate:` instead.
+ To create a `SPUStandardUpdaterController` programmatically, use `-initWithUpdaterDelegate:userDriverDelegate:` or `-initWithStartingUpdater:updaterDelegate:userDriverDelegate:` instead.
  */
 - (instancetype)init NS_UNAVAILABLE;
 
@@ -79,6 +81,8 @@ SU_EXPORT @interface SPUStandardUpdaterController : NSObject
  Create a new `SPUStandardUpdaterController` programmatically.
  
  The updater is started automatically. See `-startUpdater`  for more information.
+ 
+ Note the `updaterDelegate` and `userDriverDelegate` are weakly referenced, so you are responsible for keeping them alive.
  */
 - (instancetype)initWithUpdaterDelegate:(nullable id<SPUUpdaterDelegate>)updaterDelegate userDriverDelegate:(nullable id<SPUStandardUserDriverDelegate>)userDriverDelegate;
 
@@ -87,6 +91,8 @@ SU_EXPORT @interface SPUStandardUpdaterController : NSObject
  
  You can specify whether or not you want to start the updater immediately.
  If you do not start the updater, you must invoke `-startUpdater` at a later time to start it.
+ 
+ Note the `updaterDelegate` and `userDriverDelegate` are weakly referenced, so you are responsible for keeping them alive.
  */
 - (instancetype)initWithStartingUpdater:(BOOL)startUpdater updaterDelegate:(nullable id<SPUUpdaterDelegate>)updaterDelegate userDriverDelegate:(nullable id<SPUStandardUserDriverDelegate>)userDriverDelegate;
 
index f8d5ef09ad895e2807b310b660797c201098b9a4..b9405aa22f72be64562ac51af550e3488ed68f77 100644 (file)
@@ -33,7 +33,7 @@ SU_EXPORT @interface SPUStandardUserDriver : NSObject <SPUUserDriver>
  Initializes a Sparkle's standard user driver for user update interactions
  
  @param hostBundle The target bundle of the host that is being updated.
- @param delegate The optional delegate to this user driver.
+ @param delegate The optional delegate to this user driver. Note the standard user driver weakly references the delegate, so you are responsible for keeping it alive.
  */
 - (instancetype)initWithHostBundle:(NSBundle *)hostBundle delegate:(nullable id<SPUStandardUserDriverDelegate>)delegate;
 
index e2f8dca17eef13663771347fd421d1ba9aad9b52..6eadbeadc0457fdac9953969df4cb3ee56846edc 100644 (file)
@@ -42,6 +42,8 @@ NS_ASSUME_NONNULL_BEGIN
  - `feedURL`
  
  Please view the documentation on each of these properties for more detail if you are to configure them dynamically.
+ 
+ This class must be used on the main thread.
  */
 SU_EXPORT @interface SPUUpdater : NSObject
 
@@ -52,10 +54,10 @@ SU_EXPORT @interface SPUUpdater : NSObject
  
  Related: See `SPUStandardUpdaterController` which wraps a `SPUUpdater` instance and is suitable for instantiating inside of nib files.
  
- @param hostBundle The bundle that should be targetted for updating.
+ @param hostBundle The bundle that should be targeted for updating.
  @param applicationBundle The application bundle that should be waited for termination and relaunched (unless overridden). Usually this can be the same as hostBundle. This may differ when updating a plug-in or other non-application bundle.
  @param userDriver The user driver that Sparkle uses for user update interaction.
- @param delegate The delegate for `SPUUpdater`.
+ @param delegate The delegate for `SPUUpdater`. Note the updater weakly references the delegate, so you are responsible for keeping it alive.
  */
 - (instancetype)initWithHostBundle:(NSBundle *)hostBundle applicationBundle:(NSBundle *)applicationBundle userDriver:(id <SPUUserDriver>)userDriver delegate:(nullable id<SPUUpdaterDelegate>)delegate;
 
@@ -96,11 +98,13 @@ SU_EXPORT @interface SPUUpdater : NSObject
  
  If an update hasn't started, the user may be shown that a new check for updates is occurring.
  If an update has already been downloaded or begun installing from a previous session, the user may be presented to install that update.
- If the user is already being presented with an update, that update will be shown to the user in active focus.
+ If the user is already being presented with an update or update permission prompt, that notice may be shown to the user in active focus
+ (as long as the user driver is the standard `SPUStandardUserDriver` or if it implements `-[SPUUserDriver showUpdateInFocus]`).
  
  This will find updates that the user has previously opted into skipping.
- 
  See `canCheckForUpdates` property which can determine when this method may be invoked.
+
+ This must be called on the main thread.
  */
 - (void)checkForUpdates;
 
@@ -114,7 +118,7 @@ SU_EXPORT @interface SPUUpdater : NSObject
  to ask the user's permission to check for updates automatically and `automaticallyChecksForUpdates` is `NO`.
  If you want to reset the updater's cycle after an updater setting change, see `resetUpdateCycle` or `resetUpdateCycleAfterShortDelay` instead.
  
- This is meant for programmatically initating a check for updates in the background without the user initiating it.
+ This is meant for programmatically initiating a check for updates in the background without the user initiating it.
  This check will not show UI if no new updates are found.
  
  If a new update is found, the updater's user driver may handle showing it at an appropriate (but not necessarily immediate) time.
@@ -126,6 +130,8 @@ SU_EXPORT @interface SPUUpdater : NSObject
  This will not find updates that the user has opted into skipping.
  
  This method does not do anything if there is a `sessionInProgress`.
+
+ This must be called on the main thread.
  */
 - (void)checkForUpdatesInBackground;
 
@@ -144,13 +150,18 @@ SU_EXPORT @interface SPUUpdater : NSObject
  Updates that have been skipped by the user will not be found.
  
  This method does not do anything if there is a `sessionInProgress`.
+
+ This must be called on the main thread.
  */
 - (void)checkForUpdateInformation;
 
 /**
  A property indicating whether or not updates can be checked by the user.
  
- An update check can be made by the user when an update session isn't in progress, or when an update or its progress is being shown to the user.
+ An update check can be made by the user when an update session isn't in progress.
+ An update check can also be made when an update or its progress is being shown to the user
+ (as long as the user driver is the standard `SPUStandardUserDriver` or if it implements `-[SPUUserDriver showUpdateInFocus]`).
+ 
  A user cannot check for updates when data (such as the feed or an update) is still being downloaded automatically in the background.
  
  This property is suitable to use for menu item validation for seeing if `-checkForUpdates` can be invoked.
@@ -194,7 +205,9 @@ SU_EXPORT @interface SPUUpdater : NSObject
  to your app's command line arguments instead of setting this property.
  
  The update schedule cycle will be reset in a short delay after the property's new value is set.
- This is to allow reverting this property without kicking off a schedule change immediately
+ This is to allow reverting this property without kicking off a schedule change immediately.
+ 
+ This property is KVO compliant. This property must be called on the main thread.
  */
 @property (nonatomic) BOOL automaticallyChecksForUpdates;
 
@@ -209,7 +222,9 @@ SU_EXPORT @interface SPUUpdater : NSObject
  Do not always set it on launch unless you want to ignore the user's preference.
  
  The update schedule cycle will be reset in a short delay after the property's new value is set.
- This is to allow reverting this property without kicking off a schedule change immediately
+ This is to allow reverting this property without kicking off a schedule change immediately.
+ 
+ This property is KVO compliant. This property must be called on the main thread.
  */
 @property (nonatomic) NSTimeInterval updateCheckInterval;
 
@@ -231,6 +246,8 @@ SU_EXPORT @interface SPUUpdater : NSObject
  Hence developers shouldn't maintain an additional user default for this property.
  Only set this property if the user wants to change the default via a user settings option.
  Do not always set it on launch unless you want to ignore the user's preference.
+ 
+ This property is KVO compliant. This property must be called on the main thread.
  */
 @property (nonatomic) BOOL automaticallyDownloadsUpdates;
 
@@ -307,7 +324,7 @@ SU_EXPORT @interface SPUUpdater : NSObject
  
  Note if Sparkle is being used to update another application, the bundle information retrieved is from the main application performing the updating.
  
- This default implementation can be overrided.
+ This default implementation can be overridden.
  */
 @property (nonatomic, copy) NSString *userAgentString;
 
@@ -322,6 +339,8 @@ SU_EXPORT @interface SPUUpdater : NSObject
  A property indicating whether or not the user's system profile information is sent when checking for updates.
 
  Setting this property will persist in the host bundle's user defaults.
+ 
+ This property is KVO compliant. This property must be called on the main thread.
  */
 @property (nonatomic) BOOL sendsSystemProfile;
 
@@ -331,6 +350,8 @@ SU_EXPORT @interface SPUUpdater : NSObject
  For testing purposes, the last update check is stored in the `SULastCheckTime` key in the host bundle's user defaults.
  For example, `defaults delete my-bundle-id SULastCheckTime` can be invoked to clear the last update check time and test
  if update checks are automatically scheduled.
+ 
+ This property must be called on the main thread.
  */
 @property (nonatomic, readonly, copy, nullable) NSDate *lastUpdateCheckDate;
 
@@ -342,6 +363,8 @@ SU_EXPORT @interface SPUUpdater : NSObject
  If the `updateCheckInterval` or `automaticallyChecksForUpdates` properties are changed, this method is automatically invoked after a short delay using `-resetUpdateCycleAfterShortDelay`. In these cases, manually resetting the update cycle is not necessary.
  
  See also `-resetUpdateCycleAfterShortDelay` which gives the user a short delay before triggering a cycle reset.
+ 
+ This must be called on the main thread.
  */
 - (void)resetUpdateCycle;
 
@@ -355,6 +378,8 @@ SU_EXPORT @interface SPUUpdater : NSObject
  no cycle reset will be done.
  
  If the `updateCheckInterval` or `automaticallyChecksForUpdates` properties are changed, this method is automatically invoked. In these cases, manually resetting the update cycle is not necessary.
+ 
+ This must be called on the main thread.
  */
 - (void)resetUpdateCycleAfterShortDelay;
 
index c879e8f8fcdb2182db959504ef41a2fc63572b5e..dd09794543cb9114b78877f0464372ca0522cb4b 100644 (file)
@@ -108,7 +108,7 @@ SU_EXPORT extern NSString *const SUSystemProfilerPreferredLanguageKey;
  This feature was added in Sparkle 2.
  
  @return The set of channel names the updater is allowed to find new updates in. An empty set is the default behavior,
-         which means the updater will only look for updates in the default channel.
+         which means the updater will only look for updates in the default channel. The default channel is always included in the allowed set.
  */
 - (NSSet<NSString *> *)allowedChannelsForUpdater:(SPUUpdater *)updater;
 
@@ -137,7 +137,11 @@ SU_EXPORT extern NSString *const SUSystemProfilerPreferredLanguageKey;
 /**
  Returns whether Sparkle should prompt the user about checking for new updates automatically.
  
- Use this to override the default behavior.
+ Use this to override the default behavior, which is to prompt for permission to check for updates on second app launch
+ (if SUEnableAutomaticChecks is not specified).
+ 
+ This method is not called if SUEnableAutomaticChecks is defined in Info.plist or
+ if the user has responded to a permission prompt before.
  
  @param updater The updater instance.
  @return @c YES if the updater should prompt for permission to check for new updates automatically, otherwise @c NO
@@ -288,7 +292,7 @@ SU_EXPORT extern NSString *const SUSystemProfilerPreferredLanguageKey;
 - (void)updater:(SPUUpdater *)updater willDownloadUpdate:(SUAppcastItem *)item withRequest:(NSMutableURLRequest *)request;
 
 /**
- Called immediately after succesfull download of the specified update.
+ Called immediately after successful download of the specified update.
  
  @param updater The SUUpdater instance.
  @param item The appcast item corresponding to the update that has been downloaded.
@@ -382,7 +386,7 @@ SU_EXPORT extern NSString *const SUSystemProfilerPreferredLanguageKey;
  @param updater The updater instance.
  @return The custom version comparator or @c nil if you don't want to be delegated this task.
  */
-- (nullable id<SUVersionComparison>)versionComparatorForUpdater:(SPUUpdater *)updater;
+- (nullable id<SUVersionComparison>)versionComparatorForUpdater:(SPUUpdater *)updater __deprecated_msg("Custom version comparators are deprecated because they are incompatible with how the system compares different versions of an app.");
 
 /**
  Called when a background update will be scheduled after a delay.
index 8b69e962c53acb025c647fa85da0fc936b805583..12d0223ea93e26061de3b3915f20c7b7e2360f2c 100644 (file)
 NS_ASSUME_NONNULL_BEGIN
 
 /**
- This class can be used for reading certain updater settings.
+ This class can be used for reading and updating updater settings.
  
  It retrieves the settings by first looking into the host's user defaults.
  If the setting is not found in there, then the host's Info.plist file is looked at.
+ 
+ For updating updater settings, changes are made in the host's user defaults.
  */
 SU_EXPORT @interface SPUUpdaterSettings : NSObject
 
@@ -32,13 +34,17 @@ SU_EXPORT @interface SPUUpdaterSettings : NSObject
 
 /**
  * Indicates whether or not automatic update checks are enabled.
+ *
+ * This property is KVO compliant. This property must be called on the main thread.
  */
-@property (readonly, nonatomic) BOOL automaticallyChecksForUpdates;
+@property (nonatomic) BOOL automaticallyChecksForUpdates;
 
 /**
  * The regular update check interval.
+ *
+ * This property is KVO compliant. This property must be called on the main thread.
  */
-@property (readonly, nonatomic) NSTimeInterval updateCheckInterval;
+@property (nonatomic) NSTimeInterval updateCheckInterval;
 
 /**
  * Indicates whether or not automatically downloading updates is allowed to be turned on by the user.
@@ -56,13 +62,17 @@ SU_EXPORT @interface SPUUpdaterSettings : NSObject
  *
  * Note this does not indicate whether or not automatic downloading of updates is allowable.
  * See `-allowsAutomaticUpdates` property for that.
+ *
+ * This property is KVO compliant. This property must be called on the main thread.
  */
-@property (readonly, nonatomic) BOOL automaticallyDownloadsUpdates;
+@property (nonatomic) BOOL automaticallyDownloadsUpdates;
 
 /**
  * Indicates whether or not anonymous system profile information is sent when checking for updates.
+ *
+ * This property is KVO compliant. This property must be called on the main thread.
  */
-@property (readonly, nonatomic) BOOL sendsSystemProfile;
+@property (nonatomic) BOOL sendsSystemProfile;
 
 @end
 
index c43003f9d5d7d74b7c4352efd26a8b49d002d8b2..d0cc98e63398fb538576f4eb4f278de4b235d191 100644 (file)
@@ -46,7 +46,7 @@ SU_EXPORT @protocol SPUUserDriver <NSObject>
 - (void)showUpdatePermissionRequest:(SPUUpdatePermissionRequest *)request reply:(void (^)(SUUpdatePermissionResponse *))reply;
 
 /**
- * Show the user initating an update check
+ * Show the user initiating an update check
  *
  * Respond to the user initiating an update check. Sparkle uses this to show the user a window with an indeterminate progress bar.
  *
@@ -64,11 +64,11 @@ SU_EXPORT @protocol SPUUserDriver <NSObject>
  *
  *  `SPUUpdateStateNotDownloaded` - Update has not been downloaded yet.
  *
- *  `SPUUpdateStateDownloaded` - Update has already been downloaded but not started installing yet.
+ *  `SPUUpdateStateDownloaded` - Update has already been downloaded in the background automatically (via `SUAutomaticallyUpdate`) but not started installing yet.
  *
  *  `SPUUpdateStateInstalling` - Update has been downloaded and already started installing.
  *
- *  The `userIntiated` property on the @c state indicates if the update was initiated by the user or if it was automatically scheduled in the background.
+ *  The `userInitiated` property on the @c state indicates if the update was initiated by the user or if it was automatically scheduled in the background.
  *
  *  Additionally, these properties on the @c appcastItem are of importance:
  *
@@ -78,9 +78,10 @@ SU_EXPORT @protocol SPUUserDriver <NSObject>
  *
  *  @c appcastItem.criticalUpdate indicates if the update is a critical update.
  *
- * A reply of `SPUUserUpdateChoiceInstall` begins or resumes downloading or installing the update.
+ * A reply of `SPUUserUpdateChoiceInstall` begins or resumes downloading, extracting, or installing the update.
  * If the state.stage is `SPUUserUpdateStateInstalling`, this may send a quit event to the application and relaunch it immediately (in this state, this behaves as a fast "install and Relaunch").
- * Do not use this reply if @c appcastItem.informationOnlyUpdate is YES.
+ * If the state.stage is `SPUUpdateStateNotDownloaded` or `SPUUpdateStateDownloaded` the user may be presented an authorization prompt to install the update after `-showDownloadDidStartExtractingUpdate` is called if authorization is required for installation. For example, this may occur if the update on disk is owned by a different user (e.g. root or admin for non-admin users), or if the update is a package install.
+ * Do not use a reply of `SPUUserUpdateChoiceInstall` if @c appcastItem.informationOnlyUpdate is YES.
  *
  * A reply of `SPUUserUpdateChoiceDismiss` dismisses the update for the time being. The user may be reminded of the update at a later point.
  * If the state.stage is `SPUUserUpdateStateDownloaded`, the downloaded update is kept after dismissing until the next time an update is shown to the user.
@@ -183,8 +184,11 @@ SU_EXPORT @protocol SPUUserDriver <NSObject>
  *
  * Sparkle uses this to show an indeterminate progress bar.
  *
- * Note that an update can resume at this point after having been downloaded before,
- * so this may be called without any of the download callbacks being invoked prior.
+ * Before this point, `showDownloadDidReceiveDataOfLength:` or `showUpdateFoundWithAppcastItem:state:reply:` may be called.
+ * An update can potentially resume at this point after having been automatically downloaded in the background (without the user driver)  before.
+ *
+ * After extraction starts, the user may be shown an authorization prompt to install the update if authorization is required for installation.
+ * For example, this may occur if the update on disk is owned by a different user (e.g. root or admin for non-admin users), or if the update is a package install.
  */
 - (void)showDownloadDidStartExtractingUpdate;
 
@@ -252,14 +256,6 @@ SU_EXPORT @protocol SPUUserDriver <NSObject>
  */
 - (void)showUpdateInstalledAndRelaunched:(BOOL)relaunched acknowledgement:(void (^)(void))acknowledgement;
 
-/**
- * Show the user the current presented update or its progress in utmost focus
- *
- * The user wishes to check for updates while the user is being shown update progress.
- * Bring whatever is on screen to frontmost focus (permission request, update information, downloading or extraction status, choice to install update, etc).
- */
-- (void)showUpdateInFocus;
-
 /**
  * Dismiss the current update installation
  *
@@ -269,12 +265,22 @@ SU_EXPORT @protocol SPUUserDriver <NSObject>
  */
 - (void)dismissUpdateInstallation;
 
+@optional
+
+/**
+ * Show the user the current presented update or its progress in utmost focus
+ *
+ * The user wishes to check for updates while the user is being shown update progress.
+ * Bring whatever is on screen to frontmost focus (permission request, update information, downloading or extraction status, choice to install update, etc).
+ * Implementing this method is optional.
+ */
+- (void)showUpdateInFocus;
+
 /*
  * Below are deprecated methods that have been replaced by better alternatives.
  * The deprecated methods will be used if the alternatives have not been implemented yet.
  * In the future support for using these deprecated methods may be removed however.
  */
-@optional
 
 // Clients should move to non-deprecated methods
 // Deprecated methods are only (temporarily) kept around for compatibility reasons
index e875e501c1f4a94f149e723828440a458437041a..6e6b1ab8049ba2aa1e7e2a2269477366f219dc6b 100644 (file)
@@ -235,8 +235,7 @@ SU_EXPORT @interface SUAppcastItem : NSObject<NSSecureCoding>
  
  This may be:
  - @c application - indicates this is a regular application update.
- - @c package - indicates this is a guided package installer update.
- - @c interactive-package - indicates this is an interactive package installer update (deprecated; use "package" instead)
+ - @c package - indicates this is a package installer update.
  
  This is extracted from the @c sparkle:installationType attribute in the @c <enclosure> element.
  
index 2211c172e149e1e3618fd33d4cf5ce14567e71ef..c9e23fefd3e32d1d585187abd24d456f88c39845 100644 (file)
@@ -67,7 +67,7 @@ typedef NS_ENUM(OSStatus, SUError) {
     SUInstallationAuthorizeLaterError = 4008,
     SUNotValidUpdateError = 4009,
     SUAgentInvalidationError = 4010,
-    SUInstallationRootInteractiveError = 4011,
+    //SUInstallationRootInteractiveError = 4011,
     SUInstallationWriteNoPermissionError = 4012,
     
     // API misuse errors.
index 5bc7d68b3017f4811473ec997858e3625308acfe..6d2c771c3075a389dd3738f6faeb78d2fb6c9ed6 100644 (file)
@@ -83,7 +83,7 @@ SU_EXPORT @interface SUUpdater : NSObject
 /*!
  Checks for updates, but does not display any UI unless an update is found.
 
- This is meant for programmatically initating a check for updates. That is,
+ This is meant for programmatically initiating a check for updates. That is,
  it will display no UI unless it actually finds an update, in which case it
  proceeds as usual.
 
@@ -160,7 +160,7 @@ SU_EXPORT @interface SUUpdater : NSObject
 /*!
  The user agent used when checking for and downloading updates.
 
- The default implementation can be overrided.
+ The default implementation can be overridden.
  */
 @property (nonatomic, copy) NSString *userAgentString;
 
index 42edf332cc218a50ea0951180316a369613f9eda..affe0a7c07792ac411240d824a45f544b1d6ca23 100644 (file)
@@ -156,7 +156,7 @@ __deprecated_msg("Deprecated in Sparkle 2. See SPUUpdaterDelegate instead")
 - (void)updater:(SUUpdater *)updater willDownloadUpdate:(SUAppcastItem *)item withRequest:(NSMutableURLRequest *)request;
 
 /*!
- Called immediately after succesfull download of the specified update.
+ Called immediately after successful download of the specified update.
  
  \param updater The SUUpdater instance.
  \param item The appcast item corresponding to the update that has been downloaded.
index af3fe6d05057de908fc235c400deeb27f1871472..01a494aa9b2ba32b00980cca8a0255e202af2426 100644 (file)
@@ -1,6 +1,6 @@
 framework module Sparkle {
   umbrella header "Sparkle.h"
-
   export *
+
   module * { export * }
 }
diff --git a/OSX/Sparkle.framework/Versions/B/Modules/module.private.modulemap b/OSX/Sparkle.framework/Versions/B/Modules/module.private.modulemap
new file mode 100644 (file)
index 0000000..8bc5cfd
--- /dev/null
@@ -0,0 +1,38 @@
+//
+//  Sparkle.private.modulemap
+//  Sparkle
+//
+//  Created on 4/30/25.
+//  Copyright © 2025 Sparkle Project. All rights reserved.
+//
+
+framework module Sparkle_Private {
+    // Nothing exported here
+}
+
+explicit module Sparkle_Private.SPUStandardUserDriver {
+    header "SPUStandardUserDriver+Private.h"
+    export *
+}
+
+explicit module Sparkle_Private.SPUGentleUserDriverReminders {
+    header "SPUGentleUserDriverReminders.h"
+    export *
+}
+
+explicit module Sparkle_Private.SPUUserAgent {
+    header "SPUUserAgent+Private.h"
+    export *
+}
+
+explicit module Sparkle_Private.SUAppcastItem {
+    header "SUAppcastItem+Private.h"
+    header "SPUAppcastItemStateResolver.h"
+    export *
+}
+
+explicit module Sparkle_Private.SUInstallerLauncher {
+    header "SUInstallerLauncher+Private.h"
+    header "SPUInstallationType.h"
+    export *
+}
index 2c6e5561954fb62dae50078720fbd1b07da01032..f06aa3391852bcc431b31f1b006e8f7260a505d6 100644 (file)
@@ -13,7 +13,7 @@
 #define SPUInstallationTypeGuidedPackage @"package" // the preferred installation type for package installations
 #define SPUInstallationTypeInteractivePackage @"interactive-package" // the deprecated installation type; use guided package instead
 
-#define SPUInstallationTypesArray (@[SPUInstallationTypeApplication, SPUInstallationTypeGuidedPackage, SPUInstallationTypeInteractivePackage])
+#define SPUInstallationTypesArray (@[SPUInstallationTypeApplication, SPUInstallationTypeGuidedPackage])
 #define SPUValidInstallationType(x) ((x != nil) && [SPUInstallationTypesArray containsObject:(NSString * _Nonnull)x])
 
 #endif /* SPUInstallationType_h */
index 1005ded9c45efc46e15b3f160314093d4e3f715e..ab49b4178fcaa215930997dabef76d723abcccda 100644 (file)
@@ -10,6 +10,7 @@
 #define SUAppcastItem_Private_h
 
 #import <Foundation/Foundation.h>
+#import <Sparkle/SUAppcastItem.h>
 
 NS_ASSUME_NONNULL_BEGIN
 
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdateAlert.nib b/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdateAlert.nib
deleted file mode 100644 (file)
index ce9f4cb..0000000
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdateAlert.nib and /dev/null differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib b/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib
deleted file mode 100644 (file)
index d1a64e0..0000000
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib and /dev/null differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib b/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib
deleted file mode 100644 (file)
index 01210ef..0000000
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib and /dev/null differ
index 4f44fbc92cc0e87005d11bb1630ecfa87f034b6b..539d044409a6cf3f8ba53abe18165d0cabe8778a 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/Base.lproj/Sparkle.strings differ
index 2300fdbc044d31c9e9f14c7f34754d5e7f57cb07..e3278acf16d816a3a417af3851eac63dab567708 100644 (file)
@@ -3,7 +3,7 @@
 <plist version="1.0">
 <dict>
        <key>BuildMachineOSBuild</key>
-       <string>22G90</string>
+       <string>24G231</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleExecutable</key>
@@ -17,7 +17,7 @@
        <key>CFBundlePackageType</key>
        <string>FMWK</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.5.0</string>
+       <string>2.8.1</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleSupportedPlatforms</key>
                <string>MacOSX</string>
        </array>
        <key>CFBundleVersion</key>
-       <string>2031</string>
+       <string>2050</string>
        <key>DTCompiler</key>
        <string>com.apple.compilers.llvm.clang.1_0</string>
        <key>DTPlatformBuild</key>
-       <string></string>
+       <string>24F74</string>
        <key>DTPlatformName</key>
        <string>macosx</string>
        <key>DTPlatformVersion</key>
-       <string>13.3</string>
+       <string>15.5</string>
        <key>DTSDKBuild</key>
-       <string>22E245</string>
+       <string>24F74</string>
        <key>DTSDKName</key>
-       <string>macosx13.3</string>
+       <string>macosx15.5</string>
        <key>DTXcode</key>
-       <string>1431</string>
+       <string>1640</string>
        <key>DTXcodeBuild</key>
-       <string>14E300c</string>
+       <string>16F6</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.13</string>
 </dict>
index a5bb5ac2eeb29056c48d7d2889acb9e4a65613f9..d8dee77bcf813c81c20eaeeee50ff901e08d1313 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/SUStatus.nib and b/OSX/Sparkle.framework/Versions/B/Resources/SUStatus.nib differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/SUUpdateAlert.nib b/OSX/Sparkle.framework/Versions/B/Resources/SUUpdateAlert.nib
new file mode 100644 (file)
index 0000000..272a9d4
Binary files /dev/null and b/OSX/Sparkle.framework/Versions/B/Resources/SUUpdateAlert.nib differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib b/OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib
new file mode 100644 (file)
index 0000000..55cc583
Binary files /dev/null and b/OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib b/OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib
new file mode 100644 (file)
index 0000000..1016023
Binary files /dev/null and b/OSX/Sparkle.framework/Versions/B/Resources/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 55b0230..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "محدث البرنامج";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "معلومات عن الإصدار:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "تذكيري لاحقًا";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "تخطي هذا الإصدار";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "تثبيت التحديث";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "تنزيل التحديثات وتثبيتها تلقائيًا في المستقبل";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index dcd6dde..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "عدم التحقق";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "هل تريد أن يتم التحقق من وجود تحديثات تلقائيًا؟";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "تضمين تقرير عن النظام دون ذكر معلومات عن المستخدم";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "تنزيل التحديثات وتثبيتها تلقائيًا في المست";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "التحقق تلقائيًا";
index 7ba248ad3f4368f1824a64625728545302da71cb..290f858a9c98c75ae9c9eb3bfb32998de56e8a76 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/ar.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ca.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/ca.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 284cf6d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Actualització del programari";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Notes d'aquesta versió:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Recorda-m'ho més tard";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Omet aquesta versió";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instal·la l'actualització";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Descarrega i instal·la les actualitzacions automàticament en el futur";
index 1a8d279b47d2139d970821576085c18caf0c6312..ad056b7d0320814eb78e729b77c3955557181a50 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/ca.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/ca.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index ff7d56f..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Aktualizace aplikace";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Poznámky k vydání:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Připomenout později";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Přeskočit tuto verzi";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instalovat aktualizaci";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "V budoucnu stahovat a instalovat aktualizace automaticky";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 6c971d1..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Informace z anonymního systémového profilu pomáhají vývojářům lépe plánovat budoucí vývoj aplikace.\nBudete-li mít nějaký dotaz, obraťte se na nás.\n\nToto jsou informace, které budou odeslány:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Nevyhledávat";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Vyhledávat aktualizace automaticky?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Odeslat anonymní systémový profil";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Stahovat a instalovat aktualizace automaticky";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Automaticky vyhledávat";
index 8025bac12afa22be5155648d877b5b002f2de237..4c1e6ef67234a8a0c1b16a01b55022ee4c51cf40 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/cs.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/da.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/da.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 271ae30..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Software Update";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Om denne udgivelse:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Påmind mig senere";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Spring over";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installer";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Hent og installer opdateringer automatisk i fremtiden";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/da.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/da.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 0bc75d7..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Søg ikke";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Søg efter opdateringer automatisk?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Vedhæft anonym systemprofil";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Hent og installer opdateringer automatisk";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Søg automatisk";
index 07b5827d5f7fb598adeff46316c602320c13fe2f..51a2624587bcfa198dcb58e3a2b051c6d7e245ac 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/da.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/da.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/de.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/de.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 93e067a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Softwareupdate";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Versionshinweise:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Später erinnern";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Diese Version überspringen";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installieren";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Updates in Zukunft automatisch laden und installieren";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/de.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/de.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index b34f5a4..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Das anonymisierte Systemprofil unterstützt uns bei der zukünftigen Entwicklung. Bitte kontaktiere uns, wenn du Fragen hierzu hast.\n\nDiese Informationen würden an uns gesendet werden:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Nicht suchen";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Automatisch nach Updates suchen?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Anonymisiertes Systemprofil übertragen";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Updates automatisch laden und installieren";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Automatisch suchen";
index d551282f6aacf172a6f5bdd344fb6710c18bd65c..0b755cb23d612506e6c5333f3b3111ef2e00457c 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/de.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/de.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/el.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/el.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index fc8679d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Ενημέρωση προγράμματος";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Σημειώσεις Έκδοσης:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Υπενθύμιση Αργότερα";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Παράλειψη Έκδοσης";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Εγκατάσταση Ενημέρωσης";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Αυτόματη λήψη και εγκατάσταση ενημερώσεων στο μέλλον";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/el.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/el.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index febfca2..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Οι ανώνυμες πληροφορίες του προφίλ του συστήματός σας, μας βοηθούν στο σχεδιασμό της μελλοντικής ανάπτυξης του προγράμματος. Παρακαλώ επικοινωνήστε μαζί μας άν έχετε ερωτήσεις.\n\nΑυτές είναι οι πληροφορίες που θα σταλούν σε εμάς:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Κανένας έλεγχος";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Αυτόματος έλεγχος για ενημερώσεις;";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Συμπερίληψη του ανώνυμου προφίλ του συστήματός σας";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Αυτόματη λήψη και εγκατάσταση ενημερώσεων";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Αυτόματος Ελεγχος";
index 805e4074cf333e240dc666b6d987f95bb5c8457e..d2e41b3507c3f9c20597a12fe651ca9ec7114641 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/el.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/el.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/en.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/en.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 45a4cfc..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Software Update";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Release Notes:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Remind Me Later";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Skip This Version";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Install Update";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Automatically download and install updates in the future";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/en.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/en.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index fe430d9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "176"; */
-"OhZ-1K-DmA.title" = "Check Automatically";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "177"; */
-"cCJ-V0-aTi.title" = "Don’t Check";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "178"; */
-"gmh-T4-BO0.title" = "Check for updates automatically?";
-
-/* Class = "NSTextFieldCell"; title = "DO NOT LOCALIZE"; ObjectID = "179"; */
-"179.title" = "DO NOT LOCALIZE";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "180"; */
-"gz7-LM-gNf.title" = "Include anonymous system profile";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Automatically download and install updates";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/es.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/es.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index ab59ec2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Actualización de software";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Notas de la versión:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Recordármelo";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "No instalar esta versión";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instalar actualización";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Descargar e instalar actualizaciones automáticamente";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/es.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/es.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 885bf29..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "La información de perfil de sistema anónimo se usa para ayudarnos a planear el trabajo de desarrollo futuro. Por favor, póngase en contacto con nosotros si tiene preguntas sobre esto.\n\nEsta es la información que nos enviaría:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "No comprobar";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "¿Comprobar si hay actualizaciones automáticamente?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Incluir perfil de sistema anónimo";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Descargar e instalar actualizaciones automáticamente";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Comprobar automáticamente";
index a79fc47eedb51827149bc532f6a7778d4fbb2eb6..5744e8d73de22677f6bd87b562302c038c96f162 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/es.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/es.lproj/Sparkle.strings differ
index 342f6584f6266a3a861dab0644fa63edc13e65f0..ae6bead3a138d52de27bb02f24f9194a5275076a 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/fa.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/fa.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index dca6e2e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Ohjelmiston pävitys";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Tietoa päivityksestä:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Muistuta myöhemmin";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Ohita tämä versio";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Asenna päivitys";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Hae ja asenna päivitykset jatkossa automaattisesti";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 04bf32b..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Älä tarkista";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Tarkista päivitykset käynnistyksen yhteydessä?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Sisällytä nimetön järjestelmäprofiili";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Hae ja asenna päivitykset automaattisesti";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Tarkista automaattisesti";
index 974473a4ec2951434135f6b19714483cf9bcf924..5fa6ec0b710887ece133cc1fe7fb1665599c5bcd 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/fi.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index fd8042e..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Mise à jour logiciel";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Notes de version :";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Pas maintenant";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Ignorer cette version";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installer";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Télécharger et installer automatiquement les mises à jour";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index c059f18..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Les informations anonymes de profil système nous aident à planifier les futurs développements. Contactez-nous pour toute question à ce sujet.\n\nCi-dessous figurent les informations qui seront transmises :";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Ne pas vérifier";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Rechercher automatiquement les mises à jour ?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Avec transmission anonyme de mon profil système";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Télécharger et installer automatiquement les mises à jour";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Vérifier automatiquement";
index 8a9ee0479725fff158a55300a096f3d126b1fd0a..9a4a7012b6b82107f1192c8d5fb5a063d3114874 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/fr.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/he.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/he.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index dc8fa21..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "עדכון תכנה";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "פרטי גרסה:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "הזכר לי מאוחר יותר";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "דלג על גרסה זו";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "התקן עדכון";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "הורד והתקן עדכונים אוטומטית גם בעתיד";
index 8a29dbe6aeee6cf2627e1d4e384ae5cf13578106..c3c6874cc3c49097387177d5abe39b65fdad7a59 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/he.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/he.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 60525af..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Aktualiziranje softvera";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Napomene uz izdanje:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Podsjeti me kasnije";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Zanemari ovu verziju";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instaliraj nadogradnju";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Ubuduće preuzmi i instaliraj nadogradnje automatski";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 665e3a1..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonimizirani podaci profila susatava pomažu nam planirati budući razvoj. Kontaktiraj nas, ako imaš pitanja o tome.\n\nŠalju se sljedeći podaci:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Nemoj provjeravati";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Automatski provjeriti nadogradnje?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Uključi anonimizirane podatke o profilu sustava";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Preuzmi i instaliraj nadogradnje automatski";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Provjeri automatski";
index 2dc1a9184161bd8d3711f6d0f562898483e68c11..3f22e9411b8fa0adc3f8cd9fe50259e332297927 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/hr.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 841a542..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Szoftverfrissítés";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Változások az előző verzióhoz képest:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Emlékeztessen később";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Verzió kihagyása";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Telepítés";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "A jövőben automatikusan töltse le és telepítse a frissítéseket";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index d1a121f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Manuális keresés";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Keresse automatikusan a frissítéseket?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Anonim rendszerinformáció küldése";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Automatikus keresés";
index 6b397d42ecbc145bd03d4ff64ef8c362fa54ab6c..5c0504ba76cef5fc613a0cb42b27ec52d0792f63 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/hu.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/is.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/is.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 314a8ca..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Hugbúnaðaruppfærsla";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Útgáfupunktar:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Áminntu mig síðar";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Sleppa þessari útgáfu";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Innsetja";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Sækja og innsetja uppfærslur sjálfkrafa framvegis";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/is.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/is.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 66dc318..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Upplýsingar úr nafnlausum kerfisskýrslum eru notaðar til að hjálpa okkur við framtíðarþróun hugbúnaðarins. Ekki hika við að hafa samband ef spurningar vakna um þetta.\n\nÞetta eru upplýsingarnar sem yrðu sendar:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Ekki kanna";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Athuga sjálfkrafa með uppfærslur?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Innifela nafnlausa kerfisskýrslu";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Sækja og innsetja uppfærslur sjálfkrafa";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Kanna sjálfkrafa";
index 1b1858138eae7672e365fd82b3252de327c76081..cc749443d4faab9c0ae97ec0795c76eb82be775b 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/is.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/is.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/it.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/it.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index cc0d7c3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Aggiornamento Software";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Note di rilascio:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Ricordamelo più tardi";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Ignora questa versione";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installa";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "In futuro scarica e installa automaticamente gli aggiornamenti";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/it.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/it.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index a051914..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Le informazioni del profilo di sistema anomino sono utilizzate per aiutarci in futuri lavori di sviluppo. Contattaci se hai dei quesiti sull’argomento.\n\nQueste sono le informazioni che verrebbero inviate:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Non controllare";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Controllo automaticamente gli aggiornamenti?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Include profilo di sistema anonimo";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Scarica e installa automaticamente gli aggiornamenti";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Controlla Automaticamente";
index 27f0834001b8df46c33ac8c76f7166bd4f35f36c..57f5be67083f9987ad69a1a2472de329c76da33a 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/it.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/it.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 6ac6410..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "ソフトウェア・アップデート";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "リリースノート:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "後で通知";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "このバージョンはスキップ";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "アップデートをインストール";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "今後はアップデートのダウンロードとインストールを自動で行う";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index cff48a2..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "匿名のシステムプロファイル情報は、今後の開発の参考にさせていただきます。この件に関してご質問があればご連絡下さい。\n\n以下の情報が送信されます:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "確認しない";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "アップデートを自動で確認しますか?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "匿名のシステム情報を含める";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "自動で確認";
index 903adfc73f33554da7c1023b69069863685f0aba..954cb25001c73316adbc60a3a39b6c64d10e0a08 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/ja.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index ee92bf2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Software Update";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "배포 정보:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "나중에";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "이 버전 건너뛰기";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "업데이트 설치";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "나중에 업데이트 자동으로 다운로드 및 설치";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 472ef43..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "익명으로 보내지는 시스템 정보로 차후 프로그램 개발에 도움이 될 수 있습니다. 질문이 있으시면 연락 주십시오.\n\n아래 정보가 전송될 것입니다.";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "취소";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "자동으로 업데이트 확인할까요?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "익명 시스템 정보 포함";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "자동으로 확인";
index fe2190e43398c3937fda4ebb5a8a386752ff3b43..d4f8d2d53ac0da6e4272af6853ccc44d047bb184 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/ko.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index bd58fbb..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Programoppdatering";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Om oppdateringen:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Utsett";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Hopp over";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installer";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Last ned og installer automatisk i fremtiden";
-
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index c921f62..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Den anonyme systemprofilen hjelper oss med å planlegge fremtidig utviklingsarbeid. Ta gjerne kontakt med oss hvis du har spørsmål om dette.
\nFølgende innhold vil bli sendt:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Ikke søk";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Søk etter oppdateringer automatisk?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Inkluder anonym systemprofil";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Last ned og installer automatisk";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Søk automatisk";
-
index 3d8e2aa2ad9df2672d34c36843a891bc8904838c..7a518c9def6db13e4fa49523fb435140e2e8697b 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/nb.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 3edac36..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Software-update";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Versiegegevens:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Herinner mij later";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Sla deze versie over";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installeer update";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Download en installeer updates voortaan automatisch";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 8995361..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Aan de hand van anonieme informatie over het systeemprofiel kunnen wij toekomstige ontwikkelingswerkzaamheden beter plannen. Neem contact met ons op als je hierover vragen hebt.\n\nDit is de informatie die wordt verzonden:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Zoek niet";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Automatisch zoeken naar updates?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Voeg anoniem systeemprofiel bij";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Download en installeer updates automatisch";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Zoek automatisch";
index 3c4c92ba187c5c114f892834e2157c432c0131cc..cd9f48d8e171fad8802125c3027b8fd7f786e20d 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/nl.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/nn.lproj/Sparkle.strings b/OSX/Sparkle.framework/Versions/B/Resources/nn.lproj/Sparkle.strings
new file mode 100644 (file)
index 0000000..ab54f02
Binary files /dev/null and b/OSX/Sparkle.framework/Versions/B/Resources/nn.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 4092fd0..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Uaktualnienie oprogramowania";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Szczegóły wydania:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Przypomnij później";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Pomiń tę wersję";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Zainstaluj teraz";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Automatycznie pobierz i zainstaluj przyszłe uaktualnienia";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index ca85ca8..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Nie sprawdzaj";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Sprawdzać automatycznie uaktualnienia?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Załącz anonimowe informacje o systemie";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Automatycznie pobierz i zainstaluj uaktualnienia";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Sprawdzaj automatycznie";
index 33226f240c86da5a63bf6111b0e1676f35dfeef1..b2a184cf3ef695a0123cfa0865063d35f260f34e 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/pl.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 65aab08..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Atualização de Software";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Notas do Lançamento:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Mais Tarde";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Ignorar Esta Versão";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instalar Atualização";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Baixar e instalar atualizações futuras automaticamente";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index a435270..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "As informações anônimas do sistema são usadas para nos ajudar a planejar o desenvolvimento futuro do aplicativo. Contate-nos caso tenha dúvidas sobre este procedimento.\n\nAs seguintes informações seriam enviadas:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Não Buscar";
-
-/* Class = "NSTextFieldCell"; title = "DO NOT LOCALIZE"; ObjectID = "cfa-j0-Ya4"; */
-"cfa-j0-Ya4.title" = "";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Buscar atualizações automaticamente?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Incluir perfil anônimo do sistema";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Baixar e instalar atualizações automaticamente";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Buscar Automaticamente";
index 6c393ab9474405886865b8e24feb9aa01b434316..d9070044a51316e5e2b8ae7735e0d20bd2980a5d 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/pt-BR.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index ae805c4..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Actualização de Software";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Notas de lançamento:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Lembrar mais tarde";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Saltar esta versão";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instalar actualização";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "No futuro, transferir e instalar actualizações automaticamente";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index cb41028..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "A informação anónima do perfil de sistema é usada para no futuro nos ajudar a planear o trabalho de desenvolvimento. Por favor contacte-nos se tiver alguma questão acerca deste assunto.\n\nEsta é a informação que seria enviada:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Não procurar";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Procurar actualizações automaticamente?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Incluir perfil de sistema anónimo";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Transferir e instalar actualizações automaticamente";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Procurar automaticamente";
index fddae71bb57ac6e07a140af7c2d19a74c5da5380..307b323fb57acb1946ac0c1d029401a555267e90 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/pt-PT.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 37e9bc7..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Actualizarea aplicației";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Note de ediție:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Amintește-mi mai târziu";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Sari peste…";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Instalează actualizarea";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "În viitor descarcă și instalează în automat actualizările";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index c9d3813..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Nu verifica";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Verifică pentru actualizări în mod automat?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Include profil anomin de sistem";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Descarcă și instalează în automat actualizările";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Verifică în mod automat";
index f08fba0eb336e1d7d3e689743f06553863f428a6..478e68329af0482d2b8e9052f03f2932a5b1aa2d 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/ro.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 137fd57..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Обновление программного обеспечения";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Заметки о выпуске:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Напоминать позже";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Пропустить эту версию";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Установить обновление";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Автоматически загружать и устанавливать обновления в будущем";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 99f1596..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Использование анонимного профиля системы помогает нам в планировании будущей работы по разработке. Если у вас есть какие-либо вопросы по этой теме, обращайтесь к нам.\n\nЭто информация, предназначенная для отправления:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Не проверять";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Выполнять автоматическую проверку наличия обновлений?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Включить анонимный профиль системы";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Автоматически загружать и устанавливать обновления";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Проверять автоматически";
index 1ce90e80bd734980106b6f62a68782643910544a..693f938e422c4552ee9fdab82d411610c9a49def 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/ru.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 266f0fb..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Aktualizácia softvéru";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Poznámky k vydaniu:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Pripomenúť neskôr";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Vynechať túto verziu";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Nainštalovať";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "V budúcnosti aktualizácie preberať a inštalovať automaticky";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 25c836d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonymný profil systému nám umožní zlepšiť plánovanie budúceho vývoja aplikácie. Ak máte ohľadom tohto akékoľvek otázky, neváhajte a kontaktujte nás.\n\nOdosielané budú nasledujúce informácie:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Nekontrolovať";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Kontrolovať aktualizácie automaticky?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Zahrnúť anonymný profil systému";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Kontrolovať automaticky";
index 9e3444e0d8b13ef8ab6e5fd950011afe386b2cf5..fea743aaed28b86f7b94cf5c75d7d9549a300c37 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/sk.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index d106021..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Posodabljanje programske opreme";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Opombe ob izdaji:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Spomni me kasneje";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Preskoči to verzijo";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Namesti posodobitev";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "V prihodnje samodejno nameščaj posodobitve";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 03b141c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonimni profil sistema se uporablja za načrtovanje nadaljnega razvoja programa. V primeru vprašanj nas lahko kontaktirate.\n\nPošljejo se sledeče informacije:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Ne preverjaj";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Naj občasno preverjam, če so na voljo posodobitve?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Vključi anonimni profil sistema";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Samodejno namestite posodobitve";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Samodejno preverjaj";
index 2e64a63baf63e71ad471e92d4d2b473b747b76c5..8efec2482a7921d6ef8d324dbfb56d311366c7ac 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/sl.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 382b634..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Programuppdatering";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Versionsinformation:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Påminn mig senare";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Hoppa över denna version";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Installera uppdatering";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Hämta och installera nya uppdateringar automatiskt i framtiden.";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index b26b32e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Textcell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Textcell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Anonym systemprofilinformation används för att hjälpa oss att planera framtida utvecklingsarbete. Vänligen kontakta oss ifall du har några frågot om detta.\n\nDetta är informationen som skulle sändas:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Kontrollera inte";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Leta efter uppdateringar automatiskt?\n";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Inkludera anonym systemprofil";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Hämta och installera nya uppdateringar automatiskt.";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Kontrollera automatiskt";
index df36ec1c657801897900d105e096e948cf69abcb..ae267f776b0bd9c4481bc37182e22e4ab61081d3 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/sv.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/th.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/th.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index c57e3d3..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "อัพเดทซอฟต์แวร์";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Release Notes:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "เตือนในภายหลัง";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "ข้ามเวอร์ชั่นนี้";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "ติดตั้งอัพเดท";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "ดาวน์โหลดและติดตั้งอัพเดทโดยอัตโนมัติในอนาคต";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/th.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/th.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index b755d03..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "ข้อมูลระบบแบบนิรนามช่วยในการวางแผนพัฒนาแอปพลิเคชันของเราในอนาคต กรุณาติดต่อเราถ้าคุณมีข้อสงสัยในเรื่องนี้\n\nนี่คือข้อมูลที่จะถูกส่งไป:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "ไม่ต้องตรวจสอบ";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "ตรวจสอบอัพเดทอัตโนมัติ?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "ส่งข้อมูลระบบแบบนิรนาม";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "ดาวน์โหลดและติดตั้งอัพเดทโดยอัตโนมัติ";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "ตรวจสอบโดยอัตโนมัติ";
index 6b8c878683fd90609772e5373469ba98d58d0ce3..e859a28859f26745b1abdb1d17a3a4803f9a7c12 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/th.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/th.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 7f67ed6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Software-Aktualisierung";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Sürüm Hakkında:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Sonra Hatırlat";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Bu Sürümü Geç";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Kur";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Bundan sonra güncellemeleri kendiliğinden indir ve kur";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 4901fad..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Gönderdiğiniz anonim sistem bilgileri bu yazılımın geliştirilmesi için kullanılacaktır. Konu ile ilgili ayrıntılı bilgi için lütfen bizimle bağlantıya geçiniz. Göndereceğiniz Bilgiler:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Arama";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Güncellemeler otomatik olarak aransın mı?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Sistem bilgilerini kimlik gizlenmiş olarak gönder";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Güncellemeleri kendiliğinden indir ve kur";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Otomatik Olarak Ara";
index 5496cbb92df9cf7709f94adfbe8d4b2a6c433a22..6beeb10446164ca41f5216cc22d7fb63e625c5b3 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/tr.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index ece6670..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "Оновлення програмного забезпечення";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "Примітки про нову версію:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "Нагадати пізніше";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "Пропустити цю версію";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "Встановити оновлення";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "Автоматично завантажувати та встановлювати оновлення у майбутньому";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 27451a3..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "Використання анонімного профілю системи допомагає нам у планування майбутньої розробки. Якщо у вас виникли питання щодо цього, звертайтесь до нас.\n\nІнформація, що буде надіслано:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "Не перервіряти";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "Виконувати автоматичну перевірку оновлень?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "Автоматично надсилати профіль системи";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "Автоматично завантажувати та встановлювати оновлення";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "Перевіряти автоматично";
index e3f079190233e190b772d44dd39b8b88f5078a07..e6687f8f77325933b8669162cd0742fb7cb06423 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/uk.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index 5772fc6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "软件更新";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "更新信息:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "稍后提示我";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "跳过这个版本";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "安装更新";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "以后自动下载并安装更新";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index bdf7d69..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "无记名系统概况信息被用于帮助我们安排将来的开发工作。如果对此存在疑问请联系我们。\n\n这是将要被发送的信息::";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "不核查";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "自动核查更新?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "包括无记名系统概况";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "自动下载并安装更新";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "自动核查";
index 3acf2a0c653431e49f2d201048cfb78e16f4e1a5..8f735c1f6390c4be6bd5f0ae2987dedb805d99ff 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/zh_CN.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index d7cb6fe..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "軟體更新";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "更新事項:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "稍後提醒我";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "跳過此版本";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "安裝更新";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "以後自動下載並安裝更新";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index b40c572..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "匿名系統概況資訊可用來協助我等計畫未來開發工作。若對此有任何疑問,請聯繫我等。\n\n以下係會傳送嘅資訊:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "毋檢查";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "自動檢查更新?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "包含匿名系統概況";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "自動下載並安裝更新";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "自動檢查";
index 4d758a3c877f66e7bb28e2ae29f4ad766c2b11da..c15689506dfd1f4a9a394fc5079461615bbf93f0 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/zh_HK.lproj/Sparkle.strings differ
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/SUUpdateAlert.strings b/OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/SUUpdateAlert.strings
deleted file mode 100644 (file)
index d53374d..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* Class = "NSWindow"; title = "Software Update"; ObjectID = "5"; */
-"5.title" = "軟體更新";
-
-/* Class = "NSTextFieldCell"; title = "Release Notes:"; ObjectID = "170"; */
-"170.title" = "更新事項:";
-
-/* Class = "NSButtonCell"; title = "Remind Me Later"; ObjectID = "171"; */
-"171.title" = "暫緩提醒";
-
-/* Class = "NSButtonCell"; title = "Skip This Version"; ObjectID = "172"; */
-"172.title" = "跳過此版本";
-
-/* Class = "NSButtonCell"; title = "Install Update"; ObjectID = "173"; */
-"173.title" = "安裝更新項目";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates in the future"; ObjectID = "175"; */
-"175.title" = "自動下載並安裝未來的更新項目";
diff --git a/OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.strings b/OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/SUUpdatePermissionPrompt.strings
deleted file mode 100644 (file)
index 635b453..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "43"; */
-"43.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "45"; */
-"45.title" = "Text Cell";
-
-/* Class = "NSTextFieldCell"; title = "Anonymous system profile information is used to help us plan future development work. Please contact us if you have any questions about this.\n\nThis is the information that would be sent:"; ObjectID = "183"; */
-"183.title" = "匿名系統描述資訊可用來協助我們計畫未來的開發工作。若您有任何相關問題,請與我們聯繫。\n\n以下是會傳送的資訊:";
-
-/* Class = "NSButtonCell"; title = "Don’t Check"; ObjectID = "cCJ-V0-aTi"; */
-"cCJ-V0-aTi.title" = "不要檢查";
-
-/* Class = "NSTextFieldCell"; title = "Check for updates automatically?"; ObjectID = "gmh-T4-BO0"; */
-"gmh-T4-BO0.title" = "自動檢查更新項目?";
-
-/* Class = "NSButtonCell"; title = "Include anonymous system profile"; ObjectID = "gz7-LM-gNf"; */
-"gz7-LM-gNf.title" = "包含匿名的系統描述資料";
-
-/* Class = "NSButtonCell"; title = "Automatically download and install updates"; ObjectID = "AUc-33-qGN"; */
-"AUc-33-qGN.title" = "自動下載並安裝更新項目";
-
-/* Class = "NSButtonCell"; title = "Check Automatically"; ObjectID = "OhZ-1K-DmA"; */
-"OhZ-1K-DmA.title" = "自動檢查";
index 6018e8bca0ce73f8692deddae66c397998339dba..1d77bb66ea0f4f5ddfa907925fbb777240e4d960 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/Sparkle.strings and b/OSX/Sparkle.framework/Versions/B/Resources/zh_TW.lproj/Sparkle.strings differ
index 2039bf7e7d7fb48b8b23e2237048eb9fa0349a85..3b1363c4b1a4fe929dff16b299da6cf11ecc2cc8 100755 (executable)
Binary files a/OSX/Sparkle.framework/Versions/B/Sparkle and b/OSX/Sparkle.framework/Versions/B/Sparkle differ
index 8f7af20d4049d6fc1b29a2ea133860bfd43bd6c5..c50fe3bbfe00639d6dbe0d18ed5921c141e67497 100644 (file)
@@ -3,7 +3,7 @@
 <plist version="1.0">
 <dict>
        <key>BuildMachineOSBuild</key>
-       <string>22G90</string>
+       <string>24G231</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleExecutable</key>
@@ -55,7 +55,7 @@
        <key>CFBundlePackageType</key>
        <string>APPL</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.5.0</string>
+       <string>2.8.1</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleSupportedPlatforms</key>
                <string>MacOSX</string>
        </array>
        <key>CFBundleVersion</key>
-       <string>2031</string>
+       <string>2050</string>
        <key>DTCompiler</key>
        <string>com.apple.compilers.llvm.clang.1_0</string>
        <key>DTPlatformBuild</key>
-       <string></string>
+       <string>24F74</string>
        <key>DTPlatformName</key>
        <string>macosx</string>
        <key>DTPlatformVersion</key>
-       <string>13.3</string>
+       <string>15.5</string>
        <key>DTSDKBuild</key>
-       <string>22E245</string>
+       <string>24F74</string>
        <key>DTSDKName</key>
-       <string>macosx13.3</string>
+       <string>macosx15.5</string>
        <key>DTXcode</key>
-       <string>1431</string>
+       <string>1640</string>
        <key>DTXcodeBuild</key>
-       <string>14E300c</string>
+       <string>16F6</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.utilities</string>
        <key>LSMinimumSystemVersion</key>
index e43bdc82fe43e5283febc88e16a58efb5a9a4091..92161b97014cfaf9d93c1b85f377d2e70098921e 100755 (executable)
Binary files a/OSX/Sparkle.framework/Versions/B/Updater.app/Contents/MacOS/Updater and b/OSX/Sparkle.framework/Versions/B/Updater.app/Contents/MacOS/Updater differ
index a5bb5ac2eeb29056c48d7d2889acb9e4a65613f9..d8dee77bcf813c81c20eaeeee50ff901e08d1313 100644 (file)
Binary files a/OSX/Sparkle.framework/Versions/B/Updater.app/Contents/Resources/SUStatus.nib and b/OSX/Sparkle.framework/Versions/B/Updater.app/Contents/Resources/SUStatus.nib differ
index a7bc0d1acc30cb781103c2052e73957b9eed1c89..3430875b770319c5ea8a3a09ec5c06bee7019e04 100644 (file)
@@ -6,7 +6,7 @@
        <dict>
                <key>Resources/SUStatus.nib</key>
                <data>
-               C+A5AK9r0wh2EeQDmcX3eh5QGr8=
+               Iu5Uac2/Jq/TkBKt72CBLw3j1D8=
                </data>
        </dict>
        <key>files2</key>
@@ -15,7 +15,7 @@
                <dict>
                        <key>hash2</key>
                        <data>
-                       V7nQA4E39SW5aUzqhBVsXTFN0jH5W2mdJr74xs58fWU=
+                       Qd5rCHQjMKfxN9BfliN2b7KXpOro8kFotf6JbmgnSLI=
                        </data>
                </dict>
        </dict>
index 0ae6a4024fd03cb45dbdb06548f2265311698230..0fc767daad770b2d5a2f775a20eba80089d87eed 100644 (file)
@@ -3,13 +3,13 @@
 <plist version="1.0">
 <dict>
        <key>BuildMachineOSBuild</key>
-       <string>22G90</string>
+       <string>24G231</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleExecutable</key>
        <string>Downloader</string>
        <key>CFBundleIdentifier</key>
-       <string>org.sparkle-project.Downloader</string>
+       <string>org.sparkle-project.DownloaderService</string>
        <key>CFBundleInfoDictionaryVersion</key>
        <string>6.0</string>
        <key>CFBundleName</key>
@@ -17,7 +17,7 @@
        <key>CFBundlePackageType</key>
        <string>XPC!</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.5.0</string>
+       <string>2.8.1</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleSupportedPlatforms</key>
                <string>MacOSX</string>
        </array>
        <key>CFBundleVersion</key>
-       <string>2031</string>
+       <string>2050</string>
        <key>DTCompiler</key>
        <string>com.apple.compilers.llvm.clang.1_0</string>
        <key>DTPlatformBuild</key>
-       <string></string>
+       <string>24F74</string>
        <key>DTPlatformName</key>
        <string>macosx</string>
        <key>DTPlatformVersion</key>
-       <string>13.3</string>
+       <string>15.5</string>
        <key>DTSDKBuild</key>
-       <string>22E245</string>
+       <string>24F74</string>
        <key>DTSDKName</key>
-       <string>macosx13.3</string>
+       <string>macosx15.5</string>
        <key>DTXcode</key>
-       <string>1431</string>
+       <string>1640</string>
        <key>DTXcodeBuild</key>
-       <string>14E300c</string>
+       <string>16F6</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.13</string>
        <key>NSAppTransportSecurity</key>
index 8cf246de76c1df6801f5feeb9685c536e368d84f..adc7633cc48ed5fc5361af46a39037955d619959 100755 (executable)
Binary files a/OSX/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc/Contents/MacOS/Downloader and b/OSX/Sparkle.framework/Versions/B/XPCServices/Downloader.xpc/Contents/MacOS/Downloader differ
index 3e4288ceac8a6dc7db30831ca38b5969e21278a6..f1286c9b6a80a388dfe982b5f14613b3bed5130c 100644 (file)
@@ -3,7 +3,7 @@
 <plist version="1.0">
 <dict>
        <key>BuildMachineOSBuild</key>
-       <string>22G90</string>
+       <string>24G231</string>
        <key>CFBundleDevelopmentRegion</key>
        <string>en</string>
        <key>CFBundleExecutable</key>
@@ -17,7 +17,7 @@
        <key>CFBundlePackageType</key>
        <string>XPC!</string>
        <key>CFBundleShortVersionString</key>
-       <string>2.5.0</string>
+       <string>2.8.1</string>
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleSupportedPlatforms</key>
                <string>MacOSX</string>
        </array>
        <key>CFBundleVersion</key>
-       <string>2031</string>
+       <string>2050</string>
        <key>DTCompiler</key>
        <string>com.apple.compilers.llvm.clang.1_0</string>
        <key>DTPlatformBuild</key>
-       <string></string>
+       <string>24F74</string>
        <key>DTPlatformName</key>
        <string>macosx</string>
        <key>DTPlatformVersion</key>
-       <string>13.3</string>
+       <string>15.5</string>
        <key>DTSDKBuild</key>
-       <string>22E245</string>
+       <string>24F74</string>
        <key>DTSDKName</key>
-       <string>macosx13.3</string>
+       <string>macosx15.5</string>
        <key>DTXcode</key>
-       <string>1431</string>
+       <string>1640</string>
        <key>DTXcodeBuild</key>
-       <string>14E300c</string>
+       <string>16F6</string>
        <key>LSMinimumSystemVersion</key>
        <string>10.13</string>
        <key>NSHumanReadableCopyright</key>
index 65e0fe2349d2dccdd5039b85c3349d100d270b89..3cd62a0aeed113cee621ddcc015e8f706ba0f2b0 100755 (executable)
Binary files a/OSX/Sparkle.framework/Versions/B/XPCServices/Installer.xpc/Contents/MacOS/Installer and b/OSX/Sparkle.framework/Versions/B/XPCServices/Installer.xpc/Contents/MacOS/Installer differ
index 76f57cde36ea9924473d4e3e368bb5d4c61ad0cc..979ded2d4619504b23c9da6fb1970d484f6a2a01 100644 (file)
@@ -4,66 +4,39 @@
 <dict>
        <key>files</key>
        <dict>
-               <key>Resources/Base.lproj/SUUpdateAlert.nib</key>
+               <key>Resources/Base.lproj/Sparkle.strings</key>
                <data>
-               CcSGUnHshFRNbXNCax4Fk/Ar3sk=
+               jWvSNptszitFRmKtYk08DuO6z10=
                </data>
-               <key>Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib</key>
+               <key>Resources/Info.plist</key>
                <data>
-               kQCQnExWsd4UN/XCwMWsdBo8rmU=
+               AIeUJJ8PypJR3L3BiWCrAklq7Vs=
                </data>
-               <key>Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib</key>
+               <key>Resources/ReleaseNotesColorStyle.css</key>
                <data>
-               ShA7h1IUUX/SyuDWg6JseOHtNHo=
+               NjIvb1z7eJuLCKf9HS15O5heg50=
                </data>
-               <key>Resources/Base.lproj/Sparkle.strings</key>
+               <key>Resources/SUStatus.nib</key>
                <data>
-               yENpjnRY3Io5iY3w/nXBi2P2CFc=
+               Iu5Uac2/Jq/TkBKt72CBLw3j1D8=
                </data>
-               <key>Resources/Info.plist</key>
+               <key>Resources/SUUpdateAlert.nib</key>
                <data>
-               inXDNNZsCBUSiN/ib9t/0pgmdBo=
+               aBY/8sWAcbKxrkcg0p2M+gv0eDg=
                </data>
-               <key>Resources/ReleaseNotesColorStyle.css</key>
+               <key>Resources/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib</key>
                <data>
-               NjIvb1z7eJuLCKf9HS15O5heg50=
+               A02xo7KWD5EJV3vQIZIgEN2Gm94=
                </data>
-               <key>Resources/SUStatus.nib</key>
+               <key>Resources/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib</key>
                <data>
-               C+A5AK9r0wh2EeQDmcX3eh5QGr8=
+               zWe0e02UlZdX+N7AUu4TSBx7tIo=
                </data>
-               <key>Resources/ar.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       qTOMJ1P/HhCcJQi4qSJV9l/b7q0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ar.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       zZ/0sjHdlPnBGe10CetKo1kF1xQ=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
                <key>Resources/ar.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash</key>
                        <data>
-                       5Ukin0TnIF0ot6Daz8OSgIoDZJ0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ca.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       l9CaCmAXFcs+Z+8rRt7PX9onkf8=
+                       T7fNcqHlJUnjYfupB4g4wM7Eagk=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       DL6k3g2A8CPQPkykQht4w+H/xYc=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/cs.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       G9Wgf14zMhU2alRSZvqclMmlTCA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/cs.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       rhsuTqRoVAfmLW+GJ1vvxJPRJ0U=
+                       cEAmpjo27zR+JhuaUXN0UQr3QK4=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       KTLNyu97zLvTNgaUfYWqc8nB9C4=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/da.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       NEt5JVKz+OoMSynKxJC18KXMGaA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/da.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       s6oFpgOPENk+LCyXJoLfVqZauVQ=
+                       SMVp5lfHi/lfNXmw6lJYSrSwU/M=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       7MO7J38OUDrmZMLJiNSeNRATia8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/de.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       YLQxXHDo3e3Udzaj8LHDIjotWzE=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/de.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       W8+shbfn38JAPBpgHTMWuU0oHfQ=
+                       W+QsOXYRxKh4cMvK6JkwZvN+IVI=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       FcFO4FvZjeiHQb9cbZI1wh1jHT4=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/el.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       BS+NpAFPK7X/XzX+n99gJLhlNKU=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/el.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       TNa05IunzylN4fz2uHvkj5EnyRk=
+                       vSRRGTSIFiObd3pshiP5RWeEHiw=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       6VadVc0qrgmUnWfL3FgiI6TzchM=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/en.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       FSez7jCd0gDTFFGHiWL1QXY8OUU=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/en.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       7+SiSQLU1hqbN74YfiBS1cQFVqU=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/es.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Q36SuanjGk70efU6liei3uz+Uds=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/es.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       kNfRs9Pgn30BdjtuNzhRvKXcqu0=
+                       /Fqwo/qEklmldCP6iVh/6v/hRtA=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       08cvLbzKYXVy2xMw/nxid5JOK7o=
+                       MrnoX4qJOfgIVq3M6x24fUAx9lI=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       IySTqO8MqmOO/IHR5WBZdf0jYaA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/fi.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       My5YiAuNV+4oR1vPL1np+nMMMOI=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/fi.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       NcjaY8nD4cpjcpK4M878R5JDK1s=
+                       voU8aUJaurOIaAdtV33OM6YmtEg=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       KRoZrUbgs7+EwIxs18H121Szw+0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/fr.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       ffz6ccHMgxcBdH6by1YAYX1jpOQ=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/fr.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       p4tAU3Ek6hEWqW9e8+C1L8WMQIM=
+                       2Emh5JDGV5uqAvja/ExFDMHAIuo=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       BS6wdN+n1R2u/skiaNGAfrXwcKA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/he.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       nZXhvxaoacIflCBRrHxQ4NDkeKg=
+                       rYSw5ov8cR5YOqzXnWRZZAXrsHg=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       +bhO5LfEJtbZlq+wfPs/WUEO2ic=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/hr.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       b/ru54Y0QwvH9Kz9sfRPEoP5z5k=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/hr.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       rdv7bU5k1tUG/tyNsQ1i/Rniypk=
+                       eNe6/Ewhtf0h3uHopz6L6dK8/yA=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       70rdfUc3cUNcMed6Hq4zQBWoGrk=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/hu.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       VD/QPXFfEHRW7ksDLYiiO1xl1LQ=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/hu.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       PMarJZpNhDysjzZuBuyKv8KBTXQ=
+                       PijrXJOIU6kJbybmO9H6692KXDE=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       5CCN2xKgiom6y3+mcWd48RVdX48=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/is.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       bQiB5tUCaD24QKubEYeBTXsAF1g=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/is.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       vGNXtUX/4qNYIzE89IO7e4GxS60=
+                       2Ksks8It17APw4bY49SNRY+2Thw=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash</key>
                        <data>
-                       tplLwN1kGq9MoWLnyPQhozI6c54=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/it.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Yev0Ro2PsLfgCLoY7JNED63PnqM=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/it.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       IGMzQ4TCQgpEQaOcESzlhe8ny9I=
+                       2/3AFNWHP6LviaOgYOiM8rEqa4o=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
                <key>Resources/it.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash</key>
-                       <data>
-                       HvJh7rlxinaVRX3rGu84YDTq5j8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ja.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       vl6gP7QCeuFYsNYdgVYYUcm0S/4=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ja.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       vmA8scrUnfvMygrsa76QF557nDU=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ja.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       qUoPouJsSuujtYJeA1Jn1M6d+CA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ko.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       xZjyKASZdwg70f4m29uGtJjFUgQ=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ko.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       d+ifBccX26E56rM7eOY72BKC5aY=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ko.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       vidckNwrgXZkzwbptfj9ycGywxE=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/nb.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       fck+vL9Sgcx19X7HthrjizRGhu8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/nb.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       eiq9zVX/y56Q0ymxVNFnYahFbxs=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/nb.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Xm8t/g53ktlmyq8w1aI29nEiGO8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/nl.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       5ZpTsHPgV4inhhYiISGjC03BMG4=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/nl.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       LgvDZbmPK7Ox9+gNe7zXN3egxlM=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/nl.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       HUFefTfqhwJx6nNNmACg3qxtHKo=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pl.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       HX2RXVrN+fpwO4I60/UDyNuGj5Y=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pl.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       abNyxpda7OkXoR5Ok35XgMr9eBc=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pl.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       MXjhjMKrcFaSZhXYssMrBTXPu80=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pt-BR.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       YFXY6v+45ptf8TuBq2MsKKdhfQ8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pt-BR.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       2iCpI0fy7Tm1zxR19dV1iCYW3bo=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pt-BR.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       mVP9x5C0h0Q+njDLXhZXmDsOjWM=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pt-PT.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       pWRHcAJRvjUt7BOLr/gd+IupcGA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pt-PT.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Om//DOu8+gBjHYrCHVmxKxBDvPs=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/pt-PT.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       6IY8J7Jbjd3eG/BMld5iJSwZZvM=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ro.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       a/RNqEdkehva+SwGWz11MktFGWA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ro.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       JDMBsS6fp2v5X+C0d1EJAREHIkA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ro.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       rihcAKPJ1j7EoW5B+lq7Dpci/Zo=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ru.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Lmn0e5MDPfan55gnani1dQbR10Q=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ru.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       z+XqvyZR2X6cb0PioKpfYDCF3YY=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ru.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       ZtVq/Mf1qT9j8xdhz9ULfJ1O05k=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sk.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       8o3l6mjHafwy5sLMMO2rZIe7xiQ=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sk.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       s3Cllq+eYT+urMLfXvnwsMkboWQ=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sk.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       gqdvwKoHMg+gDZ4MZVVqbV4yqI8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sl.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Ny5EoZGpd5UK5c3eMIUKLR8x4/I=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sl.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       vbP9bj0jn5GKz9uEu3amXnozkWo=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sl.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       hz8NwYxW1d0aWPQDMF8/c4lJRwU=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sv.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       YWicg3ZZLCEoiJ9WOUUZ6WoTZJY=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sv.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       JKbTlT+iKE5KOwvLD9N/Go2K+q0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/sv.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       UH7udC5C4WHwnnx4Eg6Io23rBzk=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/th.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Cd6guArNrSoJO3e2ntd1Eys3bok=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/th.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       L4ZWMKTKnMsbMsL8V2V6OLySKLE=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/th.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       O9PZTdxbP4Y306ym/2sJ6p5klE0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/tr.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       wl9JoCOsqKgCSgMpFzhwObUUdh8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/tr.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       7lGd5uiq64Gdix4ymGi5MrjTtjs=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/tr.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       L+JSm1Y1SMSRVqore5+HlcHCyew=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/uk.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       6/WdcAg1mJs1/HT5krHhOxqyMWk=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/uk.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       I4B4qXPwnMhj/A+yU0vvngP7oak=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/uk.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       3YLrl/aRzoPCubIKa873XDZeU1w=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_CN.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       DjCjxSor6wnKAz8bFLcPCnW1Kw0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_CN.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       xeCj4c1ifxxhDFeLtNsSc4NgBFw=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_CN.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       Q18TnLdR6a0E72xXP6ETh0FF4CY=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_HK.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       +9prrb68fl57+m9WFQ+8Ay6XjRk=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_HK.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       5Pazf5ErH02Ny5mFB+R+dwCWPVM=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_HK.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       v2NQCc/vUJacBpqiLL5yANtiGc4=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_TW.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       167IbTfOhYu699bxXBhaGehjrco=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_TW.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       SNJz+3Rb1AJ2cKstnbGWL6Q8OW8=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/zh_TW.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash</key>
-                       <data>
-                       48nGyIkkDrsDKSq77pFReYsumCA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-       </dict>
-       <key>files2</key>
-       <dict>
-               <key>Autoupdate</key>
-               <dict>
-                       <key>cdhash</key>
-                       <data>
-                       o5T5EkaC+CwlU729GYNYKmqetao=
-                       </data>
-                       <key>requirement</key>
-                       <string>cdhash H"a394f9124682f82c2553bdbd1983582a6a9eb5aa" or cdhash H"0e6dcaf18ca843031d6c7395f90f2c430ced6967"</string>
-               </dict>
-               <key>Headers/SPUDownloadData.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       yhS+aH6hPb1hSOt0tT6Rej2kQoPz6wrtntLOBuoIIJs=
-                       </data>
-               </dict>
-               <key>Headers/SPUStandardUpdaterController.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       +3I+CmUwJuOPUMU9MsBJW4BZNzMkjeJjyYVSGAFGKh8=
-                       </data>
-               </dict>
-               <key>Headers/SPUStandardUserDriver.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       Y4fOofv2Ua1TAI9qM7wL8CalQGHLa1spvUNg9JB71NE=
-                       </data>
-               </dict>
-               <key>Headers/SPUStandardUserDriverDelegate.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       Y1CXvdztYvr7TNU5uykV9jSjdvcpl2aCQPwjVHZe+IQ=
-                       </data>
-               </dict>
-               <key>Headers/SPUUpdateCheck.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       H30F2i5GYmOu/j4JEw5WsuZbiGJXnge5gpyb9e2SHAM=
-                       </data>
-               </dict>
-               <key>Headers/SPUUpdatePermissionRequest.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       hnRNYPeaK0NWoKPXEYs2AoyD6QOE0CHDJWJxKM5Ma24=
-                       </data>
-               </dict>
-               <key>Headers/SPUUpdater.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       2RfJYG0mMGzLSAP82wi9XHEFSfkoBc22JiIik4SObd0=
-                       </data>
-               </dict>
-               <key>Headers/SPUUpdaterDelegate.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       LHjSN/efNGASgXqi8P76eNivCLV2QZxP2/rvDMLcKyU=
-                       </data>
-               </dict>
-               <key>Headers/SPUUpdaterSettings.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       Nnk1lMwSl/z+ugdM8ovU0U/bQUoOWG6zjYQHXPF+kCU=
-                       </data>
-               </dict>
-               <key>Headers/SPUUserDriver.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       FZyzRoNn6SIm0ugYRKGMzlmq0C60WknB8YHjZtfmmYw=
-                       </data>
-               </dict>
-               <key>Headers/SPUUserUpdateState.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       Z4UKJcXMF/bUmSkIiM+D8jTiS8i5x1CLqoo4uG4aQvg=
-                       </data>
-               </dict>
-               <key>Headers/SUAppcast.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       M3KUgO+Ud/n5t/rXjFYzQMUTPDA8fK7W46QQfuh5DnA=
-                       </data>
-               </dict>
-               <key>Headers/SUAppcastItem.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       imKkb6r+8fp+9enH9Xlnh0VZ5S12ZkwmU53UHTx/Tdo=
-                       </data>
-               </dict>
-               <key>Headers/SUErrors.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       fmP8Y0mI10K5McjVGtVKtgzae36JLxmqLw3sr7vdBGY=
-                       </data>
-               </dict>
-               <key>Headers/SUExport.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       XO8CQmbFThLbYg949NEGhg3g+iouIw3/3+BCCLtEdFE=
-                       </data>
-               </dict>
-               <key>Headers/SUStandardVersionComparator.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       fUB7nOch1cZQ50HstpLnfxLvO14Y6oE29yRI6NcgjGw=
-                       </data>
-               </dict>
-               <key>Headers/SUUpdatePermissionResponse.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       HScQok/zuc704lNfwGl1Csr6nigQLAsjeRJXG1HTuks=
-                       </data>
-               </dict>
-               <key>Headers/SUUpdater.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       8BXIwn75UYazfTyDZklTch+t6AlsOxNdTI/bNj/qx1I=
-                       </data>
-               </dict>
-               <key>Headers/SUUpdaterDelegate.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       XRFzmZB3ShVUFY8JAvcjptVwxLmD/VL5rwnFoy5rSlc=
-                       </data>
-               </dict>
-               <key>Headers/SUVersionComparisonProtocol.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       KLu0JKx6uB4rk/YeNZ/vo+0J1qONCyZQBNIQPA9GvbQ=
-                       </data>
-               </dict>
-               <key>Headers/SUVersionDisplayProtocol.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       PyPE+5u9vBlxRYDuTdf3P/wxQ26nM8m7MIw/dOerUSw=
-                       </data>
-               </dict>
-               <key>Headers/Sparkle.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       OkQqMusip3u1oI5hrGeNr/32xpfTMCC4Kmg7r0Aijgw=
-                       </data>
-               </dict>
-               <key>Modules/module.modulemap</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       1TF+JZkzFr6n8oH4WItto+C5Vf3K12f0H9KjqD0A5QU=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SPUAppcastItemStateResolver.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       HDvimACMGXV647Jwg2IqAFvOgJoB8G0sdPbeoW8yFO4=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SPUGentleUserDriverReminders.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       9W2dJ38WQX151mpIS0r8/EfCqZV6jEh621xwna2JVAI=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SPUInstallationType.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       hj9Br7Gf1Y8X1dqNvSUHMP70K+Q+S9xZAyPYMqKthFQ=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SPUStandardUserDriver+Private.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       rMdk5zH+nm0wf+Mt6k0GtFGWQiXCsql0WiPwNanN6q0=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SPUUserAgent+Private.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       DD6nxqq6syhA5BxWuyLPq03uTd4zAmA7b0q6msG1hQw=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SUAppcastItem+Private.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       760gwh52KqECJ9eZ1qZ6YyaaFHNHaEFf9mel5xnG4aE=
-                       </data>
-               </dict>
-               <key>PrivateHeaders/SUInstallerLauncher+Private.h</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       yy6cRl8IqwMJwr86TS98NdnHb/WkSAaUcAoiKYUg3ZQ=
-                       </data>
-               </dict>
-               <key>Resources/Base.lproj/SUUpdateAlert.nib</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       rNJnQOQk5Kw1RR/pFDaL/mDaQ6JBYFTTBPMmbSZRWD8=
-                       </data>
-               </dict>
-               <key>Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       JKjxgN6h8KUeAa51gY+o3UrMEEEIvZUG3qN6jSF8jZk=
-                       </data>
-               </dict>
-               <key>Resources/Base.lproj/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       bwYMQkHPDvn3lBABOZ6BxAcwSpZ3Lrl1YyvMRkNWt6U=
-                       </data>
-               </dict>
-               <key>Resources/Base.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       aZ6hIsTY6mApb4yL8CxqMHw0W1sTdp71lBqcEBR5ATk=
-                       </data>
-               </dict>
-               <key>Resources/Info.plist</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       As2ncnEr+6Q0chlVgQ1A/2o+An2IpNJGUM54KpAbokE=
-                       </data>
-               </dict>
-               <key>Resources/ReleaseNotesColorStyle.css</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       dr1pmXWP2OUdF+a0gttDT5tHaMArA3r2vS46AAzoy8E=
-                       </data>
-               </dict>
-               <key>Resources/SUStatus.nib</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       V7nQA4E39SW5aUzqhBVsXTFN0jH5W2mdJr74xs58fWU=
-                       </data>
-               </dict>
-               <key>Resources/ar.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       33nOBJb6OPaZt3PKT2iUJ3RfF/c59DAGmt9TCQVn74A=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ar.lproj/SUUpdatePermissionPrompt.strings</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       ku6BdTbNrkSmKEdwyNA1hmoKbQ3uRv8JR4LK4cjqgpA=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ar.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       yx9tkKjj3aOHvgdYCWXM89uhlyVeNb4oqcAenJxibwI=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ca.lproj/SUUpdateAlert.strings</key>
-               <dict>
-                       <key>hash2</key>
-                       <data>
-                       18qLsTRnJfi0wDf6A85XbiMXGORSmuo9Ul3IK4m5gq0=
-                       </data>
-                       <key>optional</key>
-                       <true/>
-               </dict>
-               <key>Resources/ca.lproj/Sparkle.strings</key>
-               <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       3iHHzb3P1DvR6KaXp59ybrj1JySnfOgPbOigOIgI7es=
+                       PNYw/afpNtOrmCNC8SWxaJTWSgQ=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/cs.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/ja.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       qSoDl0PIYv+OrSxtJfUYk9xeQihmzfaxAf+egKyw4y4=
+                       myJp0ElupCpG4phEI8Q8ALK1czc=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/cs.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/ko.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       obkk1c1EawdfEyPHqo5ddIzsUcWfClFUbg895zj3/Ag=
+                       +rLWeKh8N/PJndmu/vE/a0ZZ//4=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/cs.lproj/Sparkle.strings</key>
+               <key>Resources/nb.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       2Nm0MQj4WgMucaSuEdljuTIGS/oceXEuVWi2kDgjRq0=
+                       7T4tgFrl8L5HKxsa3BqpxwlCbhk=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/da.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/nl.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       aKNcPadrNnf7wuYmBAxoRzES9XhxXRHMrW/+9MtZBQs=
+                       5LcVaHg0grJ0vDggCaXx7l1KTwI=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/da.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/nn.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       xremLoAOqEfufOFyjOrH8S8ZkWwRklRhGCGB/igGD38=
+                       6TKcfDjDXy2w/l+WpcyN3q33OSs=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/da.lproj/Sparkle.strings</key>
+               <key>Resources/pl.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       BOUi5PfyUb/ZRM6WZOuFC34IOic4+XPJkLikDtwhZIw=
+                       kwySQYkh8n0leATrIoAeyTZy1+A=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/de.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/pt-BR.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       A6JiLH5c4UX2iobAPXPHv7TLiBInrdHvtvqnnsTBxLI=
+                       VopPIMLshPYiYuKljquuZzNGJVY=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/de.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/pt-PT.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       GPjZbm0EAKfj0CK7Pb1UITo5WoDzNpf4m2XELfj3eio=
+                       NEDnlPEQQ+nDbGRR+eWfCulsTxU=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/de.lproj/Sparkle.strings</key>
+               <key>Resources/ro.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       Wv+mo8RfxojepYE9GcBeYwUNycpqkk9qo/BjYGwb08M=
+                       x4LCBI0pkdA2fEOdYtnSRj/IVsI=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/el.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/ru.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       utAXO7a8Od4ICYV3R0WQBa8ncUQ30SfruZACTuvyDxk=
+                       8OsJ6WTQeMTV06mnU6nIp1Wyilc=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/el.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/sk.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       V0h7tXPJI0b1Z0FEMxe7RJIn2oWGg9QUhF/cRSz7aWE=
+                       6LpsH87uTuP3IDgICCnsls9ljF0=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/el.lproj/Sparkle.strings</key>
+               <key>Resources/sl.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       Bl2oDZnDwbj55sSp/MNoHmcSbiOW5kxY1OGcL3k5scY=
+                       sMh8m/GbzigzKc4IWFynhJZgZZw=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/en.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/sv.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       EBVS8ZfEIJxGSghO17emwoHQo0LVWWzBJMFs8RwvKWg=
+                       G2RCHl7W/Db88nHDTgDF9txwpeI=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/en.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/th.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       MN0HeTdXIxqALqUMUoLnVkRcDcvnDXqjsifU07tV3a8=
+                       lhtsbCs8a/YN8USZqRzAu6l+WKM=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/es.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/tr.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       8KSmmlZHYEiMGUwXQRV+ZDxs07XmaeH4XIYI+di1ono=
+                       nQVohktMItLSG//uX50V1Q3tjNQ=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/es.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/uk.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       GEtUsrVDWqXyHAV8lWPrEUWQm30jetvOjJZdlI7egwQ=
+                       JGzTZrZVOFEmdPUU2nGug8+1Egg=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/es.lproj/Sparkle.strings</key>
+               <key>Resources/zh_CN.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       OaVgz8LiS96ZT2vfsJKv7bM+mwC0DT7Px6A1rIxboYg=
+                       y6gXzs0x9sm68yiEJTGg8h8w+SY=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/fa.lproj/Sparkle.strings</key>
+               <key>Resources/zh_HK.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       Ue4NSlcLQL9OAOrD5Ibul1RaIwZOl6vcIv7DsffzQMA=
+                       twyTX9DzpgoJDvTFdkPXfvuGo6Q=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/fi.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/zh_TW.lproj/Sparkle.strings</key>
                <dict>
-                       <key>hash2</key>
+                       <key>hash</key>
                        <data>
-                       O+ja0EMKj5RxMmW3TRALc9XTpMJ7Y7dwXm706E33rUA=
+                       6ltKBe6A8F5/DrkTElCM58gP9iA=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/fi.lproj/SUUpdatePermissionPrompt.strings</key>
+       </dict>
+       <key>files2</key>
+       <dict>
+               <key>Autoupdate</key>
                <dict>
-                       <key>hash2</key>
+                       <key>cdhash</key>
                        <data>
-                       MfjVC0QQ0Dxvz6Rt03EhMaahM5Gh5rhqMSJFEqzSRLo=
+                       Y5PWQvqGAUx8n4Ksz4bveQ3a6xI=
                        </data>
-                       <key>optional</key>
-                       <true/>
+                       <key>requirement</key>
+                       <string>cdhash H"6393d642fa86014c7c9f82accf86ef790ddaeb12" or cdhash H"85a39bc15f811476c9c39a17e2365eeb1f88b58f"</string>
                </dict>
-               <key>Resources/fi.lproj/Sparkle.strings</key>
+               <key>Headers/SPUDownloadData.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       O6+s8+GKGX06x08WB1v526jOSl30MEoNnzjhYKe4IA0=
+                       yhS+aH6hPb1hSOt0tT6Rej2kQoPz6wrtntLOBuoIIJs=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/fr.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SPUStandardUpdaterController.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       Avyaxx14FRXq/CTIDvvF7uww42SRhYgNSc960h7MCfc=
+                       lkiZ+GQk10vq5kdO/AxFC8JpBq6/iC8oQDR3tYNbSn8=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/fr.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Headers/SPUStandardUserDriver.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       qlNtkoH6vAA93/yxp8Stav74m46gvKb+3R26QDMSsXs=
+                       VP0vOS6fZYXlXPuWp7mYvsAylJ8W3r4ZVCn6kHhbL9I=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/fr.lproj/Sparkle.strings</key>
+               <key>Headers/SPUStandardUserDriverDelegate.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       O5To7z4frtvm1D6zwFzz6rpleVtia2BFro3bElXznDg=
+                       Y1CXvdztYvr7TNU5uykV9jSjdvcpl2aCQPwjVHZe+IQ=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/he.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SPUUpdateCheck.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       SmfKGCNVK9M61LCNGqWk4/FZInlcKG2U9uD5ajPVobw=
+                       H30F2i5GYmOu/j4JEw5WsuZbiGJXnge5gpyb9e2SHAM=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/he.lproj/Sparkle.strings</key>
+               <key>Headers/SPUUpdatePermissionRequest.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       dWNbn7k2fHYYtPta1WhZ1DvglupayXIaQjBYK/8G7cQ=
+                       hnRNYPeaK0NWoKPXEYs2AoyD6QOE0CHDJWJxKM5Ma24=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/hr.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SPUUpdater.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       L7shRNgdZIfbt5y5pioLEIo+A9I7VtgIUFpzoCFkB1I=
+                       gBm9VXuaoijT9k+8S9Lqq9L6DHZzPcAWZxuU5kkUWMU=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/hr.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Headers/SPUUpdaterDelegate.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       5x5zRCWzWYlbd7MkUcbPs5ZWrWQRDZnj3s9K2LmsnBw=
+                       bUP8h5u5vMbDU68cKrno2Y22fRQTrOJp5Ipj2rHTSbc=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/hr.lproj/Sparkle.strings</key>
+               <key>Headers/SPUUpdaterSettings.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       Nmip9NgB014UDYN3yOsmsOFa9D3wED0L56Mve3WIVQg=
+                       GiYGeD+dxWuBIX54u11Tgrg9lNjritBVEN/4WWlE61M=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/hu.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SPUUserDriver.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       8LbsWTkMSczHFa4Rh9XZDRo0uCOyrV9VXUYEiEvnG7I=
+                       I++Y+tlGVPYOGf28d6ougNs3KQAghISe/uZJ7eyFOLc=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/hu.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Headers/SPUUserUpdateState.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       twHi8JXysxao7MlTGr178ZpB8yz1mXkij2V5n8NJWSQ=
+                       Z4UKJcXMF/bUmSkIiM+D8jTiS8i5x1CLqoo4uG4aQvg=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/hu.lproj/Sparkle.strings</key>
+               <key>Headers/SUAppcast.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       0UBqgjXjtRG51lEacNaLTmNvj5aFUeJ7oo1J4WYkrCw=
+                       M3KUgO+Ud/n5t/rXjFYzQMUTPDA8fK7W46QQfuh5DnA=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/is.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SUAppcastItem.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       04Q9PpqtuYz6kfVhf6eI9XBxJn0LQB9Ck/ceBq1ztGU=
+                       vz8FZzMme+74ydZ2E7v8UlIK1XDwKATrL+tEfVF99A0=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/is.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Headers/SUErrors.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       heK63dQF7YJvehrOEQk1jesq6v3bQBJy2jL+w5jjMlE=
+                       IdPofMbgIxKD7Bb94Ptqvb7kAPGfIR4ajS2zqO5bfbY=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/is.lproj/Sparkle.strings</key>
+               <key>Headers/SUExport.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       5/4A+HgH/PhUAQ3NVnURPeiIJsQYJyZ28sAObmxJlVU=
+                       XO8CQmbFThLbYg949NEGhg3g+iouIw3/3+BCCLtEdFE=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/it.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SUStandardVersionComparator.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       1zxkJlohqYtSJb0pj93fJXlPkedYm2IllbilGRDFo90=
+                       fUB7nOch1cZQ50HstpLnfxLvO14Y6oE29yRI6NcgjGw=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/it.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Headers/SUUpdatePermissionResponse.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       XjyG4RGvcVUZia4jJHGYQEfgocs1iEx7iljn+vue5xY=
+                       HScQok/zuc704lNfwGl1Csr6nigQLAsjeRJXG1HTuks=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/it.lproj/Sparkle.strings</key>
+               <key>Headers/SUUpdater.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       2Glm2TwT78wZfe8iqBg8z/oCgrmtzqthnzNlHvHt5ls=
+                       lvb1mNWCyofJ0X88zXvMsK5PBXrG6Pr7hUrY0E3jNvY=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/ja.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/SUUpdaterDelegate.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       vFagmq7Xdp80v7/plWY/m3PBNbxFsCeu0x8wDzZQRT4=
+                       oaCMM/1B690QWRbYGB0iJBf5/toBzcQq+moxURBs3jY=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/ja.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Headers/SUVersionComparisonProtocol.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       zYuOp6owctTI6zIFWac7yKqGLEglaXnTlNOnh/n7mow=
+                       KLu0JKx6uB4rk/YeNZ/vo+0J1qONCyZQBNIQPA9GvbQ=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/ja.lproj/Sparkle.strings</key>
+               <key>Headers/SUVersionDisplayProtocol.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       ND5iilhwr65bkm+YhqLGqKEISY1I2td3Ncn8D8Vdass=
+                       PyPE+5u9vBlxRYDuTdf3P/wxQ26nM8m7MIw/dOerUSw=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/ko.lproj/SUUpdateAlert.strings</key>
+               <key>Headers/Sparkle.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       shkQwYfF0rI+GzhWoVLqI7A1hKTnRr/o4wnUFb3Vhik=
+                       OkQqMusip3u1oI5hrGeNr/32xpfTMCC4Kmg7r0Aijgw=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/ko.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Modules/module.modulemap</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       lqPQJYKtJlVGV2/UpetCpxTEpb4u5aUUU9CjmZO2OaI=
+                       K8rh62bVXcSfWKz+hWN1pbvJHG6DvbKY0ZRCrmJkz6Y=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/ko.lproj/Sparkle.strings</key>
+               <key>Modules/module.private.modulemap</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       YqbMnU7mRpPLmsdD7YIXgMZkaxkkL5aaeoiv4bLN93I=
+                       2x1g9XtDqesX81UPVyCsU0ZtQ4U2hnD7UUjaW3H0Pzo=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/nb.lproj/SUUpdateAlert.strings</key>
+               <key>PrivateHeaders/SPUAppcastItemStateResolver.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       RQbKlvLGnVjjVMP5eHHNUCv5kLJl4EA6zNGdDKatbH0=
+                       HDvimACMGXV647Jwg2IqAFvOgJoB8G0sdPbeoW8yFO4=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/nb.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>PrivateHeaders/SPUGentleUserDriverReminders.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       F85iUA2aHbvo23Z0jJ/T/pwJ2HOQdYD5eRyAow9cSgY=
+                       9W2dJ38WQX151mpIS0r8/EfCqZV6jEh621xwna2JVAI=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/nb.lproj/Sparkle.strings</key>
+               <key>PrivateHeaders/SPUInstallationType.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       6sl0vlKoRBQtvGvC7oGwtHA8/B+fNdwBGwN2AyISsXQ=
+                       eSRnJrGHhArw4ip9KaIVo3bknF8bHywhkQaEY3RbLmo=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/nl.lproj/SUUpdateAlert.strings</key>
+               <key>PrivateHeaders/SPUStandardUserDriver+Private.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       tp3fY8ogv+xcQOFkz5BkDNTZHIaRrhGgT9uKfCjDB70=
+                       rMdk5zH+nm0wf+Mt6k0GtFGWQiXCsql0WiPwNanN6q0=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/nl.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>PrivateHeaders/SPUUserAgent+Private.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       Yrwc9ESTayZoqv2JWm0nD1IHGLeAiBncPc2OeaVz8J8=
+                       DD6nxqq6syhA5BxWuyLPq03uTd4zAmA7b0q6msG1hQw=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/nl.lproj/Sparkle.strings</key>
+               <key>PrivateHeaders/SUAppcastItem+Private.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       tBjWBavMtayqool9JGs+xH56A2Kui/7dRQX27xG2jx0=
+                       9H7OIT9nEoYXUBBcvTZdSOzlq81uWIUS8Mqjuhfz9Ww=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pl.lproj/SUUpdateAlert.strings</key>
+               <key>PrivateHeaders/SUInstallerLauncher+Private.h</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       oB2rGM/SPnJLdvhUz2CJfm8TS6XhrhmHD2gFyrVSq8U=
+                       yy6cRl8IqwMJwr86TS98NdnHb/WkSAaUcAoiKYUg3ZQ=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pl.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/Base.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       ubFfFWaG2RKXgeGR4DRtvbY0fH+SNJZzBebSPCo6K5c=
+                       h0RcjBD3QQ1N6GwW87ZknA/WNeAcID6aSDdaeHqqor0=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pl.lproj/Sparkle.strings</key>
+               <key>Resources/Info.plist</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       KwctPd8Y+mrsEYWALAkKXeCfY4celUbA3MVn+Ye4Imc=
+                       ed7Rvnpwp2t+CTDfineANAlqA+JSHhVwf25fGc4rbNk=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pt-BR.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/ReleaseNotesColorStyle.css</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       hDN04zbJliR6KRqEv4lEuAVNTjbkmyYUpKjCbWKaKdU=
+                       dr1pmXWP2OUdF+a0gttDT5tHaMArA3r2vS46AAzoy8E=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pt-BR.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/SUStatus.nib</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       6NvKj6GmzGQLAsGBC6IUvRBoLSRfEJuWi7ZitoTyoTk=
+                       Qd5rCHQjMKfxN9BfliN2b7KXpOro8kFotf6JbmgnSLI=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pt-BR.lproj/Sparkle.strings</key>
+               <key>Resources/SUUpdateAlert.nib</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       Kcwam/xq0V6VzMD4+rbUrDyAtrsl186J6lEeu5K2qD4=
+                       RdxbkmhTqm4jEyi6s+NLfAaGwEuSIe94p3qvlyb9vs8=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pt-PT.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/SUUpdatePermissionPrompt.nib/keyedobjects-101300.nib</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       gto4ribWYRWZl0Eez6/7XZg3EesExPlGb5Nz1YVTuzE=
+                       pp/j4iAKxPCcaXDXKYZquxKXc+Gd2az8d54SLo972cU=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pt-PT.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/SUUpdatePermissionPrompt.nib/keyedobjects-110000.nib</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       st4wdNoLjj5sVIFHqDAh3cjRFhxhpzkcFP7AJSXjYkw=
+                       3hPMTRyHFd+VkmEv13rM90gZp79xeICeTqc4epB8jQM=
                        </data>
-                       <key>optional</key>
-                       <true/>
                </dict>
-               <key>Resources/pt-PT.lproj/Sparkle.strings</key>
+               <key>Resources/ar.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       RLdbB4cQnps2k/crFyvGScdjmGE3KSkG448wTbYi4vY=
+                       RBGCeHRxo5mJCARFFf4T6SIw7ap+JzBjjnKklhD1bLo=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/ro.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/ca.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       PZZnueQNOLmQuEtkELhzxhnG+MDu7RyeOaySHSoHmYU=
+                       ftDVyjAGSafxMwQBUAjy3t6YrXQ6YlwX1aX+2swaOxo=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/ro.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/cs.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       IkIaDJ/HgpnBNNkP+MF2JGSd+rNgAI+o9c2aNor+ewo=
+                       meZt7Pm8Rs9WIu6tTmWztQLjd1pOjg8D7xtBaD6o1Rg=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/ro.lproj/Sparkle.strings</key>
+               <key>Resources/da.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       w2L0Ki7vhlIa92HDkDRmDExmCXIGkOWil+ROXr+6I+k=
+                       jQ/2m3lGAYX5QTcmVUM7rTk09J5jvvC0FxvWbaceVfA=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/ru.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/de.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       wdiMmOcek4MJvdl1u2OoccWD56zCu2lKDGUd40bnMb8=
+                       x9QQzJi6B2SSOJDqZq4DvDsknUpEYzV8ACuI2UxDsI8=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/ru.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/el.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       /uARbwIQFupNOZvlyWgeE722GAsKcu4/QooLAEGHCBQ=
+                       Y4mBpPCV2LHau2Iw1FLkcDWXEbgYA7xd+MIeEhH9N1c=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/ru.lproj/Sparkle.strings</key>
+               <key>Resources/es.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       INHL+VHSTd0hjYmUXHPShl3l4xTB4C3KcCLgVn/AHGw=
+                       MM8rGNMHlpYdiNookp0IxizkWQRVPQBHAod9x0Sb8N8=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sk.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/fa.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       FDJ/dTwG5X34BF9lDDkFVGJUwpLeKi1MUbF072nYass=
+                       7Z3anicfepe4p/Mn5xobbQbl4GGzZ+faPRU+R9wxkmM=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sk.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/fi.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       xa+UPXIC+og1IpGE6bA/+51E2uR9ZG+HGWKFA83tTNU=
+                       wUr5usP85DYiKk6id6emwPm0Ky2ErO6nXnWM51OKyuI=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sk.lproj/Sparkle.strings</key>
+               <key>Resources/fr.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       VmLLF6tJBA+j9jFby3BVx9GagD//qx4ETRywoU71PVQ=
+                       PVVNzRZ7CF4lp1JIUz8h84lZOurOkSq5lSyCX/4UHOE=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sl.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/he.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       OAq7ojI6K/xR4nFEK1OBTiJeNaHqgb8xCgzZ5Y3P7Uo=
+                       HXlb1zKdBLfOhLa9yEX5FzaehYsrKS8Re4mmZmoYVyM=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sl.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/hr.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       ik4klDAQYgMT5hrecUkfi+K/tuGyvOYk96xp+z98l74=
+                       kgBBOAoIs7pQ1E6Kg/Wd5VETmEWnJ0jVjyOHxlkgszo=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sl.lproj/Sparkle.strings</key>
+               <key>Resources/hu.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       VTtzpxCnkPCO1yB2GviO6AkaZFKPpcUh530dTdqFcQE=
+                       zCoW5NSHxvqzV7T30Pu/fsiCNxshMEE//LG2nNVA0s8=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sv.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/is.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       LYXEBB7MF82Ig5MgIM9pTtJJAYJL51nzYzbVW1kdSGI=
+                       QD/rpQNBDpRVzQ6q/lkqJXbu2yQTDM8s2xPdpLEB+H4=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sv.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/it.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       XDORKepHKWfDihFVMFnshPW/qjSLPLoU/zHqJQbRoBk=
+                       VqdEXBto12hJrFm5iqXCDJAC1eB+nwonIEhhYPhbc2Y=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/sv.lproj/Sparkle.strings</key>
+               <key>Resources/ja.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       nidShaf5BKX1wQntkXeQhcGQoWUzNgVQhfHSM44GXVM=
+                       5ASRACivcFec+iCLtPrdnjWSUF/ImvII9AcfIwlVP7I=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/th.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/ko.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       dvWO9t2NYZ+cQoe/9B3Tib+EPOdPp4wgatHaVVhu8gQ=
+                       piaes/WgfQxPXXRn1QZTcgha73SExRip14T/1sj1quQ=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/th.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/nb.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       mxCL8k437ikdUpl3px2Ii/2fZqL85x1Fn/xe7h1YI6E=
+                       728NyukMRAtH7OCZCenN818zg/NOcqYUyMXAdS7L/+A=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/th.lproj/Sparkle.strings</key>
+               <key>Resources/nl.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       vj4h7104vuQqis9NXvSgrgQNz9czX6lMJqdvem4VCUk=
+                       yprfNPuT/j85TMySEUv2prH4oSi7XzYsufMkfXwmx30=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/tr.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/nn.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       Eas+RUaJ03H05UVqHIhONcr5aa06Oj3g21RnNac5od4=
+                       HbjGhTpVCqJTgtotVUMaHB0wjWo3Z2xPhZPMFjP4pa4=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/tr.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/pl.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       D3zqZ6c91YzDkgT4Vs+/SM98tCcw+qDhY/eKhohBfZg=
+                       XFSz+OHrMCbhQucQ4hZ/L4Obc6ta1/GHGSMPM65oKqk=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/tr.lproj/Sparkle.strings</key>
+               <key>Resources/pt-BR.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       noD1zsNtx5u2wHPX8rarT7YPn+H09/DgvHb2553BnDo=
+                       ApLK3CrPw0h1weC1Ti1Q3jgzzV4gyGYMjv/iuFmqyEw=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/uk.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/pt-PT.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       lR6DOvFkMHpmbtXQJNE1aXtRXgBbd0siVMoq01D4dhM=
+                       /JWFMtJqjh50Yi0/VY/CahKADoxJ+2FK/Q4Yg6zORwA=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/uk.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/ro.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       +MphWMKEy2hsIqrjroJQcq+x1mytcNeZm+z3Lv+ll6A=
+                       sr8GQiLDijZysB/glAb3mXGMsPxOcVEhZiY51v3+pu0=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/uk.lproj/Sparkle.strings</key>
+               <key>Resources/ru.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       gvuLzOKGahqSQtAwSCb9CuBAYuDVwfj+lwwSv/NPq8s=
+                       cZOvKOsqCbn+cRnPYGWiFQxlkJcbIvmMVvNWzZCFGSM=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_CN.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/sk.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       NXEAoNAKcjI5GBtGxYcUXmtz+rP06ocJSSVlaR/lnMA=
+                       4Vjaqk8/kbV87gWriW8sG8RnMXkyzFO7fAHn2u6eUjg=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_CN.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/sl.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       8co96MJCMuKNvaPFe13uh2d028P/Cgpa8iOiNml9rfE=
+                       xidwxgSmyMieKDNXyLMi2M5qhfTYXAkAIEgzH2X42YA=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_CN.lproj/Sparkle.strings</key>
+               <key>Resources/sv.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       nKdLa3IQhWTKipj6MF+VwRUugjpvTVuGIpzQF/QDUYI=
+                       SiGtW8+Ng20mVxDC5KCmTwfJVR8cSWlNZzSpMdI+/Tk=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_HK.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/th.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       zegYIhIFwtdJa87mjTlkalyYSz31LrnhiwNWDJDPqBU=
+                       S2yNwqtpoEJd46qdw4bGU5NI45g+R6oQ+UwX40WhV6U=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_HK.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/tr.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       54ogzTvsgJOl4aSWIQRzRzky1TddmGlpamTLhHMJWb0=
+                       sEDT8C00HroEfBXfyvtgQG0IRwlqlEZuyrUS3PsWq7U=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_HK.lproj/Sparkle.strings</key>
+               <key>Resources/uk.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       AKEvYEi8FGZbbYnhpr2nqeUWrBQaj7wJjo8/KjED1U0=
+                       /0TVhjWz6ECdVLQrcsh2pD4X+pj26pazJYO56Ix0erY=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_TW.lproj/SUUpdateAlert.strings</key>
+               <key>Resources/zh_CN.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       jdmB9inrJUf1OmYmVnORSMfdz5z1SWmBtdv39I776K4=
+                       5/VDuSl36avJByQcQR2NsPWcT+5ICFmz6I5LSV4Jdsg=
                        </data>
                        <key>optional</key>
                        <true/>
                </dict>
-               <key>Resources/zh_TW.lproj/SUUpdatePermissionPrompt.strings</key>
+               <key>Resources/zh_HK.lproj/Sparkle.strings</key>
                <dict>
                        <key>hash2</key>
                        <data>
-                       4tCLZKKcNuOJ1up1IgFXUeEp7s5U5BOBGHC1EZMyrhE=
+                       P8IQEy8z2Jrz0l0nx+oZQmz20wS+UCVFOEVuDsT7eFg=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>hash2</key>
                        <data>
-                       NhrxIO01cQJckmOoEhEbQ73y2RcEy8drXCHDvsvcLEw=
+                       djIeHdhEybZWjLSvfGO7V9nRtwAQmu7dflch14cnsS0=
                        </data>
                        <key>optional</key>
                        <true/>
                <dict>
                        <key>cdhash</key>
                        <data>
-                       bwydMD30i3XJLgdaSJaOKvGHWNw=
+                       mkisnCA6DZfDLsEPIrQPoVwih5g=
                        </data>
                        <key>requirement</key>
-                       <string>cdhash H"6f0c9d303df48b75c92e075a48968e2af18758dc" or cdhash H"ccf6be6a2321e5fca26c2d4e18a84a7b88335410"</string>
+                       <string>cdhash H"9a48ac9c203a0d97c32ec10f22b40fa15c228798" or cdhash H"2832bff9485769960d4937d89acb034b258abc48"</string>
                </dict>
                <key>XPCServices/Downloader.xpc</key>
                <dict>
                        <key>cdhash</key>
                        <data>
-                       JGT6QWfBdYaNLDT53M7XH6CMf9w=
+                       08kWuFtk/8slVNRSaoyWymbcizU=
                        </data>
                        <key>requirement</key>
-                       <string>cdhash H"2464fa4167c175868d2c34f9dcced71fa08c7fdc" or cdhash H"4d0238ab298ac7844cc4c060c8d0e44fdb6c199a"</string>
+                       <string>cdhash H"d3c916b85b64ffcb2554d4526a8c96ca66dc8b35" or cdhash H"5f36255ea27f0164d96bf4abdaf26c2a9a5cf2d5"</string>
                </dict>
                <key>XPCServices/Installer.xpc</key>
                <dict>
                        <key>cdhash</key>
                        <data>
-                       7skE4fG1Lz/R9Xo6olqHNFAC5VE=
+                       v8w8gupAbknq3Hy9hVbzI3wuMf8=
                        </data>
                        <key>requirement</key>
-                       <string>cdhash H"eec904e1f1b52f3fd1f57a3aa25a87345002e551" or cdhash H"ab805e9c434dc9a04e995ff82949a5338e9e0be2"</string>
+                       <string>cdhash H"bfcc3c82ea406e49eadc7cbd8556f3237c2e31ff" or cdhash H"7105be3dceddf5251708f9ff84b6b8d0fe3c9a7d"</string>
                </dict>
        </dict>
        <key>rules</key>
index c0428c10daa4210729e3e3b9844300001290ab6f..29886a8ffa04bbc8bcd993f2f2e13cf116afa9a2 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSMainNibFile</key>
        <string>Updater</string>
        <key>CFBundleIconFile</key>
index b3d7ebf00419fb3cbe651c4477acd13c11d9142f..aa6a526474b9568268fcc2d0198f5c1c91d5cbad 100644 (file)
@@ -17,7 +17,7 @@
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>LSMinimumSystemVersion</key>
        <string>${MACOSX_DEPLOYMENT_TARGET}</string>
        <key>NSPrincipalClass</key>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSMainNibFile</key>
        <string>SaverRunner</string>
 </dict>
index e4d1181e6f42ece6457a79c65f07115448efd91e..5af419c2bda636a9df7c19aa1ef05468378dfc59 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright © 2006-2023 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2006-2025 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -292,7 +292,11 @@ typedef enum { SimpleXMLCommentKind,
 #if defined(HAVE_IPHONE) && defined(USE_HTML_LABELS)
 
 
-@interface HTMLLabel : UIView <UIWebViewDelegate>
+@interface HTMLLabel : UIView <UIWebViewDelegate
+# ifdef USE_WEBKIT
+                                 , WKNavigationDelegate
+# endif
+                              >
 {
   NSString *html;
   UIFont *font;
@@ -323,6 +327,7 @@ typedef enum { SimpleXMLCommentKind,
   webView = [[UIWebView alloc] init];
 # ifdef USE_WEBKIT
   webView.UIDelegate = self;
+  webView.navigationDelegate = self;
 # else
   webView.delegate = self;
   webView.dataDetectorTypes = UIDataDetectorTypeNone;
@@ -501,6 +506,7 @@ static char *anchorize (const char *url);
         navigationType:(UIWebViewNavigationType)type
 {
   // Force clicked links to open in Safari, not in this window.
+  // Old way, 2020-ish?
   if (type == UIWebViewNavigationTypeLinkClicked) {
     UIApplication *app = [UIApplication sharedApplication];
     NSURL *url = [req URL];
@@ -521,6 +527,26 @@ static char *anchorize (const char *url);
 }
 
 
+#ifdef USE_WEBKIT
+- (void)webView:(WKWebView *)wv
+        decidePolicyForNavigationAction:(WKNavigationAction *)na
+        decisionHandler:(void (^)(WKNavigationActionPolicy))dh
+{
+  // Force clicked links to open in Safari, not in this window.
+  // New way, 2025-ish.
+  if (na.navigationType == WKNavigationTypeLinkActivated) {
+#   pragma clang diagnostic push   // "openURL deprecated in iOS 10"
+#   pragma clang diagnostic ignored "-Wdeprecated-declarations"
+    [[UIApplication sharedApplication] openURL:na.request.URL];
+#   pragma clang diagnostic pop
+    dh (WKNavigationActionPolicyCancel);
+  } else {
+    dh (WKNavigationActionPolicyAllow);
+  }
+}
+#endif // USE_WEBKIT
+
+
 - (void) setFrame: (CGRect)r
 {
   [super setFrame: r];
@@ -1133,21 +1159,21 @@ boldify (NSText *nstext)
 
 
 /* Creates a human-readable anchor to put on a URL.
+   Duplicated in driver/demo-Gtk.c.
  */
 static char *
 anchorize (const char *url)
 {
-  const char *wiki1 =  "http://en.wikipedia.org/wiki/";
-  const char *wiki2 = "https://en.wikipedia.org/wiki/";
-  const char *math1 =  "http://mathworld.wolfram.com/";
-  const char *math2 = "https://mathworld.wolfram.com/";
-  if (!strncmp (wiki1, url, strlen(wiki1)) ||
-      !strncmp (wiki2, url, strlen(wiki2))) {
+  const char *wiki  = "https://en.wikipedia.org/wiki/";
+  const char *math  = "https://mathworld.wolfram.com/";
+  const char *shade = "https://www.shadertoy.com/view/";
+  if (!strncmp (wiki, url, strlen(wiki))) {
     char *anchor = (char *) malloc (strlen(url) * 3 + 10);
+    const char *in;
+    char *out;
     strcpy (anchor, "Wikipedia: \"");
-    const char *in = url + strlen(!strncmp (wiki1, url, strlen(wiki1))
-                                  ? wiki1 : wiki2);
-    char *out = anchor + strlen(anchor);
+    in = url + strlen(wiki);
+    out = anchor + strlen(anchor);
     while (*in) {
       if (*in == '_') {
         *out++ = ' ';
@@ -1156,10 +1182,10 @@ anchorize (const char *url)
         *out++ = ' ';
       } else if (*in == '%') {
         char hex[3];
+        unsigned int n = 0;
         hex[0] = in[1];
         hex[1] = in[2];
         hex[2] = 0;
-        int n = 0;
         sscanf (hex, "%x", &n);
         *out++ = (char) n;
         in += 2;
@@ -1172,14 +1198,14 @@ anchorize (const char *url)
     *out = 0;
     return anchor;
 
-  } else if (!strncmp (math1, url, strlen(math1)) ||
-             !strncmp (math2, url, strlen(math2))) {
+  } else if (!strncmp (math, url, strlen(math))) {
     char *anchor = (char *) malloc (strlen(url) * 3 + 10);
+    const char *start, *in;
+    char *out;
     strcpy (anchor, "MathWorld: \"");
-    const char *start = url + strlen(!strncmp (math1, url, strlen(math1))
-                                     ? math1 : math2);
-    const char *in = start;
-    char *out = anchor + strlen(anchor);
+    start = url + strlen(math);
+    in = start;
+    out = anchor + strlen(anchor);
     while (*in) {
       if (*in == '_') {
         *out++ = ' ';
@@ -1197,6 +1223,16 @@ anchorize (const char *url)
     *out = 0;
     return anchor;
 
+  } else if (!strncmp (shade, url, strlen(shade))) {
+    char *anchor = (char *) malloc (strlen(url) * 3 + 10);
+    const char *in;
+    char *out;
+    strcpy (anchor, "Shadertoy: ");
+    in = url + strlen(shade);
+    out = anchor + strlen(anchor);
+    strcat (out, in);
+    return anchor;
+
   } else {
     return strdup (url);
   }
index 5562a3ef8bf7b8d4f92e8fb41c8c58b4183ab2f7..44aa81d9e91da34698e665e22c6717b96849ff33 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright © 2006-2021 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2006-2026 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -181,6 +181,18 @@ extern void check_gl_error (const char *type);
 
 - (NSOpenGLPixelFormat *) getGLPixelFormat
 {
+
+  // Jan 2024: for hacks that set "prefersGLSL":
+  // With this we get: OpenGL 4.1, GLSL 4.10, #version 150
+  // Without it:       OpenGL 2.1, GLSL 1.20, #version 120
+  //
+# define USE_OPENGL_3_2
+
+# ifdef USE_OPENGL_3_2
+  PrefsReader *prefs = [self prefsReader];
+  BOOL gles3p = [prefs getBooleanResource:"prefersGLSL"];
+# endif
+
   NSOpenGLPixelFormatAttribute attrs[40];
   int i = 0;
   attrs[i++] = NSOpenGLPFAColorSize; attrs[i++] = 24;
@@ -226,13 +238,25 @@ extern void check_gl_error (const char *type);
 
 # pragma clang diagnostic push   // "NSOpenGLPFAWindow deprecated in 10.9"
 # pragma clang diagnostic ignored "-Wdeprecated"
-  attrs[i++] = NSOpenGLPFAWindow;
+
+# ifdef USE_OPENGL_3_2
+  if (!gles3p)  // Why??
+# endif
+    attrs[i++] = NSOpenGLPFAWindow;
+
 # pragma clang diagnostic pop
 
 # ifdef JWXYZ_GL
   attrs[i++] = NSOpenGLPFAPixelBuffer;
 # endif
 
+# ifdef USE_OPENGL_3_2
+  if (gles3p) {
+    attrs[i++] = NSOpenGLPFAOpenGLProfile;
+    attrs[i++] = NSOpenGLProfileVersion3_2Core;
+  }
+# endif
+
   attrs[i] = 0;
 
   NSOpenGLPixelFormat *result = [[NSOpenGLPixelFormat alloc]
index ce50a74f229dd7e1d6f3f30205c3096452e9f578..09d25babd46b621e4dbe2d2bb64652716ddee5a7 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright © 2006-2023 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 2006-2025 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -142,7 +142,17 @@ extern NSDictionary *make_function_table_dict(void);  // ios-function-table.m
 # ifndef HAVE_IPHONE
   // CFBundleGetDataPointerForName doesn't work in "Archive" builds.
   // I'm guessing that symbol-stripping is mandatory.  Fuck.
+
+# ifdef USE_SHADERTOY
+  // On macOS Cocoa, the XScreenSaverView inside a Shadertoy.saver was
+  // compiled with -DUSE_SHADERTOY so that we know to load the shared
+  // "xshadertoy_xscreensaver_function_table".  (On iOS, that knowledge
+  // is encoded into the "ios-function-table.m" file.)
+  NSString *classname = @"XShadertoy";
+# else
   NSString *classname = [[nsb executablePath] lastPathComponent];
+# endif
+
   NSString *table_name = [[classname lowercaseString]
                            stringByAppendingString:
                              @"_xscreensaver_function_table"];
@@ -216,6 +226,16 @@ extern NSDictionary *make_function_table_dict(void);  // ios-function-table.m
     perror ("setenv");
     NSAssert1 (0, @"setenv \"XSCREENSAVER_CLASSPATH=%s\" failed", s);
   }
+
+  // Set $BUNDLE_RESPATH for xshadertoy.c to find the GLSL files.
+  NSBundle *nsb = [NSBundle bundleForClass:[self class]];
+  NSAssert1 (nsb, @"no bundle for class %@", [self class]);
+  NSString *nsrespath = [nsb resourcePath];    // "Contents/Resources"
+  const char *respath = [nsrespath cStringUsingEncoding:NSUTF8StringEncoding];
+  if (setenv ("BUNDLE_RESPATH", respath, 1)) {
+    perror ("setenv");
+    NSAssert1 (0, @"setenv \"BUNDLE_RESPATH=%s\" failed", respath);
+  }
 }
 
 
@@ -486,6 +506,7 @@ static NSMutableArray *all_saver_views = NULL;
 # ifdef CATCH_SIGNALS
   catch_signals();
 # endif
+
   xsft = [self findFunctionTable: saver_title];
   if (! xsft) {
     [self release];
@@ -502,9 +523,25 @@ static NSMutableArray *all_saver_views = NULL;
      $HOME/Library/Preferences/ByHost/ in a file named like
      "org.jwz.xscreensaver.<CLASSNAME>.<NUMBERS>.plist"
    */
-  NSString *name = [NSString stringWithCString:xsft->progclass
-                             encoding:NSUTF8StringEncoding];
-  name = [@"org.jwz.xscreensaver." stringByAppendingString:name];
+  NSString *progclass2;
+  Bool shader_p = !strcasecmp (xsft->progclass, "xshadertoy");
+
+  if (!shader_p) {
+    // Normal saver: use the name that came from the function table.
+    progclass2 = [NSString stringWithCString:xsft->progclass
+                                    encoding:NSUTF8StringEncoding];
+  } else {
+    // Shadertoy saver: we are using the "XShaderToy" function table,
+    // so set our progclass back to the real hack name instead.
+    // This path happens on both macOS and iOS.
+    progclass2 = [_title stringByReplacingOccurrencesOfString:@" "
+                                                   withString:@""];
+    xsft->progclass =
+      strdup ([progclass2 cStringUsingEncoding:NSUTF8StringEncoding]);
+  }
+
+  NSString *name = [@"org.jwz.xscreensaver."
+                       stringByAppendingString:progclass2];
   [self setResourcesEnv:name];
   [self loadCustomFonts];
   
@@ -516,7 +553,7 @@ static NSMutableArray *all_saver_views = NULL;
   free (defs);
   // free (opts);  // bah, we need these! #### leak!
   xsft->options = opts;
-  
+
   progname = progclass = xsft->progclass;
 
   next_frame_time = 0;
index 2859048585868bc8ec666c2c32255201a82f9b61..5b61b3022df82be234f4a31e4c0a438218e5b70f 100644 (file)
 \b0 by Jamie Zawinski\
 and many others\
 \
-version 6.13\
-02-Dec-2025\
+version 6.14\
+15-Jan-2026\
 \
 {\field{\*\fldinst{HYPERLINK "https://www.jwz.org/xscreensaver/"}}{\fldrslt \cf2 \ul \ulc2 https://www.jwz.org/xscreensaver/}}\
 \pard\pardeftab720
 \cf0 \
 
-\b To install all 260+ screen savers:\
+\b To install all 270+ screen savers:\
 \pard\pardeftab720\li360
 
 \b0 \cf0 \
index 0c80f00b116dad60cea9d2efeac71afb228a3fae..0ca02cedfc05d1c2c156b98c973137405ecb1667 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2012-2022 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2012-2025 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -23,7 +23,7 @@ require 5;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.14 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.15 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 1;
 
@@ -75,10 +75,20 @@ sub build_h($) {
 
   my %names = ();
 
-  foreach my $var (
-    (values %{ parse_makefile_vars ('../hacks/Makefile.in', 'EXES') }),
-    (values %{ parse_makefile_vars ('../hacks/glx/Makefile.in', 'GL_EXES',
-                                 'SUID_EXES') })) {
+  my @exes =
+    (values %{ parse_makefile_vars ('../hacks/Makefile.in', 'EXES') },
+     values %{ parse_makefile_vars ('../hacks/glx/Makefile.in', 'GL_EXES',
+                                    'SUID_EXES') });
+  my @slexes = values %{ parse_makefile_vars ('../hacks/glx/Makefile.in',
+                                              'GLSL_EXES') };
+  my %slexes;
+  foreach my $var (@slexes) {
+    foreach my $name (split (/\s+/, $var)) {
+      $slexes{$name} = 1;
+    }
+  }
+
+  foreach my $var (@exes, @slexes) {
     $var =~ s/covid19/co____9/gs;
     foreach my $name (split (/\s+/, $var)) {
       if ($name =~ /@/ || $disable{$name}) {
@@ -109,6 +119,7 @@ sub build_h($) {
 
   $body .= "extern struct $suf";
   foreach my $s (@names, 'testx11') {
+    next if ($slexes{$s});
     my $s2 = $s;
     $s2 =~ s/-/_/g;
     $body .= "\n ${s2}_${suf},";
@@ -118,6 +129,7 @@ sub build_h($) {
   sub line($$) {
     my ($s, $suf) = @_;
 
+    next if ($s eq 'xshadertoy');
     my $xml_file = "../hacks/config/$s.xml";
     open (my $in, '<:utf8', $xml_file) || error ("$xml_file: $!");
     local $/ = undef;  # read entire file
@@ -126,6 +138,7 @@ sub build_h($) {
     my ($title) = ($body =~ m@<screensaver[^<>]*?[ \t]_label=\"([^\"]+)\"@m);
     error ("$xml_file: no title") unless $title;
 
+    $s = 'xshadertoy' if ($slexes{$s});
     return "\t@\"${title}\":\t[NSValue valueWithPointer:&${s}_${suf}],\n";
   }
 
index 20fde09732c2dd6a0c9b002fc37f0d0d148f3e67..078f1db775bc3e8e0f586aa488103ba902842a90 100644 (file)
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSMainNibFile</key>
        <string>iSaverRunner</string>
        <key>CFBundleDisplayName</key>
index 229917468d4235de2fe7c29a12a2b52b68d1d292..2ed1b73d363119ec0f3d2fcb819a6b1f99a154ab 100755 (executable)
@@ -25,7 +25,7 @@ REQUIRED_SPACE=260  # MB
 export PATH="/bin:/sbin:/usr/bin:/usr/sbin:$PATH"
 
 function error() {
-  echo "XScreenSaver Installer: Error: $@" >&2
+  echo "XScreenSaver Installer: Error:" "$@" >&2
 
   # Using "System Events" says "No user interaction allowed" on 10.9.
   # But using "SystemUIServer" or "Automator Runner" still seems to work.
@@ -51,9 +51,9 @@ __EOF__
 }
 
 
-if [ x"$DSTVOLUME"    = x ]; then DSTVOLUME="/";              fi
-if [ x"$PACKAGE_PATH" = x ]; then error "PACKAGE_PATH unset"; fi
-if [ x"$HOME"         = x ]; then error "HOME unset";         fi
+if [ -z "$DSTVOLUME"    ]; then DSTVOLUME="/";              fi
+if [ -z "$PACKAGE_PATH" ]; then error "PACKAGE_PATH unset"; fi
+if [ -z "$HOME"         ]; then error "HOME unset";         fi
 
 
 echo "Destination: $DSTVOLUME" >&2
@@ -83,12 +83,12 @@ You can't copy the installer out of the Disk Image!"
 
 free=`df -k "$DSTVOLUME" |
      tail -1 | head -1 | awk '{print $4}'`
-need=$(( $REQUIRED_SPACE * 1024 ))
+need=$(( REQUIRED_SPACE * 1024 ))
 if [ "$free" -lt "$need" ]; then
- free=$(( $free / 1024 ))
+ free=$(( free / 1024 ))
  error "Not enough disk space: $free MB available, $REQUIRED_SPACE MB required."
 else
- free=$(( $free / 1024 ))
+ free=$(( free / 1024 ))
  echo "Free space: $free MB" >&2
 fi
 
@@ -112,7 +112,7 @@ for f in *.{saver,app} "$UPDATER_SRC" ; do
     DST="$DST1"
   fi
 
-  DD="$DST/$f"
+  DD="${DST:?}/$f"
 
   echo "Installing $DD" >&2
   rm -rf "$DD" || error "Unable to delete $DD"
@@ -159,12 +159,12 @@ done
 # would be wiped by the upgrade.
 #
 V=`sw_vers -productVersion`
-V0=`echo $V | sed 's/^\([^.]*\).*/\1/'`
-V1=`echo $V | sed 's/^[^.]*\.\([^.]*\).*$/\1/'`
+V0=`echo "$V" | sed 's/^\([^.]*\).*/\1/'`
+V1=`echo "$V" | sed 's/^[^.]*\.\([^.]*\).*$/\1/'`
 
-if [ "$V0" -ge 11 -o \
-     "$V0" -eq 10 -a "$V1" -ge 15 ] ; then     # If >= 10.15
-  for HOME2 in "$DSTVOLUME/Users/"* ; do       # for each user
+if [ "$V0" -ge 11 ] ||
+   ( [ "$V0" -eq 10 ] && [ "$V1" -ge 15 ] ) ; then     # If >= 10.15
+  for HOME2 in "$DSTVOLUME/Users/"* ; do               # for each user
 
     CON="$HOME2/Library/Containers"
     LEG="$CON/com.apple.ScreenSaver.Engine.legacyScreenSaver"
@@ -193,8 +193,8 @@ fi
 pid=`ps -Ac -o pid,comm | grep legacyScreenSaver | \
      sed -e 's/^ *//' -e 's/ .*//'`
 if [ ! -z "$pid" ]; then
-  kill $pid   # Sometimes it will not die.
-  ( sleep 5 ; kill -9 $pid ) &
+  kill "$pid"   # Sometimes it will not die.
+  ( sleep 5 ; kill -9 "$pid" ) &
 fi
 
 
@@ -215,7 +215,7 @@ sleep 5
 pid=`ps -Ac -o pid,comm | grep 'System Settings' | \
      sed -e 's/^ *//' -e 's/ .*//'`
 if [ ! -z "$pid" ]; then
-  kill $pid
+  kill "$pid"
 fi
 
 
index 716b91062b2da21fb289d04dc058aa0a54fa9fa8..76493d3a9ffe19c215618f81451ba526b0c78a88 100644 (file)
@@ -1,5 +1,5 @@
 /* Generated file, do not edit.
-   Created: Sun Apr 27 13:13:54 2025 by build-fntable.pl 1.14.
+   Created: Sat Jan 10 19:40:32 2026 by build-fntable.pl 1.15.
  */
 
 #import <Foundation/Foundation.h>
@@ -256,6 +256,7 @@ extern struct xscreensaver_function_table
  xlyap_xscreensaver_function_table,
  xmatrix_xscreensaver_function_table,
  xrayswarm_xscreensaver_function_table,
+ xshadertoy_xscreensaver_function_table,
  xspirograph_xscreensaver_function_table,
  zoom_xscreensaver_function_table,
  testx11_xscreensaver_function_table;
@@ -270,6 +271,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Test X11":    [NSValue valueWithPointer:&testx11_xscreensaver_function_table],
 #else
        @"Abstractile": [NSValue valueWithPointer:&abstractile_xscreensaver_function_table],
+       @"Alien Beacon":        [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Anemone":     [NSValue valueWithPointer:&anemone_xscreensaver_function_table],
        @"Anemotaxis":  [NSValue valueWithPointer:&anemotaxis_xscreensaver_function_table],
        @"Ant Inspect": [NSValue valueWithPointer:&antinspect_xscreensaver_function_table],
@@ -281,6 +283,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Attraction":  [NSValue valueWithPointer:&attraction_xscreensaver_function_table],
        @"Atunnel":     [NSValue valueWithPointer:&atunnel_xscreensaver_function_table],
        @"Barcode":     [NSValue valueWithPointer:&barcode_xscreensaver_function_table],
+       @"Battered Planet":     [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Beats":       [NSValue valueWithPointer:&beats_xscreensaver_function_table],
        @"Binary Horizon":      [NSValue valueWithPointer:&binaryhorizon_xscreensaver_function_table],
        @"Binary Ring": [NSValue valueWithPointer:&binaryring_xscreensaver_function_table],
@@ -335,6 +338,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Droste":      [NSValue valueWithPointer:&droste_xscreensaver_function_table],
        @"Dumpster Fire":       [NSValue valueWithPointer:&dumpsterfire_xscreensaver_function_table],
        @"Dymaxion Map":        [NSValue valueWithPointer:&dymaxionmap_xscreensaver_function_table],
+       @"Elemental Ring":      [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Endgame":     [NSValue valueWithPointer:&endgame_xscreensaver_function_table],
        @"Energy Stream":       [NSValue valueWithPointer:&energystream_xscreensaver_function_table],
        @"Engine":      [NSValue valueWithPointer:&engine_xscreensaver_function_table],
@@ -353,6 +357,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Flip Text":   [NSValue valueWithPointer:&fliptext_xscreensaver_function_table],
        @"Flow":        [NSValue valueWithPointer:&flow_xscreensaver_function_table],
        @"Fluid Balls": [NSValue valueWithPointer:&fluidballs_xscreensaver_function_table],
+       @"Flux Core":   [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Flying Toasters":     [NSValue valueWithPointer:&flyingtoasters_xscreensaver_function_table],
        @"Font Glide":  [NSValue valueWithPointer:&fontglide_xscreensaver_function_table],
        @"Fuzzy Flakes":        [NSValue valueWithPointer:&fuzzyflakes_xscreensaver_function_table],
@@ -362,6 +367,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Geodesic Gears":      [NSValue valueWithPointer:&geodesicgears_xscreensaver_function_table],
        @"GFlux":       [NSValue valueWithPointer:&gflux_xscreensaver_function_table],
        @"Gibson":      [NSValue valueWithPointer:&gibson_xscreensaver_function_table],
+       @"Gimbal Harmonics":    [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"GL Blur":     [NSValue valueWithPointer:&glblur_xscreensaver_function_table],
        @"GL Cells":    [NSValue valueWithPointer:&glcells_xscreensaver_function_table],
        @"Gleidescope": [NSValue valueWithPointer:&gleidescope_xscreensaver_function_table],
@@ -383,6 +389,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Headroom":    [NSValue valueWithPointer:&headroom_xscreensaver_function_table],
        @"Helix":       [NSValue valueWithPointer:&helix_xscreensaver_function_table],
        @"Hexadrop":    [NSValue valueWithPointer:&hexadrop_xscreensaver_function_table],
+       @"Hex Plasma":  [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Hex Strut":   [NSValue valueWithPointer:&hexstrut_xscreensaver_function_table],
        @"Hex Trail":   [NSValue valueWithPointer:&hextrail_xscreensaver_function_table],
        @"High Voltage":        [NSValue valueWithPointer:&highvoltage_xscreensaver_function_table],
@@ -409,6 +416,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Kumppa":      [NSValue valueWithPointer:&kumppa_xscreensaver_function_table],
        @"Lament":      [NSValue valueWithPointer:&lament_xscreensaver_function_table],
        @"Lavalite":    [NSValue valueWithPointer:&lavalite_xscreensaver_function_table],
+       @"Logarithmic Circles": [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Loop":        [NSValue valueWithPointer:&loop_xscreensaver_function_table],
        @"m6502":       [NSValue valueWithPointer:&m6502_xscreensaver_function_table],
        @"Marbling":    [NSValue valueWithPointer:&marbling_xscreensaver_function_table],
@@ -427,6 +435,8 @@ NSDictionary *make_function_table_dict(void) {
        @"Mountain":    [NSValue valueWithPointer:&mountain_xscreensaver_function_table],
        @"Munch":       [NSValue valueWithPointer:&munch_xscreensaver_function_table],
        @"Nakagin":     [NSValue valueWithPointer:&nakagin_xscreensaver_function_table],
+       @"Neon Gravity":        [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
+       @"Neon Triangulator":   [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Nerve Rot":   [NSValue valueWithPointer:&nerverot_xscreensaver_function_table],
        @"Noof":        [NSValue valueWithPointer:&noof_xscreensaver_function_table],
        @"Nose Guy":    [NSValue valueWithPointer:&noseguy_xscreensaver_function_table],
@@ -449,6 +459,7 @@ NSDictionary *make_function_table_dict(void) {
        @"Pong":        [NSValue valueWithPointer:&pong_xscreensaver_function_table],
        @"Pop Squares": [NSValue valueWithPointer:&popsquares_xscreensaver_function_table],
        @"Projective Plane":    [NSValue valueWithPointer:&projectiveplane_xscreensaver_function_table],
+       @"Protophore":  [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Providence":  [NSValue valueWithPointer:&providence_xscreensaver_function_table],
        @"Pulsar":      [NSValue valueWithPointer:&pulsar_xscreensaver_function_table],
        @"Pyro":        [NSValue valueWithPointer:&pyro_xscreensaver_function_table],
@@ -467,10 +478,12 @@ NSDictionary *make_function_table_dict(void) {
        @"Rubik Blocks":        [NSValue valueWithPointer:&rubikblocks_xscreensaver_function_table],
        @"SBalls":      [NSValue valueWithPointer:&sballs_xscreensaver_function_table],
        @"Scooter":     [NSValue valueWithPointer:&scooter_xscreensaver_function_table],
+       @"Self Reflect":        [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Shade Bobs":  [NSValue valueWithPointer:&shadebobs_xscreensaver_function_table],
        @"Sierpinski":  [NSValue valueWithPointer:&sierpinski_xscreensaver_function_table],
        @"Sierpinski 3D":       [NSValue valueWithPointer:&sierpinski3d_xscreensaver_function_table],
        @"Skulloop":    [NSValue valueWithPointer:&skulloop_xscreensaver_function_table],
+       @"Skyline":     [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Sky Tentacles":       [NSValue valueWithPointer:&skytentacles_xscreensaver_function_table],
        @"Slide Screen":        [NSValue valueWithPointer:&slidescreen_xscreensaver_function_table],
        @"Slip":        [NSValue valueWithPointer:&slip_xscreensaver_function_table],
@@ -485,21 +498,27 @@ NSDictionary *make_function_table_dict(void) {
        @"Squiral":     [NSValue valueWithPointer:&squiral_xscreensaver_function_table],
        @"Squirtorus":  [NSValue valueWithPointer:&squirtorus_xscreensaver_function_table],
        @"Stairs":      [NSValue valueWithPointer:&stairs_xscreensaver_function_table],
+       @"Star Dome":   [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Starfish":    [NSValue valueWithPointer:&starfish_xscreensaver_function_table],
+       @"Star Nest":   [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Star Wars":   [NSValue valueWithPointer:&starwars_xscreensaver_function_table],
        @"Stoner View": [NSValue valueWithPointer:&stonerview_xscreensaver_function_table],
        @"Strange":     [NSValue valueWithPointer:&strange_xscreensaver_function_table],
+       @"Stripey Torus":       [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Substrate":   [NSValue valueWithPointer:&substrate_xscreensaver_function_table],
        @"Superquadrics":       [NSValue valueWithPointer:&superquadrics_xscreensaver_function_table],
        @"Surfaces":    [NSValue valueWithPointer:&surfaces_xscreensaver_function_table],
        @"Swirl":       [NSValue valueWithPointer:&swirl_xscreensaver_function_table],
+       @"Synthwave City":      [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Tangram":     [NSValue valueWithPointer:&tangram_xscreensaver_function_table],
        @"Tessellimage":        [NSValue valueWithPointer:&tessellimage_xscreensaver_function_table],
        @"Time Tunnel": [NSValue valueWithPointer:&timetunnel_xscreensaver_function_table],
        @"Top Block":   [NSValue valueWithPointer:&topblock_xscreensaver_function_table],
+       @"Topologica":  [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Triangle":    [NSValue valueWithPointer:&triangle_xscreensaver_function_table],
        @"Tron Bit":    [NSValue valueWithPointer:&tronbit_xscreensaver_function_table],
        @"Truchet":     [NSValue valueWithPointer:&truchet_xscreensaver_function_table],
+       @"Truchet Zoom":        [NSValue valueWithPointer:&xshadertoy_xscreensaver_function_table],
        @"Twang":       [NSValue valueWithPointer:&twang_xscreensaver_function_table],
        @"Unicrud":     [NSValue valueWithPointer:&unicrud_xscreensaver_function_table],
        @"Unknown Pleasures":   [NSValue valueWithPointer:&unknownpleasures_xscreensaver_function_table],
index bbfc5d3c130f8adbe23b1c3653bf34698bf07e51..8d984dc2382616b3bb2091e03478e5e8f8afea70 100755 (executable)
@@ -1,5 +1,5 @@
 #!/opt/local/bin/perl -w
-# Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2025-2026 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -16,7 +16,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.2 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.03 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -26,6 +26,7 @@ sub minimize($$) {
   my ($in, $out) = @_;
 
   if (!defined($Perl::Tidy::VERSION)) {
+    error ("Perl::Tidy not installed") if ($ENV{USER} eq 'jwz');
     print STDERR "$progname: Perl::Tidy not installed, skipping...\n";
     return;
   }
index 2625c625d13faf6a18952779b215c631e8e5e894..78d6e2e50da32c77837ab4dd29aff0e790600fba 100755 (executable)
Binary files a/OSX/sparkle-bin/BinaryDelta and b/OSX/sparkle-bin/BinaryDelta differ
index 8284108d0cec97250cc9d667977e5e1018b76a82..a2c5dfae716b761556b92624754aa939dce3263f 100755 (executable)
Binary files a/OSX/sparkle-bin/generate_appcast and b/OSX/sparkle-bin/generate_appcast differ
index 4d776af1ce703242d168b7a6440191c2b19a9b2a..23f769a22460cdcd55cae65eaef51367fd2d39e0 100755 (executable)
Binary files a/OSX/sparkle-bin/generate_keys and b/OSX/sparkle-bin/generate_keys differ
index 90bd66bdda4ad56ab87b0c81dce5954ecb67cd4a..9476059a547b31c490d96263876e65651d46bb01 100755 (executable)
Binary files a/OSX/sparkle-bin/sign_update and b/OSX/sparkle-bin/sign_update differ
index 14cbc742c1755be3b7bf51644a3edab2074bcfe9..66d47fb0ed0233e0c20378b89f8136c9b6f0b7c4 100644 (file)
        <key>CFBundleSignature</key>
        <string>????</string>
        <key>CFBundleVersion</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>LSApplicationCategoryType</key>
        <string>public.app-category.entertainment</string>
        <key>CFBundleShortVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleLongVersionString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleGetInfoString</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>NSHumanReadableCopyright</key>
-       <string>6.13</string>
+       <string>6.14</string>
        <key>CFBundleDisplayName</key>
        <string>${PRODUCT_NAME}</string>
        <key>CFBundleIcons</key>
index b8e09ef74434bbdbde856f7b01aa0af5f61572be..3f612b5e410b05ebaab8adde3ab3bfb9a5406818 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2006-2025 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2006-2026 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -27,7 +27,7 @@ use IO::Compress::Gzip qw(gzip $GzipError);
 
 my ($exec_dir, $progname) = ($0 =~ m@^(.*?)/([^/]+)$@);
 
-my ($version) = ('$Revision: 1.60 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.62 $' =~ m/\s(\d[.\d]+)\s/s);
 
 $ENV{PATH} = "/usr/local/bin:$ENV{PATH}";   # for seticon
 $ENV{PATH} = "/opt/local/bin:$ENV{PATH}";   # for macports wget
@@ -306,6 +306,19 @@ sub compress_all_xml_files($) {
 }
 
 
+sub safe_system(@) {
+  my (@cmd) = @_;
+  print STDERR "$progname: exec: " . join(' ', @cmd) . "\n" if ($verbose > 1);
+  system @cmd;
+  my $exit_value  = $? >> 8;
+  my $signal_num  = $? & 127;
+  my $dumped_core = $? & 128;
+  error ("$cmd[0]: core dumped!") if ($dumped_core);
+  error ("$cmd[0]: signal $signal_num!") if ($signal_num);
+  error ("$cmd[0]: exit $exit_value") if ($exit_value);
+  return $exit_value;
+}
+
 sub minimize_scripts($) {
   my ($dir) = @_;
   my $d2 = $dir . '/Contents/Resources';
@@ -319,13 +332,36 @@ sub minimize_scripts($) {
     $f = "$dir/$f";
     next if ($f =~ m/\.(xml|png|jpg|ttf)$/s);
     next if (-d $f);
-    next unless (-x $f);       # Assume executable files are Perl scripts
-    my @cmd = "$exec_dir/perl-minimize.pl";
-    push @cmd, '--verbose' if ($verbose > 2);
-    push @cmd, ($f, $f);
-    print STDERR "$progname: exec: " . join(' ', @cmd) . "\n"
-      if ($verbose > 1);
-    system (@cmd);
+    if (-x $f) {       # Assume executable files are Perl scripts
+      my @cmd = "$exec_dir/perl-minimize.pl";
+      push @cmd, '--verbose' if ($verbose > 2);
+      push @cmd, ($f, $f);
+      safe_system (@cmd);
+    } elsif ($f =~ m/\.glsl$/si) {
+      open (my $in, '<:utf8', $f) || error ("$f: $!");
+      my $body = '';
+      local $/ = undef;  # read entire file
+      while (<$in>) { $body .= $_; }
+      close $in;
+      my $obody = $body;
+
+      # Omit comments in shaders.
+      $body =~ s@//[^\n]*@@gs;
+      $body =~ s@/\*.*?\*/@@gs;
+      $body =~ s/^[ \t]+|[ \t]+$//gm;
+      $body =~ s/\n\n+/\n/gs;
+      $body =~ s/^\s+|\s+$//gs;
+      $body .= "\n";
+
+      if ($body eq $obody) {
+        print STDERR "$progname: $f unchanged\n" if ($verbose > 2);
+      } else {
+        open (my $out, '>:utf8', $f);
+        print $out $body;
+        close $out;
+        print STDERR "$progname: stripped $f\n" if ($verbose);
+      }
+    }
   }
 }
 
index 3af125cbf300d0726932f00da06f6234d155069d..232a526658dbe2cc9ff90726718161041a89adef 100644 (file)
@@ -7,10 +7,21 @@
   <link>https://www.jwz.org/xscreensaver/updates.xml</link>
   <description>Updates to xscreensaver.</description>
   <language>en</language>
+  <item>
+   <title>Version 6.14</title>
+   <link>https://www.jwz.org/xscreensaver/xscreensaver-6.14.dmg</link>
+   <description><![CDATA[&bull; Added the ability to run shadertoy.com programs as screen savers. <BR>&bull; New shader-based savers: `alienbeacon', `batteredplanet', `elementalring', `fluxcore', `gimbalharmonics', `hexplasma', `logarithmiccircles', `neongravity', `neontriangulator', `protophore', `selfreflect', `skyline', `stardome', `starnest', `stripeytorus', `synthwavecity', `topologica' and `truchetzoom'. <BR>&bull; Better label wrapping in `carousel' and `photopile'. <BR>&bull; Fixed `glslideshow' preferences and title display. <BR>&bull; Sparkle 2.8. ]]></description>
+   <pubDate>Thu, 15 Jan 2026 14:28:13 -0800</pubDate>
+   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-6.14.dmg"
+    sparkle:version="6.14"
+    sparkle:edSignature="Ma7AhSeRvs+zcku/MrDDadXyb3ocHjUqISHr1TIzqid7keI06j7EycT+/885K9Bu/9DkLIDQZRBG4BX5IeUVAQ=="
+    length="107466525"
+    type="application/octet-stream" />
+  </item>
   <item>
    <title>Version 6.13</title>
    <link>https://www.jwz.org/xscreensaver/xscreensaver-6.13.dmg</link>
-   <description><![CDATA[&bull; Added a number of historical full chess games to `endgame`. <BR>&bull; Rewrote `glslideshow' to add more image-transition effects. <BR>&bull; Hacks that display images and their filenames will display their titles intead, if the image originated in an RSS feed (or has the "user.dublincore.title" xattr). ]]></description>
+   <description><![CDATA[&bull; Added a number of historical full chess games to `endgame'. <BR>&bull; Rewrote `glslideshow' to add more image-transition effects. <BR>&bull; Hacks that display images and their filenames will display their titles intead, if the image originated in an RSS feed (or has the "user.dublincore.title" xattr). ]]></description>
    <pubDate>Tue, 02 Dec 2025 17:09:25 -0800</pubDate>
    <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-6.13.dmg"
     sparkle:version="6.13"
     length="102575147"
     type="application/octet-stream" />
   </item>
-  <item>
-   <title>Version 6.09</title>
-   <link>https://www.jwz.org/xscreensaver/xscreensaver-6.09.dmg</link>
-   <description><![CDATA[&bull; New hacks,`kallisti' and `highvoltage'. <BR>&bull; Formal-wear for `headroom'.]]></description>
-   <pubDate>Fri, 07 Jun 2024 22:00:40 -0700</pubDate>
-   <enclosure url="https://www.jwz.org/xscreensaver/xscreensaver-6.09.dmg"
-    sparkle:version="6.09"
-    sparkle:edSignature="R83Wet7kF1AW9R9KihrZq0cbDnjFL8QF5wtEnK/6Adt7jPtUGCTXcpoFiCvxx3yKOuY+1FZ3pV87X6AQ4rQ8BA=="
-    length="90634351"
-    type="application/octet-stream" />
-  </item>
  </channel>
 </rss>
index 17bcfed70de70f19d5dbc757e99743563fc595af..0b5eaa78a9cb407c56576c3aadcec34f1c8b95ba 100644 (file)
                                AF480D60098EED6900FB32B8 /* PBXTargetDependency */,
                                AF480D5E098EED6900FB32B8 /* PBXTargetDependency */,
                                AF480D5C098EED6900FB32B8 /* PBXTargetDependency */,
+                               AF98C07F2F00604D00484F29 /* PBXTargetDependency */,
                                AF137D470F075CC8004DE3B2 /* PBXTargetDependency */,
                        );
                        name = "All Savers";
                        productName = "All Savers";
                };
+               AF98C0782F00600400484F29 /* All Savers (Shadertoy) */ = {
+                       isa = PBXAggregateTarget;
+                       buildConfigurationList = AF98C0792F00600400484F29 /* Build configuration list for PBXAggregateTarget "All Savers (Shadertoy)" */;
+                       buildPhases = (
+                       );
+                       dependencies = (
+                               AFAF12B32F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12B52F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12B72F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12B92F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12BB2F134EFB00449DD7 /* PBXTargetDependency */,
+                               AF98C0C32F00F37B00484F29 /* PBXTargetDependency */,
+                               AFAF12BD2F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12BF2F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12C12F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12C32F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12C52F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12C72F134EFB00449DD7 /* PBXTargetDependency */,
+                               AF98C0E62F01C57D00484F29 /* PBXTargetDependency */,
+                               AF98C0C52F00F38500484F29 /* PBXTargetDependency */,
+                               AFAF12C92F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12CB2F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12CD2F134EFB00449DD7 /* PBXTargetDependency */,
+                               AFAF12CF2F134EFB00449DD7 /* PBXTargetDependency */,
+                               AF98C07D2F00601700484F29 /* PBXTargetDependency */,
+                       );
+                       name = "All Savers (Shadertoy)";
+                       packageProductDependencies = (
+                       );
+                       productName = "All Savers (Shadertoy)";
+               };
                AFA33C020B058E17002B0E7D /* webcollage-perl */ = {
                        isa = PBXAggregateTarget;
                        buildConfigurationList = AFA33C070B058E67002B0E7D /* Build configuration list for PBXAggregateTarget "webcollage-perl" */;
                AF5D4E3D2D6409AE009BE57E /* ansi-tty.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5D4E3B2D6409AE009BE57E /* ansi-tty.c */; };
                AF5D4E3E2D6409AE009BE57E /* ansi-tty.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5D4E3B2D6409AE009BE57E /* ansi-tty.c */; };
                AF5D4E3F2D6409AE009BE57E /* ansi-tty.c in Sources */ = {isa = PBXBuildFile; fileRef = AF5D4E3B2D6409AE009BE57E /* ansi-tty.c */; };
+               AF5E58782EFDE9750056DEDC /* xftwrap.c in Sources */ = {isa = PBXBuildFile; fileRef = AFBD953C2C504ADC000DA52A /* xftwrap.c */; };
+               AF5E58792EFDE99D0056DEDC /* xftwrap.c in Sources */ = {isa = PBXBuildFile; fileRef = AFBD953C2C504ADC000DA52A /* xftwrap.c */; };
                AF5ECEB02116B1A400069433 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF5ECEB12116B1A400069433 /* analogtv.c in Sources */ = {isa = PBXBuildFile; fileRef = AF9D4CFA09B5AC94006E59CF /* analogtv.c */; };
                AF5ECEB42116B1A400069433 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AF9771DF0989DC88001F8B92 /* SaverRunner.m in Sources */ = {isa = PBXBuildFile; fileRef = AFE1FD400981E32E00F7970E /* SaverRunner.m */; };
                AF9772C80989DCD5001F8B92 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
                AF9772E30989DFC6001F8B92 /* SaverRunner.nib in Resources */ = {isa = PBXBuildFile; fileRef = AF9772E10989DFC6001F8B92 /* SaverRunner.nib */; };
+               AF98C05F2F005F6000484F29 /* starnest.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C05E2F005F6000484F29 /* starnest.glsl */; };
+               AF98C0602F005F6000484F29 /* starnest.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C05E2F005F6000484F29 /* starnest.glsl */; };
+               AF98C0612F005F6000484F29 /* starnest.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C05E2F005F6000484F29 /* starnest.glsl */; };
+               AF98C0692F005FB900484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C06B2F005FB900484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C06C2F005FB900484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C06D2F005FB900484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C06E2F005FB900484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C06F2F005FB900484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C0702F005FB900484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C0712F005FB900484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C0832F00615700484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF98C0842F00615700484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C0862F00615700484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; settings = {COMPILER_FLAGS = "-DUSE_GL"; }; };
+               AF98C08E2F00644500484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C08F2F00644500484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C0912F00644500484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C0922F00644500484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C0932F00644500484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C0942F00644500484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C0952F00644500484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C0962F00644500484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C0972F00644500484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C09E2F00653B00484F29 /* starnest.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C05E2F005F6000484F29 /* starnest.glsl */; };
+               AF98C0A02F00657700484F29 /* starnest.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C09F2F00657700484F29 /* starnest.xml */; };
+               AF98C0A12F00657700484F29 /* starnest.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C09F2F00657700484F29 /* starnest.xml */; };
+               AF98C0A22F00657700484F29 /* starnest.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C09F2F00657700484F29 /* starnest.xml */; };
+               AF98C0AA2F00F1FA00484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C0AB2F00F1FA00484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C0AD2F00F1FA00484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C0AE2F00F1FA00484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C0AF2F00F1FA00484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C0B02F00F1FA00484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C0B12F00F1FA00484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C0B22F00F1FA00484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C0B32F00F1FA00484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C0BC2F00F25F00484F29 /* hexplasma.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0BB2F00F25F00484F29 /* hexplasma.xml */; };
+               AF98C0BD2F00F25F00484F29 /* hexplasma.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0BA2F00F25F00484F29 /* hexplasma.glsl */; };
+               AF98C0BE2F00F25F00484F29 /* hexplasma.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0BB2F00F25F00484F29 /* hexplasma.xml */; };
+               AF98C0BF2F00F25F00484F29 /* hexplasma.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0BA2F00F25F00484F29 /* hexplasma.glsl */; };
+               AF98C0C02F00F25F00484F29 /* hexplasma.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0BB2F00F25F00484F29 /* hexplasma.xml */; };
+               AF98C0C12F00F25F00484F29 /* hexplasma.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0BA2F00F25F00484F29 /* hexplasma.glsl */; };
+               AF98C0CD2F01C3E500484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C0CE2F01C3E500484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C0D02F01C3E500484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C0D12F01C3E500484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C0D22F01C3E500484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C0D32F01C3E500484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C0D42F01C3E500484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C0D52F01C3E500484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C0D62F01C3E500484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C0DF2F01C47B00484F29 /* stardome.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0DE2F01C47B00484F29 /* stardome.xml */; };
+               AF98C0E02F01C47B00484F29 /* stardome.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0DD2F01C47B00484F29 /* stardome.glsl */; };
+               AF98C0E12F01C47B00484F29 /* stardome.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0DE2F01C47B00484F29 /* stardome.xml */; };
+               AF98C0E22F01C47B00484F29 /* stardome.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0DD2F01C47B00484F29 /* stardome.glsl */; };
+               AF98C0E32F01C47B00484F29 /* stardome.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0DE2F01C47B00484F29 /* stardome.xml */; };
+               AF98C0E42F01C47B00484F29 /* stardome.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0DD2F01C47B00484F29 /* stardome.glsl */; };
+               AF98C0EE2F01F4AC00484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C0EF2F01F4AC00484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C0F12F01F4AC00484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C0F22F01F4AC00484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C0F32F01F4AC00484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C0F42F01F4AC00484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C0F52F01F4AC00484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C0F62F01F4AC00484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C0F72F01F4AC00484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C1002F01F4FE00484F29 /* stripeytorus.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0FE2F01F4FE00484F29 /* stripeytorus.glsl */; };
+               AF98C1012F01F4FE00484F29 /* stripeytorus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0FF2F01F4FE00484F29 /* stripeytorus.xml */; };
+               AF98C1022F01F4FE00484F29 /* stripeytorus.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0FE2F01F4FE00484F29 /* stripeytorus.glsl */; };
+               AF98C1032F01F4FE00484F29 /* stripeytorus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0FF2F01F4FE00484F29 /* stripeytorus.xml */; };
+               AF98C1042F01F4FE00484F29 /* stripeytorus.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0FE2F01F4FE00484F29 /* stripeytorus.glsl */; };
+               AF98C1052F01F4FE00484F29 /* stripeytorus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C0FF2F01F4FE00484F29 /* stripeytorus.xml */; };
+               AF98C10D2F01F70E00484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C10E2F01F70E00484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C1102F01F70E00484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C1112F01F70E00484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C1122F01F70E00484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C1132F01F70E00484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C1142F01F70E00484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C1152F01F70E00484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C1162F01F70E00484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C11F2F01F7CF00484F29 /* truchetzoom.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C11E2F01F7CF00484F29 /* truchetzoom.xml */; };
+               AF98C1202F01F7CF00484F29 /* truchetzoom.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C11D2F01F7CF00484F29 /* truchetzoom.glsl */; };
+               AF98C1212F01F7CF00484F29 /* truchetzoom.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C11E2F01F7CF00484F29 /* truchetzoom.xml */; };
+               AF98C1222F01F7CF00484F29 /* truchetzoom.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C11D2F01F7CF00484F29 /* truchetzoom.glsl */; };
+               AF98C1232F01F7CF00484F29 /* truchetzoom.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C11E2F01F7CF00484F29 /* truchetzoom.xml */; };
+               AF98C1242F01F7CF00484F29 /* truchetzoom.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C11D2F01F7CF00484F29 /* truchetzoom.glsl */; };
+               AF98C12C2F01FA7A00484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C12D2F01FA7A00484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C12F2F01FA7A00484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C1302F01FA7A00484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C1312F01FA7A00484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C1322F01FA7A00484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C1332F01FA7A00484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C1342F01FA7A00484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C1352F01FA7A00484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C13E2F01FB1D00484F29 /* neontriangulator.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C13C2F01FB1D00484F29 /* neontriangulator.glsl */; };
+               AF98C13F2F01FB1D00484F29 /* neontriangulator.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C13D2F01FB1D00484F29 /* neontriangulator.xml */; };
+               AF98C1402F01FB1D00484F29 /* neontriangulator.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C13C2F01FB1D00484F29 /* neontriangulator.glsl */; };
+               AF98C1412F01FB1D00484F29 /* neontriangulator.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C13D2F01FB1D00484F29 /* neontriangulator.xml */; };
+               AF98C1422F01FB1D00484F29 /* neontriangulator.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C13C2F01FB1D00484F29 /* neontriangulator.glsl */; };
+               AF98C1432F01FB1D00484F29 /* neontriangulator.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C13D2F01FB1D00484F29 /* neontriangulator.xml */; };
+               AF98C14B2F01FE8800484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C14C2F01FE8800484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C14E2F01FE8800484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C14F2F01FE8800484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C1502F01FE8800484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C1512F01FE8800484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C1522F01FE8800484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C1532F01FE8800484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C1542F01FE8800484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C15D2F01FED800484F29 /* synthwavecity.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C15B2F01FED800484F29 /* synthwavecity.glsl */; };
+               AF98C15E2F01FED800484F29 /* synthwavecity.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C15C2F01FED800484F29 /* synthwavecity.xml */; };
+               AF98C15F2F01FED800484F29 /* synthwavecity.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C15B2F01FED800484F29 /* synthwavecity.glsl */; };
+               AF98C1602F01FED800484F29 /* synthwavecity.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C15C2F01FED800484F29 /* synthwavecity.xml */; };
+               AF98C1612F01FED800484F29 /* synthwavecity.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C15B2F01FED800484F29 /* synthwavecity.glsl */; };
+               AF98C1622F01FED800484F29 /* synthwavecity.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C15C2F01FED800484F29 /* synthwavecity.xml */; };
+               AF98C16A2F02023600484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C16B2F02023600484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C16D2F02023600484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C16E2F02023600484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C16F2F02023600484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C1702F02023600484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C1712F02023600484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C1722F02023600484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C1732F02023600484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C17C2F02028E00484F29 /* logarithmiccircles.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C17A2F02028E00484F29 /* logarithmiccircles.glsl */; };
+               AF98C17D2F02028E00484F29 /* logarithmiccircles.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C17B2F02028E00484F29 /* logarithmiccircles.xml */; };
+               AF98C17E2F02028E00484F29 /* logarithmiccircles.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C17A2F02028E00484F29 /* logarithmiccircles.glsl */; };
+               AF98C17F2F02028E00484F29 /* logarithmiccircles.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C17B2F02028E00484F29 /* logarithmiccircles.xml */; };
+               AF98C1802F02028E00484F29 /* logarithmiccircles.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C17A2F02028E00484F29 /* logarithmiccircles.glsl */; };
+               AF98C1812F02028E00484F29 /* logarithmiccircles.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C17B2F02028E00484F29 /* logarithmiccircles.xml */; };
+               AF98C1892F02063500484F29 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AF98C18A2F02063500484F29 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AF98C18C2F02063500484F29 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AF98C18D2F02063500484F29 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AF98C18E2F02063500484F29 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AF98C18F2F02063500484F29 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AF98C1902F02063500484F29 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AF98C1912F02063500484F29 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AF98C1922F02063500484F29 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AF98C19C2F02067500484F29 /* neongravity-1.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C19B2F02067500484F29 /* neongravity-1.glsl */; };
+               AF98C19D2F02067500484F29 /* neongravity-0.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C19A2F02067500484F29 /* neongravity-0.glsl */; };
+               AF98C19E2F02067500484F29 /* neongravity.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C1992F02067500484F29 /* neongravity.xml */; };
+               AF98C19F2F02067500484F29 /* neongravity-1.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C19B2F02067500484F29 /* neongravity-1.glsl */; };
+               AF98C1A02F02067500484F29 /* neongravity-0.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C19A2F02067500484F29 /* neongravity-0.glsl */; };
+               AF98C1A12F02067500484F29 /* neongravity.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C1992F02067500484F29 /* neongravity.xml */; };
+               AF98C1A22F02067500484F29 /* neongravity-1.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C19B2F02067500484F29 /* neongravity-1.glsl */; };
+               AF98C1A32F02067500484F29 /* neongravity-0.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AF98C19A2F02067500484F29 /* neongravity-0.glsl */; };
+               AF98C1A42F02067500484F29 /* neongravity.xml in Resources */ = {isa = PBXBuildFile; fileRef = AF98C1992F02067500484F29 /* neongravity.xml */; };
                AF998ED60A083A280051049D /* xscreensaver-text in Resources */ = {isa = PBXBuildFile; fileRef = AF0FAF0B09CA6FF900EE1051 /* xscreensaver-text */; };
                AF998EE10A083DB30051049D /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AF998EF90A083E750051049D /* topblock.c in Sources */ = {isa = PBXBuildFile; fileRef = AF998EF80A083E750051049D /* topblock.c */; };
                AFAE148B279276BC00C62683 /* squirtorus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAE1487279276BC00C62683 /* squirtorus.xml */; };
                AFAE148C279276BC00C62683 /* squirtorus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAE1487279276BC00C62683 /* squirtorus.xml */; };
                AFAE148D279276BC00C62683 /* squirtorus.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAE1487279276BC00C62683 /* squirtorus.xml */; };
+               AFAF11A02F13446500449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF11A12F13446500449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF11A32F13446500449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF11A42F13446500449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF11A52F13446500449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF11A62F13446500449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF11A72F13446500449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF11A82F13446500449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF11A92F13446500449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF11B22F13453300449DD7 /* alienbeacon.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11B02F13453300449DD7 /* alienbeacon.glsl */; };
+               AFAF11B32F13453300449DD7 /* alienbeacon.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11B12F13453300449DD7 /* alienbeacon.xml */; };
+               AFAF11B42F13453300449DD7 /* alienbeacon.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11B02F13453300449DD7 /* alienbeacon.glsl */; };
+               AFAF11B52F13453300449DD7 /* alienbeacon.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11B12F13453300449DD7 /* alienbeacon.xml */; };
+               AFAF11B62F13453300449DD7 /* alienbeacon.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11B02F13453300449DD7 /* alienbeacon.glsl */; };
+               AFAF11B72F13453300449DD7 /* alienbeacon.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11B12F13453300449DD7 /* alienbeacon.xml */; };
+               AFAF11BF2F13459500449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF11C02F13459500449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF11C22F13459500449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF11C32F13459500449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF11C42F13459500449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF11C52F13459500449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF11C62F13459500449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF11C72F13459500449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF11C82F13459500449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF11D12F13461A00449DD7 /* batteredplanet.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11CF2F13461A00449DD7 /* batteredplanet.glsl */; };
+               AFAF11D22F13461A00449DD7 /* batteredplanet.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11D02F13461A00449DD7 /* batteredplanet.xml */; };
+               AFAF11D32F13461A00449DD7 /* batteredplanet.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11CF2F13461A00449DD7 /* batteredplanet.glsl */; };
+               AFAF11D42F13461A00449DD7 /* batteredplanet.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11D02F13461A00449DD7 /* batteredplanet.xml */; };
+               AFAF11D52F13461A00449DD7 /* batteredplanet.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11CF2F13461A00449DD7 /* batteredplanet.glsl */; };
+               AFAF11D62F13461A00449DD7 /* batteredplanet.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11D02F13461A00449DD7 /* batteredplanet.xml */; };
+               AFAF11DE2F1346CE00449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF11DF2F1346CE00449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF11E12F1346CE00449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF11E22F1346CE00449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF11E32F1346CE00449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF11E42F1346CE00449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF11E52F1346CE00449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF11E62F1346CE00449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF11E72F1346CE00449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF11F02F13473C00449DD7 /* elementalring.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11EE2F13473C00449DD7 /* elementalring.glsl */; };
+               AFAF11F12F13473C00449DD7 /* elementalring.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11EF2F13473C00449DD7 /* elementalring.xml */; };
+               AFAF11F22F13473C00449DD7 /* elementalring.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11EE2F13473C00449DD7 /* elementalring.glsl */; };
+               AFAF11F32F13473C00449DD7 /* elementalring.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11EF2F13473C00449DD7 /* elementalring.xml */; };
+               AFAF11F42F13473C00449DD7 /* elementalring.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11EE2F13473C00449DD7 /* elementalring.glsl */; };
+               AFAF11F52F13473C00449DD7 /* elementalring.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF11EF2F13473C00449DD7 /* elementalring.xml */; };
+               AFAF11FD2F13477F00449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF11FE2F13477F00449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF12002F13477F00449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF12012F13477F00449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF12022F13477F00449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF12032F13477F00449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF12042F13477F00449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF12052F13477F00449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF12062F13477F00449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF120F2F13483D00449DD7 /* fluxcore.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF120E2F13483D00449DD7 /* fluxcore.xml */; };
+               AFAF12102F13483D00449DD7 /* fluxcore.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF120D2F13483D00449DD7 /* fluxcore.glsl */; };
+               AFAF12112F13483D00449DD7 /* fluxcore.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF120E2F13483D00449DD7 /* fluxcore.xml */; };
+               AFAF12122F13483D00449DD7 /* fluxcore.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF120D2F13483D00449DD7 /* fluxcore.glsl */; };
+               AFAF12132F13483D00449DD7 /* fluxcore.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF120E2F13483D00449DD7 /* fluxcore.xml */; };
+               AFAF12142F13483D00449DD7 /* fluxcore.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF120D2F13483D00449DD7 /* fluxcore.glsl */; };
+               AFAF121C2F13487300449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF121D2F13487300449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF121F2F13487300449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF12202F13487300449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF12212F13487300449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF12222F13487300449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF12232F13487300449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF12242F13487300449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF12252F13487300449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF122E2F1348EA00449DD7 /* gimbalharmonics.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF122C2F1348EA00449DD7 /* gimbalharmonics.glsl */; };
+               AFAF122F2F1348EA00449DD7 /* gimbalharmonics.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF122D2F1348EA00449DD7 /* gimbalharmonics.xml */; };
+               AFAF12302F1348EA00449DD7 /* gimbalharmonics.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF122C2F1348EA00449DD7 /* gimbalharmonics.glsl */; };
+               AFAF12312F1348EA00449DD7 /* gimbalharmonics.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF122D2F1348EA00449DD7 /* gimbalharmonics.xml */; };
+               AFAF12322F1348EA00449DD7 /* gimbalharmonics.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF122C2F1348EA00449DD7 /* gimbalharmonics.glsl */; };
+               AFAF12332F1348EA00449DD7 /* gimbalharmonics.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF122D2F1348EA00449DD7 /* gimbalharmonics.xml */; };
+               AFAF123B2F13495300449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF123C2F13495300449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF123E2F13495300449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF123F2F13495300449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF12402F13495300449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF12412F13495300449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF12422F13495300449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF12432F13495300449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF12442F13495300449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF124D2F1349BF00449DD7 /* protophore.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF124B2F1349BF00449DD7 /* protophore.glsl */; };
+               AFAF124E2F1349BF00449DD7 /* protophore.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF124C2F1349BF00449DD7 /* protophore.xml */; };
+               AFAF124F2F1349BF00449DD7 /* protophore.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF124B2F1349BF00449DD7 /* protophore.glsl */; };
+               AFAF12502F1349BF00449DD7 /* protophore.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF124C2F1349BF00449DD7 /* protophore.xml */; };
+               AFAF12512F1349BF00449DD7 /* protophore.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF124B2F1349BF00449DD7 /* protophore.glsl */; };
+               AFAF12522F1349BF00449DD7 /* protophore.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF124C2F1349BF00449DD7 /* protophore.xml */; };
+               AFAF125A2F134AA800449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF125B2F134AA800449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF125D2F134AA800449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF125E2F134AA800449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF125F2F134AA800449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF12602F134AA800449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF12612F134AA800449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF12622F134AA800449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF12632F134AA800449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF126C2F134B2200449DD7 /* selfreflect.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF126B2F134B2200449DD7 /* selfreflect.xml */; };
+               AFAF126D2F134B2200449DD7 /* selfreflect.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF126A2F134B2200449DD7 /* selfreflect.glsl */; };
+               AFAF126E2F134B2200449DD7 /* selfreflect.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF126B2F134B2200449DD7 /* selfreflect.xml */; };
+               AFAF126F2F134B2200449DD7 /* selfreflect.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF126A2F134B2200449DD7 /* selfreflect.glsl */; };
+               AFAF12702F134B2200449DD7 /* selfreflect.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF126B2F134B2200449DD7 /* selfreflect.xml */; };
+               AFAF12712F134B2200449DD7 /* selfreflect.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF126A2F134B2200449DD7 /* selfreflect.glsl */; };
+               AFAF12792F134B8800449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF127A2F134B8800449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF127C2F134B8800449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF127D2F134B8800449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF127E2F134B8800449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF127F2F134B8800449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF12802F134B8800449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF12812F134B8800449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF12822F134B8800449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF128B2F134BE500449DD7 /* skyline.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12892F134BE500449DD7 /* skyline.glsl */; };
+               AFAF128C2F134BE500449DD7 /* skyline.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF128A2F134BE500449DD7 /* skyline.xml */; };
+               AFAF128D2F134BE500449DD7 /* skyline.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12892F134BE500449DD7 /* skyline.glsl */; };
+               AFAF128E2F134BE500449DD7 /* skyline.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF128A2F134BE500449DD7 /* skyline.xml */; };
+               AFAF128F2F134BE500449DD7 /* skyline.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12892F134BE500449DD7 /* skyline.glsl */; };
+               AFAF12902F134BE500449DD7 /* skyline.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF128A2F134BE500449DD7 /* skyline.xml */; };
+               AFAF129A2F134D8100449DD7 /* xshadertoy.c in Sources */ = {isa = PBXBuildFile; fileRef = AF98C0802F00615700484F29 /* xshadertoy.c */; };
+               AFAF129B2F134D8100449DD7 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
+               AFAF129D2F134D8100449DD7 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
+               AFAF129E2F134D8100449DD7 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
+               AFAF129F2F134D8100449DD7 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF2C31E515C0F7FE007A6896 /* QuartzCore.framework */; };
+               AFAF12A02F134D8100449DD7 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; };
+               AFAF12A12F134D8100449DD7 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF48112B0990A2C700FB32B8 /* Carbon.framework */; };
+               AFAF12A22F134D8100449DD7 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEE0BC611A6B0D6200C098BF /* OpenGL.framework */; };
+               AFAF12A32F134D8100449DD7 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = AF78369617DB9F25003B9FC0 /* libz.dylib */; };
+               AFAF12AC2F134E1A00449DD7 /* topologica.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12AA2F134E1A00449DD7 /* topologica.glsl */; };
+               AFAF12AD2F134E1A00449DD7 /* topologica.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12AB2F134E1A00449DD7 /* topologica.xml */; };
+               AFAF12AE2F134E1A00449DD7 /* topologica.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12AA2F134E1A00449DD7 /* topologica.glsl */; };
+               AFAF12AF2F134E1A00449DD7 /* topologica.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12AB2F134E1A00449DD7 /* topologica.xml */; };
+               AFAF12B02F134E1A00449DD7 /* topologica.glsl in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12AA2F134E1A00449DD7 /* topologica.glsl */; };
+               AFAF12B12F134E1A00449DD7 /* topologica.xml in Resources */ = {isa = PBXBuildFile; fileRef = AFAF12AB2F134E1A00449DD7 /* topologica.xml */; };
                AFB591AE178B812C00EA4005 /* XScreenSaverSubclass.m in Sources */ = {isa = PBXBuildFile; fileRef = AF9CC7A0099580E70075E99B /* XScreenSaverSubclass.m */; };
                AFB591B0178B812C00EA4005 /* libjwxyz.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AF4808C1098C3B6C00FB32B8 /* libjwxyz.a */; };
                AFB591B1178B812C00EA4005 /* ScreenSaver.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AF976ED30989BF59001F8B92 /* ScreenSaver.framework */; };
                        remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
                        remoteInfo = jwxyz;
                };
+               AF98C0642F005FB900484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C07C2F00601700484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C0622F005FB900484F29;
+                       remoteInfo = XShadertoy;
+               };
+               AF98C07E2F00604D00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C0782F00600400484F29;
+                       remoteInfo = "All Savers (Shadertoy)";
+               };
+               AF98C08A2F00644500484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C0A52F00F1FA00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C0C22F00F37B00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C0A32F00F1FA00484F29;
+                       remoteInfo = HexPlasma;
+               };
+               AF98C0C42F00F38500484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C0882F00644500484F29;
+                       remoteInfo = StarNest;
+               };
+               AF98C0C82F01C3E500484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C0E52F01C57D00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C0C62F01C3E500484F29;
+                       remoteInfo = StarDome;
+               };
+               AF98C0E92F01F4AC00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C1082F01F70E00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C1272F01FA7A00484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C1462F01FE8800484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C1652F02023600484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AF98C1842F02063500484F29 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
                AF998EDC0A083DB30051049D /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                        remoteGlobalIDString = AFAE146F279275BE00C62683;
                        remoteInfo = Squirtorus;
                };
+               AFAF119B2F13446500449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF11BA2F13459500449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF11D92F1346CE00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF11F82F13477F00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF12172F13487300449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF12362F13495300449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF12552F134AA800449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF12742F134B8800449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF12932F134D8100449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF4808C0098C3B6C00FB32B8;
+                       remoteInfo = jwxyz;
+               };
+               AFAF12B22F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF11992F13446500449DD7;
+                       remoteInfo = AlienBeacon;
+               };
+               AFAF12B42F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF11B82F13459500449DD7;
+                       remoteInfo = BatteredPlanet;
+               };
+               AFAF12B62F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF11D72F1346CE00449DD7;
+                       remoteInfo = ElementalRing;
+               };
+               AFAF12B82F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF11F62F13477F00449DD7;
+                       remoteInfo = FluxCore;
+               };
+               AFAF12BA2F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF12152F13487300449DD7;
+                       remoteInfo = GimbalHarmonics;
+               };
+               AFAF12BC2F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C1632F02023600484F29;
+                       remoteInfo = LogarithmicCircles;
+               };
+               AFAF12BE2F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C1822F02063500484F29;
+                       remoteInfo = NeonGravity;
+               };
+               AFAF12C02F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C1252F01FA7A00484F29;
+                       remoteInfo = NeonTriangulator;
+               };
+               AFAF12C22F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF12342F13495300449DD7;
+                       remoteInfo = Protophore;
+               };
+               AFAF12C42F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF12532F134AA800449DD7;
+                       remoteInfo = SelfReflect;
+               };
+               AFAF12C62F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF12722F134B8800449DD7;
+                       remoteInfo = Skyline;
+               };
+               AFAF12C82F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C0E72F01F4AC00484F29;
+                       remoteInfo = StripeyTorus;
+               };
+               AFAF12CA2F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C1442F01FE8800484F29;
+                       remoteInfo = SynthwaveCity;
+               };
+               AFAF12CC2F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AFAF12912F134D8100449DD7;
+                       remoteInfo = Topologica;
+               };
+               AFAF12CE2F134EFB00449DD7 /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = AF98C1062F01F70E00484F29;
+                       remoteInfo = TruchetZoom;
+               };
                AFB581AF102F363300342B11 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
                AF97707D0989D2F6001F8B92 /* Attraction.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Attraction.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF9771D70989DC4A001F8B92 /* SaverTester.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SaverTester.app; sourceTree = BUILT_PRODUCTS_DIR; };
                AF9771D90989DC4A001F8B92 /* SaverRunner.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = SaverRunner.plist; sourceTree = "<group>"; };
+               AF98C05E2F005F6000484F29 /* starnest.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = starnest.glsl; path = ../hacks/glx/glsl/starnest.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C0762F005FB900484F29 /* XShadertoy.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = XShadertoy.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C0802F00615700484F29 /* xshadertoy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = xshadertoy.c; path = ../hacks/glx/xshadertoy.c; sourceTree = SOURCE_ROOT; };
+               AF98C09C2F00644500484F29 /* StarNest.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StarNest.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C09F2F00657700484F29 /* starnest.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = starnest.xml; sourceTree = "<group>"; };
+               AF98C0B82F00F1FA00484F29 /* HexPlasma.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HexPlasma.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C0BA2F00F25F00484F29 /* hexplasma.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = hexplasma.glsl; path = ../hacks/glx/glsl/hexplasma.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C0BB2F00F25F00484F29 /* hexplasma.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = hexplasma.xml; path = ../hacks/config/hexplasma.xml; sourceTree = SOURCE_ROOT; };
+               AF98C0DB2F01C3E500484F29 /* StarDome.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StarDome.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C0DD2F01C47B00484F29 /* stardome.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = stardome.glsl; path = ../hacks/glx/glsl/stardome.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C0DE2F01C47B00484F29 /* stardome.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = stardome.xml; path = ../hacks/config/stardome.xml; sourceTree = SOURCE_ROOT; };
+               AF98C0FC2F01F4AC00484F29 /* StripeyTorus.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = StripeyTorus.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C0FE2F01F4FE00484F29 /* stripeytorus.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = stripeytorus.glsl; path = ../hacks/glx/glsl/stripeytorus.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C0FF2F01F4FE00484F29 /* stripeytorus.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = stripeytorus.xml; path = ../hacks/config/stripeytorus.xml; sourceTree = SOURCE_ROOT; };
+               AF98C11B2F01F70E00484F29 /* TruchetZoom.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TruchetZoom.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C11D2F01F7CF00484F29 /* truchetzoom.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = truchetzoom.glsl; path = ../hacks/glx/glsl/truchetzoom.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C11E2F01F7CF00484F29 /* truchetzoom.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = truchetzoom.xml; path = ../hacks/config/truchetzoom.xml; sourceTree = SOURCE_ROOT; };
+               AF98C13A2F01FA7A00484F29 /* NeonTriangulator.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NeonTriangulator.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C13C2F01FB1D00484F29 /* neontriangulator.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = neontriangulator.glsl; path = ../hacks/glx/glsl/neontriangulator.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C13D2F01FB1D00484F29 /* neontriangulator.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = neontriangulator.xml; path = ../hacks/config/neontriangulator.xml; sourceTree = SOURCE_ROOT; };
+               AF98C1592F01FE8800484F29 /* SynthwaveCity.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SynthwaveCity.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C15B2F01FED800484F29 /* synthwavecity.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = synthwavecity.glsl; path = ../hacks/glx/glsl/synthwavecity.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C15C2F01FED800484F29 /* synthwavecity.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = synthwavecity.xml; path = ../hacks/config/synthwavecity.xml; sourceTree = SOURCE_ROOT; };
+               AF98C1782F02023600484F29 /* LogarithmicCircles.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LogarithmicCircles.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C17A2F02028E00484F29 /* logarithmiccircles.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = logarithmiccircles.glsl; path = ../hacks/glx/glsl/logarithmiccircles.glsl; sourceTree = SOURCE_ROOT; };
+               AF98C17B2F02028E00484F29 /* logarithmiccircles.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = logarithmiccircles.xml; path = ../hacks/config/logarithmiccircles.xml; sourceTree = SOURCE_ROOT; };
+               AF98C1972F02063500484F29 /* NeonGravity.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NeonGravity.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AF98C1992F02067500484F29 /* neongravity.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = neongravity.xml; path = ../hacks/config/neongravity.xml; sourceTree = SOURCE_ROOT; };
+               AF98C19A2F02067500484F29 /* neongravity-0.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = "neongravity-0.glsl"; path = "../hacks/glx/glsl/neongravity-0.glsl"; sourceTree = SOURCE_ROOT; };
+               AF98C19B2F02067500484F29 /* neongravity-1.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = "neongravity-1.glsl"; path = "../hacks/glx/glsl/neongravity-1.glsl"; sourceTree = SOURCE_ROOT; };
                AF998EEE0A083DB30051049D /* TopBlock.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TopBlock.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AF998EF80A083E750051049D /* topblock.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = topblock.c; path = hacks/glx/topblock.c; sourceTree = "<group>"; };
                AF998EFA0A083E8C0051049D /* topblock.xml */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.xml; path = topblock.xml; sourceTree = "<group>"; };
                AFAE1484279275BE00C62683 /* Squirtorus.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Squirtorus.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFAE1486279276BB00C62683 /* squirtorus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = squirtorus.c; path = hacks/glx/squirtorus.c; sourceTree = "<group>"; };
                AFAE1487279276BC00C62683 /* squirtorus.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = squirtorus.xml; sourceTree = "<group>"; };
+               AFAF11AE2F13446500449DD7 /* AlienBeacon.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AlienBeacon.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF11B02F13453300449DD7 /* alienbeacon.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = alienbeacon.glsl; path = ../hacks/glx/glsl/alienbeacon.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF11B12F13453300449DD7 /* alienbeacon.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = alienbeacon.xml; path = ../hacks/config/alienbeacon.xml; sourceTree = SOURCE_ROOT; };
+               AFAF11CD2F13459500449DD7 /* BatteredPlanet.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BatteredPlanet.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF11CF2F13461A00449DD7 /* batteredplanet.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = batteredplanet.glsl; path = ../hacks/glx/glsl/batteredplanet.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF11D02F13461A00449DD7 /* batteredplanet.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = batteredplanet.xml; path = ../hacks/config/batteredplanet.xml; sourceTree = SOURCE_ROOT; };
+               AFAF11EC2F1346CE00449DD7 /* ElementalRing.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ElementalRing.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF11EE2F13473C00449DD7 /* elementalring.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = elementalring.glsl; path = ../hacks/glx/glsl/elementalring.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF11EF2F13473C00449DD7 /* elementalring.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = elementalring.xml; path = ../hacks/config/elementalring.xml; sourceTree = SOURCE_ROOT; };
+               AFAF120B2F13477F00449DD7 /* FluxCore.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = FluxCore.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF120D2F13483D00449DD7 /* fluxcore.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = fluxcore.glsl; path = ../hacks/glx/glsl/fluxcore.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF120E2F13483D00449DD7 /* fluxcore.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = fluxcore.xml; path = ../hacks/config/fluxcore.xml; sourceTree = SOURCE_ROOT; };
+               AFAF122A2F13487300449DD7 /* GimbalHarmonics.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GimbalHarmonics.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF122C2F1348EA00449DD7 /* gimbalharmonics.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = gimbalharmonics.glsl; path = ../hacks/glx/glsl/gimbalharmonics.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF122D2F1348EA00449DD7 /* gimbalharmonics.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = gimbalharmonics.xml; path = ../hacks/config/gimbalharmonics.xml; sourceTree = SOURCE_ROOT; };
+               AFAF12492F13495300449DD7 /* Protophore.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Protophore.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF124B2F1349BF00449DD7 /* protophore.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = protophore.glsl; path = hacks/glx/glsl/protophore.glsl; sourceTree = "<group>"; };
+               AFAF124C2F1349BF00449DD7 /* protophore.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = protophore.xml; sourceTree = "<group>"; };
+               AFAF12682F134AA800449DD7 /* SelfReflect.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SelfReflect.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF126A2F134B2200449DD7 /* selfreflect.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = selfreflect.glsl; path = hacks/glx/glsl/selfreflect.glsl; sourceTree = "<group>"; };
+               AFAF126B2F134B2200449DD7 /* selfreflect.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = selfreflect.xml; sourceTree = "<group>"; };
+               AFAF12872F134B8800449DD7 /* Skyline.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Skyline.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF12892F134BE500449DD7 /* skyline.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = skyline.glsl; path = ../hacks/glx/glsl/skyline.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF128A2F134BE500449DD7 /* skyline.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = skyline.xml; path = ../hacks/config/skyline.xml; sourceTree = SOURCE_ROOT; };
+               AFAF12A82F134D8100449DD7 /* Topologica.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Topologica.saver; sourceTree = BUILT_PRODUCTS_DIR; };
+               AFAF12AA2F134E1A00449DD7 /* topologica.glsl */ = {isa = PBXFileReference; lastKnownFileType = text; name = topologica.glsl; path = ../hacks/glx/glsl/topologica.glsl; sourceTree = SOURCE_ROOT; };
+               AFAF12AB2F134E1A00449DD7 /* topologica.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; name = topologica.xml; path = ../hacks/config/topologica.xml; sourceTree = SOURCE_ROOT; };
                AFB591BA178B812C00EA4005 /* Hexadrop.saver */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Hexadrop.saver; sourceTree = BUILT_PRODUCTS_DIR; };
                AFB591BC178B81E600EA4005 /* hexadrop.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = hexadrop.xml; sourceTree = "<group>"; };
                AFB591BD178B81E600EA4005 /* hexadrop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hexadrop.c; path = hacks/hexadrop.c; sourceTree = "<group>"; };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF98C06A2F005FB900484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C06B2F005FB900484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C06C2F005FB900484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C06D2F005FB900484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C06E2F005FB900484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C06F2F005FB900484F29 /* Carbon.framework in Frameworks */,
+                               AF98C0702F005FB900484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C0712F005FB900484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0902F00644500484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0912F00644500484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C0922F00644500484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C0932F00644500484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C0942F00644500484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C0952F00644500484F29 /* Carbon.framework in Frameworks */,
+                               AF98C0962F00644500484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C0972F00644500484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0AC2F00F1FA00484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0AD2F00F1FA00484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C0AE2F00F1FA00484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C0AF2F00F1FA00484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C0B02F00F1FA00484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C0B12F00F1FA00484F29 /* Carbon.framework in Frameworks */,
+                               AF98C0B22F00F1FA00484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C0B32F00F1FA00484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0CF2F01C3E500484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0D02F01C3E500484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C0D12F01C3E500484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C0D22F01C3E500484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C0D32F01C3E500484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C0D42F01C3E500484F29 /* Carbon.framework in Frameworks */,
+                               AF98C0D52F01C3E500484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C0D62F01C3E500484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0F02F01F4AC00484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0F12F01F4AC00484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C0F22F01F4AC00484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C0F32F01F4AC00484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C0F42F01F4AC00484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C0F52F01F4AC00484F29 /* Carbon.framework in Frameworks */,
+                               AF98C0F62F01F4AC00484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C0F72F01F4AC00484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C10F2F01F70E00484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C1102F01F70E00484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C1112F01F70E00484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C1122F01F70E00484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C1132F01F70E00484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C1142F01F70E00484F29 /* Carbon.framework in Frameworks */,
+                               AF98C1152F01F70E00484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C1162F01F70E00484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C12E2F01FA7A00484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C12F2F01FA7A00484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C1302F01FA7A00484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C1312F01FA7A00484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C1322F01FA7A00484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C1332F01FA7A00484F29 /* Carbon.framework in Frameworks */,
+                               AF98C1342F01FA7A00484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C1352F01FA7A00484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C14D2F01FE8800484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C14E2F01FE8800484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C14F2F01FE8800484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C1502F01FE8800484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C1512F01FE8800484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C1522F01FE8800484F29 /* Carbon.framework in Frameworks */,
+                               AF98C1532F01FE8800484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C1542F01FE8800484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C16C2F02023600484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C16D2F02023600484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C16E2F02023600484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C16F2F02023600484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C1702F02023600484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C1712F02023600484F29 /* Carbon.framework in Frameworks */,
+                               AF98C1722F02023600484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C1732F02023600484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C18B2F02063500484F29 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C18C2F02063500484F29 /* libjwxyz.a in Frameworks */,
+                               AF98C18D2F02063500484F29 /* ScreenSaver.framework in Frameworks */,
+                               AF98C18E2F02063500484F29 /* QuartzCore.framework in Frameworks */,
+                               AF98C18F2F02063500484F29 /* Cocoa.framework in Frameworks */,
+                               AF98C1902F02063500484F29 /* Carbon.framework in Frameworks */,
+                               AF98C1912F02063500484F29 /* OpenGL.framework in Frameworks */,
+                               AF98C1922F02063500484F29 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF998EE20A083DB30051049D /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFAF11A22F13446500449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11A32F13446500449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF11A42F13446500449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF11A52F13446500449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF11A62F13446500449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF11A72F13446500449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF11A82F13446500449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF11A92F13446500449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11C12F13459500449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11C22F13459500449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF11C32F13459500449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF11C42F13459500449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF11C52F13459500449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF11C62F13459500449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF11C72F13459500449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF11C82F13459500449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11E02F1346CE00449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11E12F1346CE00449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF11E22F1346CE00449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF11E32F1346CE00449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF11E42F1346CE00449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF11E52F1346CE00449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF11E62F1346CE00449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF11E72F1346CE00449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11FF2F13477F00449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF12002F13477F00449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF12012F13477F00449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF12022F13477F00449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF12032F13477F00449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF12042F13477F00449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF12052F13477F00449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF12062F13477F00449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF121E2F13487300449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF121F2F13487300449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF12202F13487300449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF12212F13487300449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF12222F13487300449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF12232F13487300449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF12242F13487300449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF12252F13487300449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF123D2F13495300449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF123E2F13495300449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF123F2F13495300449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF12402F13495300449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF12412F13495300449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF12422F13495300449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF12432F13495300449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF12442F13495300449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF125C2F134AA800449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF125D2F134AA800449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF125E2F134AA800449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF125F2F134AA800449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF12602F134AA800449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF12612F134AA800449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF12622F134AA800449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF12632F134AA800449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF127B2F134B8800449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF127C2F134B8800449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF127D2F134B8800449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF127E2F134B8800449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF127F2F134B8800449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF12802F134B8800449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF12812F134B8800449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF12822F134B8800449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF129C2F134D8100449DD7 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF129D2F134D8100449DD7 /* libjwxyz.a in Frameworks */,
+                               AFAF129E2F134D8100449DD7 /* ScreenSaver.framework in Frameworks */,
+                               AFAF129F2F134D8100449DD7 /* QuartzCore.framework in Frameworks */,
+                               AFAF12A02F134D8100449DD7 /* Cocoa.framework in Frameworks */,
+                               AFAF12A12F134D8100449DD7 /* Carbon.framework in Frameworks */,
+                               AFAF12A22F134D8100449DD7 /* OpenGL.framework in Frameworks */,
+                               AFAF12A32F134D8100449DD7 /* libz.dylib in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591AF178B812C00EA4005 /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                                AF2D86872DB1FCC900B4F248 /* PlatonicFolding.saver */,
                                AF2D86A92DB20F2100B4F248 /* Klondike.saver */,
                                AFCB48AC2DBC0958006296D3 /* DumpsterFire.saver */,
+                               AF98C0762F005FB900484F29 /* XShadertoy.saver */,
+                               AF98C09C2F00644500484F29 /* StarNest.saver */,
+                               AF98C0B82F00F1FA00484F29 /* HexPlasma.saver */,
+                               AF98C0DB2F01C3E500484F29 /* StarDome.saver */,
+                               AF98C0FC2F01F4AC00484F29 /* StripeyTorus.saver */,
+                               AF98C11B2F01F70E00484F29 /* TruchetZoom.saver */,
+                               AF98C13A2F01FA7A00484F29 /* NeonTriangulator.saver */,
+                               AF98C1592F01FE8800484F29 /* SynthwaveCity.saver */,
+                               AF98C1782F02023600484F29 /* LogarithmicCircles.saver */,
+                               AF98C1972F02063500484F29 /* NeonGravity.saver */,
+                               AFAF11AE2F13446500449DD7 /* AlienBeacon.saver */,
+                               AFAF11CD2F13459500449DD7 /* BatteredPlanet.saver */,
+                               AFAF11EC2F1346CE00449DD7 /* ElementalRing.saver */,
+                               AFAF120B2F13477F00449DD7 /* FluxCore.saver */,
+                               AFAF122A2F13487300449DD7 /* GimbalHarmonics.saver */,
+                               AFAF12492F13495300449DD7 /* Protophore.saver */,
+                               AFAF12682F134AA800449DD7 /* SelfReflect.saver */,
+                               AFAF12872F134B8800449DD7 /* Skyline.saver */,
+                               AFAF12A82F134D8100449DD7 /* Topologica.saver */,
                        );
                        name = Products;
                        path = ..;
                        name = OpenGL;
                        sourceTree = "<group>";
                };
+               AF98C05D2F005F2500484F29 /* Shadertoy */ = {
+                       isa = PBXGroup;
+                       children = (
+                               AF98C0802F00615700484F29 /* xshadertoy.c */,
+                               AFAF11B02F13453300449DD7 /* alienbeacon.glsl */,
+                               AFAF11CF2F13461A00449DD7 /* batteredplanet.glsl */,
+                               AFAF11EE2F13473C00449DD7 /* elementalring.glsl */,
+                               AFAF120D2F13483D00449DD7 /* fluxcore.glsl */,
+                               AFAF122C2F1348EA00449DD7 /* gimbalharmonics.glsl */,
+                               AF98C0BA2F00F25F00484F29 /* hexplasma.glsl */,
+                               AF98C17A2F02028E00484F29 /* logarithmiccircles.glsl */,
+                               AF98C19A2F02067500484F29 /* neongravity-0.glsl */,
+                               AF98C19B2F02067500484F29 /* neongravity-1.glsl */,
+                               AF98C13C2F01FB1D00484F29 /* neontriangulator.glsl */,
+                               AFAF124B2F1349BF00449DD7 /* protophore.glsl */,
+                               AFAF126A2F134B2200449DD7 /* selfreflect.glsl */,
+                               AFAF12892F134BE500449DD7 /* skyline.glsl */,
+                               AF98C0DD2F01C47B00484F29 /* stardome.glsl */,
+                               AF98C05E2F005F6000484F29 /* starnest.glsl */,
+                               AF98C0FE2F01F4FE00484F29 /* stripeytorus.glsl */,
+                               AF98C15B2F01FED800484F29 /* synthwavecity.glsl */,
+                               AFAF12AA2F134E1A00449DD7 /* topologica.glsl */,
+                               AF98C11D2F01F7CF00484F29 /* truchetzoom.glsl */,
+                       );
+                       name = Shadertoy;
+                       sourceTree = "<group>";
+               };
                AFC258670988A468000655EE /* config */ = {
                        isa = PBXGroup;
                        children = (
                                AFE6A4360CDD8026002805BF /* abstractile.xml */,
+                               AFAF11B12F13453300449DD7 /* alienbeacon.xml */,
                                AFC258680988A468000655EE /* anemone.xml */,
                                AFC258690988A468000655EE /* anemotaxis.xml */,
                                AFC2586A0988A468000655EE /* ant.xml */,
                                AFC258710988A468000655EE /* attraction.xml */,
                                AFC258720988A468000655EE /* atunnel.xml */,
                                AFC258730988A468000655EE /* barcode.xml */,
+                               AFAF11D02F13461A00449DD7 /* batteredplanet.xml */,
                                AF688AD3257C05FB00C91EAE /* beats.xml */,
                                AF69E20C270BA62C00358595 /* binaryhorizon.xml */,
                                AF73FF3B1A0988C500E485E9 /* binaryring.xml */,
                                AFC258990988A468000655EE /* drift.xml */,
                                AF7F06112A50C18C00E35B45 /* droste.xml */,
                                AFEC23E51CB6EBDA00DE138F /* dymaxionmap.xml */,
+                               AFAF11EF2F13473C00449DD7 /* elementalring.xml */,
                                AFC2589B0988A468000655EE /* endgame.xml */,
                                AFACE88B1CC83578008B24CD /* energystream.xml */,
                                AFC2589C0988A468000655EE /* engine.xml */,
                                AFC258AA0988A468000655EE /* flow.xml */,
                                AFC258AB0988A468000655EE /* fluidballs.xml */,
                                AFC258AC0988A468000655EE /* flurry.xml */,
+                               AFAF120E2F13483D00449DD7 /* fluxcore.xml */,
                                AFC258AD0988A468000655EE /* flyingtoasters.xml */,
                                AFC258AE0988A468000655EE /* fontglide.xml */,
                                AFC258AF0988A468000655EE /* forest.xml */,
                                AF7ACFD819FF0BA600BD752B /* geodesicgears.xml */,
                                AFC258B30988A468000655EE /* gflux.xml */,
                                AFA0B138241CE7E10071E35D /* gibson.xml */,
+                               AFAF122D2F1348EA00449DD7 /* gimbalharmonics.xml */,
                                AFC258B40988A468000655EE /* glblur.xml */,
                                AFF463730C440BAC00EE6509 /* glcells.xml */,
                                AFC258B50988A468000655EE /* gleidescope.xml */,
                                AF96015525759102007FA31B /* headroom.xml */,
                                AFC258C40988A468000655EE /* helix.xml */,
                                AFB591BC178B81E600EA4005 /* hexadrop.xml */,
+                               AF98C0BB2F00F25F00484F29 /* hexplasma.xml */,
                                AF1B0FBF1D7AB5210011DBE4 /* hexstrut.xml */,
                                AF0BF6E429456C31000D9473 /* hextrail.xml */,
                                AF42CF642BE8A50E00675AC7 /* highvoltage.xml */,
                                AFC258DB0988A468000655EE /* lissie.xml */,
                                AFC258DC0988A468000655EE /* lmorph.xml */,
                                AF4FD7020CE7A5BC005EE58E /* lockward.xml */,
+                               AF98C17B2F02028E00484F29 /* logarithmiccircles.xml */,
                                AFC258DD0988A468000655EE /* loop.xml */,
                                AF0DCA370C4C74B700D76972 /* m6502.xml */,
                                AF6E25CA276C402F0032E38F /* mapscroller.xml */,
                                AFC258E90988A469000655EE /* mountain.xml */,
                                AFC258EA0988A469000655EE /* munch.xml */,
                                AFD704DA2830880B002A8EB0 /* nakagin.xml */,
+                               AF98C1992F02067500484F29 /* neongravity.xml */,
+                               AF98C13D2F01FB1D00484F29 /* neontriangulator.xml */,
                                AFC258EB0988A469000655EE /* nerverot.xml */,
                                AFC258EC0988A469000655EE /* noof.xml */,
                                AFC258ED0988A469000655EE /* noseguy.xml */,
                                AFC258FA0988A469000655EE /* pong.xml */,
                                AFC258FB0988A469000655EE /* popsquares.xml */,
                                AFFAB32C19158E2A0020F021 /* projectiveplane.xml */,
+                               AFAF124C2F1349BF00449DD7 /* protophore.xml */,
                                AFC258FC0988A469000655EE /* providence.xml */,
                                AFC258FD0988A469000655EE /* pulsar.xml */,
                                AFC258FE0988A469000655EE /* pyro.xml */,
                                AF32D9FC0F3AD1330080F535 /* rubikblocks.xml */,
                                AFC259090988A469000655EE /* sballs.xml */,
                                AF436415241D85B900966603 /* scooter.xml */,
+                               AFAF126B2F134B2200449DD7 /* selfreflect.xml */,
                                AFC2590A0988A469000655EE /* shadebobs.xml */,
                                AFC2590B0988A469000655EE /* sierpinski.xml */,
                                AFC2590C0988A469000655EE /* sierpinski3d.xml */,
                                AF70B7A52A832166007C1EB8 /* skulloop.xml */,
+                               AFAF128A2F134BE500449DD7 /* skyline.xml */,
                                AFE2A4740E2E911200ADB298 /* skytentacles.xml */,
                                AFC2590D0988A469000655EE /* slidescreen.xml */,
                                AFC2590E0988A469000655EE /* slip.xml */,
                                AFC259170988A469000655EE /* squiral.xml */,
                                AFAE1487279276BC00C62683 /* squirtorus.xml */,
                                AFC259190988A469000655EE /* stairs.xml */,
+                               AF98C0DE2F01C47B00484F29 /* stardome.xml */,
                                AFC2591A0988A469000655EE /* starfish.xml */,
+                               AF98C09F2F00657700484F29 /* starnest.xml */,
                                AFC2591B0988A469000655EE /* starwars.xml */,
                                AFC2591C0988A469000655EE /* stonerview.xml */,
                                AFC2591D0988A469000655EE /* strange.xml */,
+                               AF98C0FF2F01F4FE00484F29 /* stripeytorus.xml */,
                                AFC2591E0988A469000655EE /* substrate.xml */,
                                AFC2591F0988A469000655EE /* superquadrics.xml */,
                                AF4A3461102A59EB00A81B2A /* surfaces.xml */,
                                AFC259200988A469000655EE /* swirl.xml */,
+                               AF98C15C2F01FED800484F29 /* synthwavecity.xml */,
                                AFC259210988A469000655EE /* t3d.xml */,
                                AFC259220988A469000655EE /* tangram.xml */,
                                AF68A49419196E3E00D41CD1 /* tessellimage.xml */,
                                AFC259230988A469000655EE /* thornbird.xml */,
                                AFC259240988A469000655EE /* timetunnel.xml */,
                                AF998EFA0A083E8C0051049D /* topblock.xml */,
+                               AFAF12AB2F134E1A00449DD7 /* topologica.xml */,
                                AFC259250988A469000655EE /* triangle.xml */,
                                AF3582211433318500E09C51 /* tronbit.xml */,
                                AFC259260988A469000655EE /* truchet.xml */,
+                               AF98C11E2F01F7CF00484F29 /* truchetzoom.xml */,
                                AFC259270988A469000655EE /* twang.xml */,
                                AFC259280988A469000655EE /* vermiculate.xml */,
                                AFC259290988A469000655EE /* vidwhacker.xml */,
                                AF480DC7098F4EB500FB32B8 /* XScreenSaver */,
                                AF480DCF098F4F0600FB32B8 /* Xlockmore */,
                                AF480DD0098F4F2000FB32B8 /* OpenGL */,
+                               AF98C05D2F005F2500484F29 /* Shadertoy */,
                        );
                        name = Hacks;
                        path = ..;
                        productReference = AF9771D70989DC4A001F8B92 /* SaverTester.app */;
                        productType = "com.apple.product-type.application";
                };
+               AF98C0622F005FB900484F29 /* XShadertoy */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C0732F005FB900484F29 /* Build configuration list for PBXNativeTarget "XShadertoy" */;
+                       buildPhases = (
+                               AF98C0652F005FB900484F29 /* Resources */,
+                               AF98C0672F005FB900484F29 /* Sources */,
+                               AF98C06A2F005FB900484F29 /* Frameworks */,
+                               AF98C0722F005FB900484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C0632F005FB900484F29 /* PBXTargetDependency */,
+                       );
+                       name = XShadertoy;
+                       productName = DangerBall;
+                       productReference = AF98C0762F005FB900484F29 /* XShadertoy.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C0882F00644500484F29 /* StarNest */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C0992F00644500484F29 /* Build configuration list for PBXNativeTarget "StarNest" */;
+                       buildPhases = (
+                               AF98C08B2F00644500484F29 /* Resources */,
+                               AF98C08D2F00644500484F29 /* Sources */,
+                               AF98C0902F00644500484F29 /* Frameworks */,
+                               AF98C0982F00644500484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C0892F00644500484F29 /* PBXTargetDependency */,
+                       );
+                       name = StarNest;
+                       productName = DangerBall;
+                       productReference = AF98C09C2F00644500484F29 /* StarNest.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C0A32F00F1FA00484F29 /* HexPlasma */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C0B52F00F1FA00484F29 /* Build configuration list for PBXNativeTarget "HexPlasma" */;
+                       buildPhases = (
+                               AF98C0A62F00F1FA00484F29 /* Resources */,
+                               AF98C0A92F00F1FA00484F29 /* Sources */,
+                               AF98C0AC2F00F1FA00484F29 /* Frameworks */,
+                               AF98C0B42F00F1FA00484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C0A42F00F1FA00484F29 /* PBXTargetDependency */,
+                       );
+                       name = HexPlasma;
+                       productName = DangerBall;
+                       productReference = AF98C0B82F00F1FA00484F29 /* HexPlasma.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C0C62F01C3E500484F29 /* StarDome */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C0D82F01C3E500484F29 /* Build configuration list for PBXNativeTarget "StarDome" */;
+                       buildPhases = (
+                               AF98C0C92F01C3E500484F29 /* Resources */,
+                               AF98C0CC2F01C3E500484F29 /* Sources */,
+                               AF98C0CF2F01C3E500484F29 /* Frameworks */,
+                               AF98C0D72F01C3E500484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C0C72F01C3E500484F29 /* PBXTargetDependency */,
+                       );
+                       name = StarDome;
+                       productName = DangerBall;
+                       productReference = AF98C0DB2F01C3E500484F29 /* StarDome.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C0E72F01F4AC00484F29 /* StripeyTorus */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C0F92F01F4AC00484F29 /* Build configuration list for PBXNativeTarget "StripeyTorus" */;
+                       buildPhases = (
+                               AF98C0EA2F01F4AC00484F29 /* Resources */,
+                               AF98C0ED2F01F4AC00484F29 /* Sources */,
+                               AF98C0F02F01F4AC00484F29 /* Frameworks */,
+                               AF98C0F82F01F4AC00484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C0E82F01F4AC00484F29 /* PBXTargetDependency */,
+                       );
+                       name = StripeyTorus;
+                       productName = DangerBall;
+                       productReference = AF98C0FC2F01F4AC00484F29 /* StripeyTorus.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C1062F01F70E00484F29 /* TruchetZoom */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C1182F01F70E00484F29 /* Build configuration list for PBXNativeTarget "TruchetZoom" */;
+                       buildPhases = (
+                               AF98C1092F01F70E00484F29 /* Resources */,
+                               AF98C10C2F01F70E00484F29 /* Sources */,
+                               AF98C10F2F01F70E00484F29 /* Frameworks */,
+                               AF98C1172F01F70E00484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C1072F01F70E00484F29 /* PBXTargetDependency */,
+                       );
+                       name = TruchetZoom;
+                       productName = DangerBall;
+                       productReference = AF98C11B2F01F70E00484F29 /* TruchetZoom.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C1252F01FA7A00484F29 /* NeonTriangulator */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C1372F01FA7A00484F29 /* Build configuration list for PBXNativeTarget "NeonTriangulator" */;
+                       buildPhases = (
+                               AF98C1282F01FA7A00484F29 /* Resources */,
+                               AF98C12B2F01FA7A00484F29 /* Sources */,
+                               AF98C12E2F01FA7A00484F29 /* Frameworks */,
+                               AF98C1362F01FA7A00484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C1262F01FA7A00484F29 /* PBXTargetDependency */,
+                       );
+                       name = NeonTriangulator;
+                       productName = DangerBall;
+                       productReference = AF98C13A2F01FA7A00484F29 /* NeonTriangulator.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C1442F01FE8800484F29 /* SynthwaveCity */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C1562F01FE8800484F29 /* Build configuration list for PBXNativeTarget "SynthwaveCity" */;
+                       buildPhases = (
+                               AF98C1472F01FE8800484F29 /* Resources */,
+                               AF98C14A2F01FE8800484F29 /* Sources */,
+                               AF98C14D2F01FE8800484F29 /* Frameworks */,
+                               AF98C1552F01FE8800484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C1452F01FE8800484F29 /* PBXTargetDependency */,
+                       );
+                       name = SynthwaveCity;
+                       productName = DangerBall;
+                       productReference = AF98C1592F01FE8800484F29 /* SynthwaveCity.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C1632F02023600484F29 /* LogarithmicCircles */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C1752F02023600484F29 /* Build configuration list for PBXNativeTarget "LogarithmicCircles" */;
+                       buildPhases = (
+                               AF98C1662F02023600484F29 /* Resources */,
+                               AF98C1692F02023600484F29 /* Sources */,
+                               AF98C16C2F02023600484F29 /* Frameworks */,
+                               AF98C1742F02023600484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C1642F02023600484F29 /* PBXTargetDependency */,
+                       );
+                       name = LogarithmicCircles;
+                       productName = DangerBall;
+                       productReference = AF98C1782F02023600484F29 /* LogarithmicCircles.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AF98C1822F02063500484F29 /* NeonGravity */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AF98C1942F02063500484F29 /* Build configuration list for PBXNativeTarget "NeonGravity" */;
+                       buildPhases = (
+                               AF98C1852F02063500484F29 /* Resources */,
+                               AF98C1882F02063500484F29 /* Sources */,
+                               AF98C18B2F02063500484F29 /* Frameworks */,
+                               AF98C1932F02063500484F29 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AF98C1832F02063500484F29 /* PBXTargetDependency */,
+                       );
+                       name = NeonGravity;
+                       productName = DangerBall;
+                       productReference = AF98C1972F02063500484F29 /* NeonGravity.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AF998EDA0A083DB30051049D /* TopBlock */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AF998EEB0A083DB30051049D /* Build configuration list for PBXNativeTarget "TopBlock" */;
                        productReference = AFAE1484279275BE00C62683 /* Squirtorus.saver */;
                        productType = "com.apple.product-type.bundle";
                };
+               AFAF11992F13446500449DD7 /* AlienBeacon */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF11AB2F13446500449DD7 /* Build configuration list for PBXNativeTarget "AlienBeacon" */;
+                       buildPhases = (
+                               AFAF119C2F13446500449DD7 /* Resources */,
+                               AFAF119F2F13446500449DD7 /* Sources */,
+                               AFAF11A22F13446500449DD7 /* Frameworks */,
+                               AFAF11AA2F13446500449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF119A2F13446500449DD7 /* PBXTargetDependency */,
+                       );
+                       name = AlienBeacon;
+                       productName = DangerBall;
+                       productReference = AFAF11AE2F13446500449DD7 /* AlienBeacon.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF11B82F13459500449DD7 /* BatteredPlanet */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF11CA2F13459500449DD7 /* Build configuration list for PBXNativeTarget "BatteredPlanet" */;
+                       buildPhases = (
+                               AFAF11BB2F13459500449DD7 /* Resources */,
+                               AFAF11BE2F13459500449DD7 /* Sources */,
+                               AFAF11C12F13459500449DD7 /* Frameworks */,
+                               AFAF11C92F13459500449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF11B92F13459500449DD7 /* PBXTargetDependency */,
+                       );
+                       name = BatteredPlanet;
+                       productName = DangerBall;
+                       productReference = AFAF11CD2F13459500449DD7 /* BatteredPlanet.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF11D72F1346CE00449DD7 /* ElementalRing */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF11E92F1346CE00449DD7 /* Build configuration list for PBXNativeTarget "ElementalRing" */;
+                       buildPhases = (
+                               AFAF11DA2F1346CE00449DD7 /* Resources */,
+                               AFAF11DD2F1346CE00449DD7 /* Sources */,
+                               AFAF11E02F1346CE00449DD7 /* Frameworks */,
+                               AFAF11E82F1346CE00449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF11D82F1346CE00449DD7 /* PBXTargetDependency */,
+                       );
+                       name = ElementalRing;
+                       productName = DangerBall;
+                       productReference = AFAF11EC2F1346CE00449DD7 /* ElementalRing.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF11F62F13477F00449DD7 /* FluxCore */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF12082F13477F00449DD7 /* Build configuration list for PBXNativeTarget "FluxCore" */;
+                       buildPhases = (
+                               AFAF11F92F13477F00449DD7 /* Resources */,
+                               AFAF11FC2F13477F00449DD7 /* Sources */,
+                               AFAF11FF2F13477F00449DD7 /* Frameworks */,
+                               AFAF12072F13477F00449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF11F72F13477F00449DD7 /* PBXTargetDependency */,
+                       );
+                       name = FluxCore;
+                       productName = DangerBall;
+                       productReference = AFAF120B2F13477F00449DD7 /* FluxCore.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF12152F13487300449DD7 /* GimbalHarmonics */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF12272F13487300449DD7 /* Build configuration list for PBXNativeTarget "GimbalHarmonics" */;
+                       buildPhases = (
+                               AFAF12182F13487300449DD7 /* Resources */,
+                               AFAF121B2F13487300449DD7 /* Sources */,
+                               AFAF121E2F13487300449DD7 /* Frameworks */,
+                               AFAF12262F13487300449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF12162F13487300449DD7 /* PBXTargetDependency */,
+                       );
+                       name = GimbalHarmonics;
+                       productName = DangerBall;
+                       productReference = AFAF122A2F13487300449DD7 /* GimbalHarmonics.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF12342F13495300449DD7 /* Protophore */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF12462F13495300449DD7 /* Build configuration list for PBXNativeTarget "Protophore" */;
+                       buildPhases = (
+                               AFAF12372F13495300449DD7 /* Resources */,
+                               AFAF123A2F13495300449DD7 /* Sources */,
+                               AFAF123D2F13495300449DD7 /* Frameworks */,
+                               AFAF12452F13495300449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF12352F13495300449DD7 /* PBXTargetDependency */,
+                       );
+                       name = Protophore;
+                       productName = DangerBall;
+                       productReference = AFAF12492F13495300449DD7 /* Protophore.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF12532F134AA800449DD7 /* SelfReflect */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF12652F134AA800449DD7 /* Build configuration list for PBXNativeTarget "SelfReflect" */;
+                       buildPhases = (
+                               AFAF12562F134AA800449DD7 /* Resources */,
+                               AFAF12592F134AA800449DD7 /* Sources */,
+                               AFAF125C2F134AA800449DD7 /* Frameworks */,
+                               AFAF12642F134AA800449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF12542F134AA800449DD7 /* PBXTargetDependency */,
+                       );
+                       name = SelfReflect;
+                       productName = DangerBall;
+                       productReference = AFAF12682F134AA800449DD7 /* SelfReflect.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF12722F134B8800449DD7 /* Skyline */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF12842F134B8800449DD7 /* Build configuration list for PBXNativeTarget "Skyline" */;
+                       buildPhases = (
+                               AFAF12752F134B8800449DD7 /* Resources */,
+                               AFAF12782F134B8800449DD7 /* Sources */,
+                               AFAF127B2F134B8800449DD7 /* Frameworks */,
+                               AFAF12832F134B8800449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF12732F134B8800449DD7 /* PBXTargetDependency */,
+                       );
+                       name = Skyline;
+                       productName = DangerBall;
+                       productReference = AFAF12872F134B8800449DD7 /* Skyline.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
+               AFAF12912F134D8100449DD7 /* Topologica */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = AFAF12A52F134D8100449DD7 /* Build configuration list for PBXNativeTarget "Topologica" */;
+                       buildPhases = (
+                               AFAF12942F134D8100449DD7 /* Resources */,
+                               AFAF12992F134D8100449DD7 /* Sources */,
+                               AFAF129C2F134D8100449DD7 /* Frameworks */,
+                               AFAF12A42F134D8100449DD7 /* Run Update Info Plist */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                               AFAF12922F134D8100449DD7 /* PBXTargetDependency */,
+                       );
+                       name = Topologica;
+                       productName = DangerBall;
+                       productReference = AFAF12A82F134D8100449DD7 /* Topologica.saver */;
+                       productType = "com.apple.product-type.bundle";
+               };
                AFB591A7178B812C00EA4005 /* Hexadrop */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = AFB591B7178B812C00EA4005 /* Build configuration list for PBXNativeTarget "Hexadrop" */;
                                        AF9771D60989DC4A001F8B92 = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
+                                       AF98C0782F00600400484F29 = {
+                                               CreatedOnToolsVersion = 16.2;
+                                       };
                                        AF998EDA0A083DB30051049D = {
                                                DevelopmentTeam = 4627ATJELP;
                                        };
                                AF633C011EE0BA6F00AB33BD /* Vigilance */,
                                AF0DCA420C4CBB0D00D76972 /* Voronoi */,
                                AF39E282198A11F60064A58D /* WindupRobot */,
+                               AF98C0782F00600400484F29 /* All Savers (Shadertoy) */,
+                               AF98C0622F005FB900484F29 /* XShadertoy */,
+                               AFAF11992F13446500449DD7 /* AlienBeacon */,
+                               AFAF11B82F13459500449DD7 /* BatteredPlanet */,
+                               AFAF11D72F1346CE00449DD7 /* ElementalRing */,
+                               AFAF11F62F13477F00449DD7 /* FluxCore */,
+                               AFAF12152F13487300449DD7 /* GimbalHarmonics */,
+                               AF98C0A32F00F1FA00484F29 /* HexPlasma */,
+                               AF98C1632F02023600484F29 /* LogarithmicCircles */,
+                               AF98C1822F02063500484F29 /* NeonGravity */,
+                               AF98C1252F01FA7A00484F29 /* NeonTriangulator */,
+                               AFAF12342F13495300449DD7 /* Protophore */,
+                               AFAF12532F134AA800449DD7 /* SelfReflect */,
+                               AFAF12722F134B8800449DD7 /* Skyline */,
+                               AF98C0C62F01C3E500484F29 /* StarDome */,
+                               AF98C0882F00644500484F29 /* StarNest */,
+                               AF98C0E72F01F4AC00484F29 /* StripeyTorus */,
+                               AF98C1442F01FE8800484F29 /* SynthwaveCity */,
+                               AFAF12912F134D8100449DD7 /* Topologica */,
+                               AF98C1062F01F70E00484F29 /* TruchetZoom */,
                                AF137D410F075C9B004DE3B2 /* Obsolete */,
                                AFA55CCC09934CE400F3E977 /* GLForestFire */,
                                AFD570C90996B9F800BA26F7 /* Ant */,
                                AF5688EF26E7060500CCBA38 /* stop@2x.png in Resources */,
                                AF5688F026E7060500CCBA38 /* stop@3x.png in Resources */,
                                AF5688F126E7060500CCBA38 /* abstractile.xml in Resources */,
+                               AFAF11B62F13453300449DD7 /* alienbeacon.glsl in Resources */,
+                               AFAF11B72F13453300449DD7 /* alienbeacon.xml in Resources */,
                                AF5688F226E7060500CCBA38 /* anemone.xml in Resources */,
                                AF5688F326E7060500CCBA38 /* anemotaxis.xml in Resources */,
                                AF5688F426E7060500CCBA38 /* antinspect.xml in Resources */,
                                AF5688FA26E7060500CCBA38 /* attraction.xml in Resources */,
                                AF5688FB26E7060500CCBA38 /* atunnel.xml in Resources */,
                                AF5688FC26E7060500CCBA38 /* barcode.xml in Resources */,
+                               AFAF11D52F13461A00449DD7 /* batteredplanet.glsl in Resources */,
+                               AFAF11D62F13461A00449DD7 /* batteredplanet.xml in Resources */,
                                AF5688FD26E7060500CCBA38 /* beats.xml in Resources */,
                                AF69E20F270BA62C00358595 /* binaryhorizon.xml in Resources */,
                                AF5688FE26E7060500CCBA38 /* binaryring.xml in Resources */,
                                AFCB48B92DBC0BDB006296D3 /* dumpsterfire.xml in Resources */,
                                AF56892C26E7060500CCBA38 /* dymaxionmap.xml in Resources */,
                                AF56892D26E7060500CCBA38 /* drift.xml in Resources */,
+                               AFAF11F42F13473C00449DD7 /* elementalring.glsl in Resources */,
+                               AFAF11F52F13473C00449DD7 /* elementalring.xml in Resources */,
                                AF56892E26E7060500CCBA38 /* endgame.xml in Resources */,
                                AF56892F26E7060500CCBA38 /* energystream.xml in Resources */,
                                AF56893026E7060500CCBA38 /* engine.xml in Resources */,
                                AF56893D26E7060500CCBA38 /* fliptext.xml in Resources */,
                                AF56893E26E7060500CCBA38 /* flow.xml in Resources */,
                                AF56893F26E7060500CCBA38 /* fluidballs.xml in Resources */,
+                               AFAF12112F13483D00449DD7 /* fluxcore.xml in Resources */,
+                               AFAF12122F13483D00449DD7 /* fluxcore.glsl in Resources */,
                                AF56894026E7060500CCBA38 /* flyingtoasters.xml in Resources */,
                                AF56894126E7060500CCBA38 /* fontglide.xml in Resources */,
                                AF56894226E7060500CCBA38 /* fuzzyflakes.xml in Resources */,
                                AF56894626E7060500CCBA38 /* geodesicgears.xml in Resources */,
                                AF56894726E7060500CCBA38 /* gflux.xml in Resources */,
                                AF56894826E7060500CCBA38 /* gibson.xml in Resources */,
+                               AFAF12302F1348EA00449DD7 /* gimbalharmonics.glsl in Resources */,
+                               AFAF12312F1348EA00449DD7 /* gimbalharmonics.xml in Resources */,
                                AF56894926E7060500CCBA38 /* glblur.xml in Resources */,
                                AF56894A26E7060500CCBA38 /* glcells.xml in Resources */,
                                AF56894B26E7060500CCBA38 /* gleidescope.xml in Resources */,
                                AF56895C26E7060500CCBA38 /* helix.xml in Resources */,
                                AF56895D26E7060500CCBA38 /* hexadrop.xml in Resources */,
                                AF56895E26E7060500CCBA38 /* hexstrut.xml in Resources */,
+                               AF98C0BF2F00F25F00484F29 /* hexplasma.glsl in Resources */,
+                               AF98C0BE2F00F25F00484F29 /* hexplasma.xml in Resources */,
                                AF0BF6EA29456D20000D9473 /* hextrail.xml in Resources */,
                                AF42CF692BE8A50E00675AC7 /* highvoltage.xml in Resources */,
                                AF56895F26E7060500CCBA38 /* hilbert.xml in Resources */,
                                AF56897026E7060500CCBA38 /* kumppa.xml in Resources */,
                                AF56897126E7060500CCBA38 /* lament.xml in Resources */,
                                AF56897226E7060500CCBA38 /* lavalite.xml in Resources */,
+                               AF98C1802F02028E00484F29 /* logarithmiccircles.glsl in Resources */,
+                               AF98C1812F02028E00484F29 /* logarithmiccircles.xml in Resources */,
                                AF56897326E7060500CCBA38 /* loop.xml in Resources */,
                                AF56897426E7060500CCBA38 /* m6502.xml in Resources */,
                                AF56897526E7060500CCBA38 /* marbling.xml in Resources */,
                                AF56897C26E7060500CCBA38 /* moebius.xml in Resources */,
                                AF56897D26E7060500CCBA38 /* moebiusgears.xml in Resources */,
                                AF56897E26E7060500CCBA38 /* moire.xml in Resources */,
+                               AF98C0A22F00657700484F29 /* starnest.xml in Resources */,
                                AF56897F26E7060500CCBA38 /* moire2.xml in Resources */,
                                AF56898026E7060500CCBA38 /* molecule.xml in Resources */,
                                AF56898126E7060500CCBA38 /* morph3d.xml in Resources */,
                                AF56898326E7060500CCBA38 /* munch.xml in Resources */,
                                AF56898426E7060500CCBA38 /* nerverot.xml in Resources */,
                                AFD704E02830880B002A8EB0 /* nakagin.xml in Resources */,
+                               AF98C19D2F02067500484F29 /* neongravity-0.glsl in Resources */,
+                               AF98C19C2F02067500484F29 /* neongravity-1.glsl in Resources */,
+                               AF98C19E2F02067500484F29 /* neongravity.xml in Resources */,
+                               AF98C1402F01FB1D00484F29 /* neontriangulator.glsl in Resources */,
+                               AF98C1412F01FB1D00484F29 /* neontriangulator.xml in Resources */,
                                AF56898526E7060500CCBA38 /* noof.xml in Resources */,
                                AF56898626E7060500CCBA38 /* noseguy.xml in Resources */,
                                AF56898726E7060500CCBA38 /* pacman.xml in Resources */,
                                AF56899726E7060500CCBA38 /* popsquares.xml in Resources */,
                                AF56899826E7060500CCBA38 /* projectiveplane.xml in Resources */,
                                AF56899926E7060500CCBA38 /* providence.xml in Resources */,
+                               AFAF124D2F1349BF00449DD7 /* protophore.glsl in Resources */,
+                               AFAF124E2F1349BF00449DD7 /* protophore.xml in Resources */,
                                AF56899A26E7060500CCBA38 /* pulsar.xml in Resources */,
                                AF56899B26E7060500CCBA38 /* pyro.xml in Resources */,
                                AF56899C26E7060500CCBA38 /* qix.xml in Resources */,
                                AF5689A826E7060500CCBA38 /* rubikblocks.xml in Resources */,
                                AF5689A926E7060500CCBA38 /* sballs.xml in Resources */,
                                AF5689AA26E7060500CCBA38 /* scooter.xml in Resources */,
+                               AFAF126C2F134B2200449DD7 /* selfreflect.xml in Resources */,
+                               AFAF126D2F134B2200449DD7 /* selfreflect.glsl in Resources */,
+                               AFAF128F2F134BE500449DD7 /* skyline.glsl in Resources */,
+                               AFAF12902F134BE500449DD7 /* skyline.xml in Resources */,
                                AF5689AB26E7060500CCBA38 /* shadebobs.xml in Resources */,
                                AF5689AC26E7060500CCBA38 /* sierpinski.xml in Resources */,
                                AF5689AD26E7060500CCBA38 /* sierpinski3d.xml in Resources */,
                                AF70B7AA2A832166007C1EB8 /* skulloop.xml in Resources */,
+                               AF98C15F2F01FED800484F29 /* synthwavecity.glsl in Resources */,
+                               AF98C1602F01FED800484F29 /* synthwavecity.xml in Resources */,
+                               AF98C11F2F01F7CF00484F29 /* truchetzoom.xml in Resources */,
+                               AF98C1202F01F7CF00484F29 /* truchetzoom.glsl in Resources */,
                                AF5689AE26E7060500CCBA38 /* skytentacles.xml in Resources */,
                                AF5689AF26E7060500CCBA38 /* slidescreen.xml in Resources */,
                                AF5689B026E7060500CCBA38 /* slip.xml in Resources */,
                                AFAE148D279276BC00C62683 /* squirtorus.xml in Resources */,
                                AF5689BA26E7060500CCBA38 /* stairs.xml in Resources */,
                                AF5689BB26E7060500CCBA38 /* starfish.xml in Resources */,
+                               AF98C0E12F01C47B00484F29 /* stardome.xml in Resources */,
+                               AF98C0E22F01C47B00484F29 /* stardome.glsl in Resources */,
+                               AF98C0612F005F6000484F29 /* starnest.glsl in Resources */,
                                AF5689BC26E7060500CCBA38 /* starwars.xml in Resources */,
                                AF5689BD26E7060500CCBA38 /* stonerview.xml in Resources */,
                                AF5689BE26E7060500CCBA38 /* strange.xml in Resources */,
+                               AF98C1002F01F4FE00484F29 /* stripeytorus.glsl in Resources */,
+                               AF98C1012F01F4FE00484F29 /* stripeytorus.xml in Resources */,
                                AF5689C026E7060500CCBA38 /* substrate.xml in Resources */,
                                AF5689C126E7060500CCBA38 /* superquadrics.xml in Resources */,
                                AF5689C226E7060500CCBA38 /* surfaces.xml in Resources */,
                                AF5689C526E7060500CCBA38 /* tessellimage.xml in Resources */,
                                AF5689C726E7060500CCBA38 /* timetunnel.xml in Resources */,
                                AF5689C826E7060500CCBA38 /* topblock.xml in Resources */,
+                               AFAF12AE2F134E1A00449DD7 /* topologica.glsl in Resources */,
+                               AFAF12AF2F134E1A00449DD7 /* topologica.xml in Resources */,
                                AF5689C926E7060500CCBA38 /* triangle.xml in Resources */,
                                AF5689CA26E7060500CCBA38 /* tronbit.xml in Resources */,
                                AF5689CB26E7060500CCBA38 /* truchet.xml in Resources */,
                                557BF0801EE90D3B00846DCE /* stop@2x.png in Resources */,
                                557BF0811EE90D3B00846DCE /* stop@3x.png in Resources */,
                                AF918AB4158FC53D002B5D1E /* abstractile.xml in Resources */,
+                               AFAF11B22F13453300449DD7 /* alienbeacon.glsl in Resources */,
+                               AFAF11B32F13453300449DD7 /* alienbeacon.xml in Resources */,
                                AF918AB5158FC53D002B5D1E /* anemone.xml in Resources */,
                                AF918AB6158FC53D002B5D1E /* anemotaxis.xml in Resources */,
                                AF918AB8158FC53D002B5D1E /* antinspect.xml in Resources */,
                                AF918ABE158FC53D002B5D1E /* attraction.xml in Resources */,
                                AF918ABF158FC53D002B5D1E /* atunnel.xml in Resources */,
                                AF918AC0158FC53D002B5D1E /* barcode.xml in Resources */,
+                               AFAF11D12F13461A00449DD7 /* batteredplanet.glsl in Resources */,
+                               AFAF11D22F13461A00449DD7 /* batteredplanet.xml in Resources */,
                                AF688AD5257C05FC00C91EAE /* beats.xml in Resources */,
                                AF69E20E270BA62C00358595 /* binaryhorizon.xml in Resources */,
                                AF73FF3D1A0988C500E485E9 /* binaryring.xml in Resources */,
                                AFCB48B32DBC0BDB006296D3 /* dumpsterfire.xml in Resources */,
                                AFEC23E81CB6EC6800DE138F /* dymaxionmap.xml in Resources */,
                                AF918AE9158FC53D002B5D1E /* drift.xml in Resources */,
+                               AFAF11F22F13473C00449DD7 /* elementalring.glsl in Resources */,
+                               AFAF11F32F13473C00449DD7 /* elementalring.xml in Resources */,
                                AF918AEA158FC53D002B5D1E /* endgame.xml in Resources */,
                                AFACE88C1CC835F7008B24CD /* energystream.xml in Resources */,
                                AF918AEB158FC53D002B5D1E /* engine.xml in Resources */,
                                AF918AF7158FC53D002B5D1E /* fliptext.xml in Resources */,
                                AF918AF8158FC53D002B5D1E /* flow.xml in Resources */,
                                AF918AF9158FC53D002B5D1E /* fluidballs.xml in Resources */,
+                               AFAF12132F13483D00449DD7 /* fluxcore.xml in Resources */,
+                               AFAF12142F13483D00449DD7 /* fluxcore.glsl in Resources */,
                                AF918AFB158FC53D002B5D1E /* flyingtoasters.xml in Resources */,
                                AF918AFC158FC53D002B5D1E /* fontglide.xml in Resources */,
                                AF918AFE158FC53D002B5D1E /* fuzzyflakes.xml in Resources */,
                                AF7ACFDA19FF0BA600BD752B /* geodesicgears.xml in Resources */,
                                AF918B01158FC53D002B5D1E /* gflux.xml in Resources */,
                                AFA0B13A241CE7E10071E35D /* gibson.xml in Resources */,
+                               AFAF122E2F1348EA00449DD7 /* gimbalharmonics.glsl in Resources */,
+                               AFAF122F2F1348EA00449DD7 /* gimbalharmonics.xml in Resources */,
                                AF918B02158FC53D002B5D1E /* glblur.xml in Resources */,
                                AF918B03158FC53D002B5D1E /* glcells.xml in Resources */,
                                AF918B04158FC53D002B5D1E /* gleidescope.xml in Resources */,
                                AF96015725759103007FA31B /* headroom.xml in Resources */,
                                AF918B13158FC53D002B5D1E /* helix.xml in Resources */,
                                AFB591BF178B81E600EA4005 /* hexadrop.xml in Resources */,
+                               AF98C0BC2F00F25F00484F29 /* hexplasma.xml in Resources */,
+                               AF98C0BD2F00F25F00484F29 /* hexplasma.glsl in Resources */,
                                AF1B0FC01D7AB5330011DBE4 /* hexstrut.xml in Resources */,
                                AF0BF6EB29456D2D000D9473 /* hextrail.xml in Resources */,
                                AF42CF682BE8A50E00675AC7 /* highvoltage.xml in Resources */,
                                AF918B26158FC53D002B5D1E /* kumppa.xml in Resources */,
                                AF918B27158FC53D002B5D1E /* lament.xml in Resources */,
                                AF918B29158FC53D002B5D1E /* lavalite.xml in Resources */,
+                               AF98C17E2F02028E00484F29 /* logarithmiccircles.glsl in Resources */,
+                               AF98C17F2F02028E00484F29 /* logarithmiccircles.xml in Resources */,
                                AF918B30158FC53D002B5D1E /* loop.xml in Resources */,
                                AF918B31158FC53D002B5D1E /* m6502.xml in Resources */,
                                AF796D3626E5C21C00DA6562 /* marbling.xml in Resources */,
                                AF918B3F158FC53D002B5D1E /* munch.xml in Resources */,
                                AF918B40158FC53D002B5D1E /* nerverot.xml in Resources */,
                                AFD704DF2830880B002A8EB0 /* nakagin.xml in Resources */,
+                               AF98C1A02F02067500484F29 /* neongravity-0.glsl in Resources */,
+                               AF98C19F2F02067500484F29 /* neongravity-1.glsl in Resources */,
+                               AF98C1A12F02067500484F29 /* neongravity.xml in Resources */,
+                               AF98C1422F01FB1D00484F29 /* neontriangulator.glsl in Resources */,
+                               AF98C1432F01FB1D00484F29 /* neontriangulator.xml in Resources */,
                                AF918B41158FC53D002B5D1E /* noof.xml in Resources */,
                                AF918B42158FC53D002B5D1E /* noseguy.xml in Resources */,
                                AF918B43158FC53D002B5D1E /* pacman.xml in Resources */,
                                AF918B50158FC53E002B5D1E /* pong.xml in Resources */,
                                AF918B51158FC53E002B5D1E /* popsquares.xml in Resources */,
                                AFFAB33019158E2A0020F021 /* projectiveplane.xml in Resources */,
+                               AFAF12512F1349BF00449DD7 /* protophore.glsl in Resources */,
+                               AFAF12522F1349BF00449DD7 /* protophore.xml in Resources */,
                                AF918B52158FC53E002B5D1E /* providence.xml in Resources */,
                                AF918B53158FC53E002B5D1E /* pulsar.xml in Resources */,
                                AF918B54158FC53E002B5D1E /* pyro.xml in Resources */,
                                AF41E96F201D4B940098E253 /* razzledazzle.xml in Resources */,
                                AF918B57158FC53E002B5D1E /* rdbomb.xml in Resources */,
                                AF918B58158FC53E002B5D1E /* ripples.xml in Resources */,
+                               AFAF128B2F134BE500449DD7 /* skyline.glsl in Resources */,
+                               AFAF128C2F134BE500449DD7 /* skyline.xml in Resources */,
                                AF918B59158FC53E002B5D1E /* rocks.xml in Resources */,
                                AF63A80B1AB4EF5D00593C75 /* romanboy.xml in Resources */,
                                AF918B5A158FC53E002B5D1E /* rorschach.xml in Resources */,
                                AF918B5E158FC53E002B5D1E /* rubikblocks.xml in Resources */,
                                AF918B5F158FC53E002B5D1E /* sballs.xml in Resources */,
                                AF436417241D85B900966603 /* scooter.xml in Resources */,
+                               AFAF126E2F134B2200449DD7 /* selfreflect.xml in Resources */,
+                               AFAF126F2F134B2200449DD7 /* selfreflect.glsl in Resources */,
+                               AF98C0A02F00657700484F29 /* starnest.xml in Resources */,
                                AF918B60158FC53E002B5D1E /* shadebobs.xml in Resources */,
                                AF918B61158FC53E002B5D1E /* sierpinski.xml in Resources */,
                                AF918B62158FC53E002B5D1E /* sierpinski3d.xml in Resources */,
                                AF70B7A92A832166007C1EB8 /* skulloop.xml in Resources */,
+                               AF98C15D2F01FED800484F29 /* synthwavecity.glsl in Resources */,
+                               AF98C15E2F01FED800484F29 /* synthwavecity.xml in Resources */,
+                               AF98C1232F01F7CF00484F29 /* truchetzoom.xml in Resources */,
+                               AF98C1242F01F7CF00484F29 /* truchetzoom.glsl in Resources */,
                                AF918B63158FC53E002B5D1E /* skytentacles.xml in Resources */,
                                AF918B64158FC53E002B5D1E /* slidescreen.xml in Resources */,
                                AF918B65158FC53E002B5D1E /* slip.xml in Resources */,
                                AFAE148C279276BC00C62683 /* squirtorus.xml in Resources */,
                                AF918B6E158FC53E002B5D1E /* stairs.xml in Resources */,
                                AF918B6F158FC53E002B5D1E /* starfish.xml in Resources */,
+                               AF98C0DF2F01C47B00484F29 /* stardome.xml in Resources */,
+                               AF98C0E02F01C47B00484F29 /* stardome.glsl in Resources */,
+                               AF98C05F2F005F6000484F29 /* starnest.glsl in Resources */,
                                AF918B70158FC53E002B5D1E /* starwars.xml in Resources */,
                                AF918B71158FC53E002B5D1E /* stonerview.xml in Resources */,
                                AF918B72158FC53E002B5D1E /* strange.xml in Resources */,
+                               AF98C1042F01F4FE00484F29 /* stripeytorus.glsl in Resources */,
+                               AF98C1052F01F4FE00484F29 /* stripeytorus.xml in Resources */,
                                AF918B73158FC53E002B5D1E /* substrate.xml in Resources */,
                                AF918B74158FC53E002B5D1E /* superquadrics.xml in Resources */,
                                AF918B75158FC53E002B5D1E /* surfaces.xml in Resources */,
                                AF68A49819196E3E00D41CD1 /* tessellimage.xml in Resources */,
                                AF918B7A158FC53E002B5D1E /* timetunnel.xml in Resources */,
                                AF918B7B158FC53E002B5D1E /* topblock.xml in Resources */,
+                               AFAF12B02F134E1A00449DD7 /* topologica.glsl in Resources */,
+                               AFAF12B12F134E1A00449DD7 /* topologica.xml in Resources */,
                                AF918B7C158FC53E002B5D1E /* triangle.xml in Resources */,
                                AF918B7D158FC53E002B5D1E /* tronbit.xml in Resources */,
                                AF918B7E158FC53E002B5D1E /* truchet.xml in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF98C0652F005FB900484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C08B2F00644500484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C09E2F00653B00484F29 /* starnest.glsl in Resources */,
+                               AF98C0A12F00657700484F29 /* starnest.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0A62F00F1FA00484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0C02F00F25F00484F29 /* hexplasma.xml in Resources */,
+                               AF98C0C12F00F25F00484F29 /* hexplasma.glsl in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0C92F01C3E500484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0E32F01C47B00484F29 /* stardome.xml in Resources */,
+                               AF98C0E42F01C47B00484F29 /* stardome.glsl in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0EA2F01F4AC00484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C1022F01F4FE00484F29 /* stripeytorus.glsl in Resources */,
+                               AF98C1032F01F4FE00484F29 /* stripeytorus.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1092F01F70E00484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C1212F01F7CF00484F29 /* truchetzoom.xml in Resources */,
+                               AF98C1222F01F7CF00484F29 /* truchetzoom.glsl in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1282F01FA7A00484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C13E2F01FB1D00484F29 /* neontriangulator.glsl in Resources */,
+                               AF98C13F2F01FB1D00484F29 /* neontriangulator.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1472F01FE8800484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C1612F01FED800484F29 /* synthwavecity.glsl in Resources */,
+                               AF98C1622F01FED800484F29 /* synthwavecity.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1662F02023600484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C17C2F02028E00484F29 /* logarithmiccircles.glsl in Resources */,
+                               AF98C17D2F02028E00484F29 /* logarithmiccircles.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1852F02063500484F29 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C1A22F02067500484F29 /* neongravity-1.glsl in Resources */,
+                               AF98C1A32F02067500484F29 /* neongravity-0.glsl in Resources */,
+                               AF98C1A42F02067500484F29 /* neongravity.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF998EDD0A083DB30051049D /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        buildActionMask = 2147483647;
                        files = (
                                AFA55E970993602F00F3E977 /* flyingtoasters.xml in Resources */,
+                               AF98C0602F005F6000484F29 /* starnest.glsl in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFAF119C2F13446500449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11B42F13453300449DD7 /* alienbeacon.glsl in Resources */,
+                               AFAF11B52F13453300449DD7 /* alienbeacon.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11BB2F13459500449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11D32F13461A00449DD7 /* batteredplanet.glsl in Resources */,
+                               AFAF11D42F13461A00449DD7 /* batteredplanet.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11DA2F1346CE00449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11F02F13473C00449DD7 /* elementalring.glsl in Resources */,
+                               AFAF11F12F13473C00449DD7 /* elementalring.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11F92F13477F00449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF120F2F13483D00449DD7 /* fluxcore.xml in Resources */,
+                               AFAF12102F13483D00449DD7 /* fluxcore.glsl in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12182F13487300449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF12322F1348EA00449DD7 /* gimbalharmonics.glsl in Resources */,
+                               AFAF12332F1348EA00449DD7 /* gimbalharmonics.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12372F13495300449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF124F2F1349BF00449DD7 /* protophore.glsl in Resources */,
+                               AFAF12502F1349BF00449DD7 /* protophore.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12562F134AA800449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF12702F134B2200449DD7 /* selfreflect.xml in Resources */,
+                               AFAF12712F134B2200449DD7 /* selfreflect.glsl in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12752F134B8800449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF128D2F134BE500449DD7 /* skyline.glsl in Resources */,
+                               AFAF128E2F134BE500449DD7 /* skyline.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12942F134D8100449DD7 /* Resources */ = {
+                       isa = PBXResourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF12AC2F134E1A00449DD7 /* topologica.glsl in Resources */,
+                               AFAF12AD2F134E1A00449DD7 /* topologica.xml in Resources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591AA178B812C00EA4005 /* Resources */ = {
                        isa = PBXResourcesBuildPhase;
                        buildActionMask = 2147483647;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AF98C0722F005FB900484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C0982F00644500484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C0B42F00F1FA00484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C0D72F01C3E500484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C0F82F01F4AC00484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C1172F01F70E00484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C1362F01FA7A00484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C1552F01FE8800484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C1742F02023600484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AF98C1932F02063500484F29 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
                AF998EEA0A083DB30051049D /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        alwaysOutOfDate = 1;
                        shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX";
                        showEnvVarsInLog = 0;
                };
+               AFAF11AA2F13446500449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF11C92F13459500449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF11E82F1346CE00449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF12072F13477F00449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF12262F13487300449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF12452F13495300449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF12642F134AA800449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF12832F134B8800449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
+               AFAF12A42F134D8100449DD7 /* Run Update Info Plist */ = {
+                       isa = PBXShellScriptBuildPhase;
+                       alwaysOutOfDate = 1;
+                       buildActionMask = 2147483647;
+                       files = (
+                       );
+                       inputPaths = (
+                               "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
+                       );
+                       name = "Run Update Info Plist";
+                       outputPaths = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+                       shellPath = /bin/sh;
+                       shellScript = "$SOURCE_ROOT/update-info-plist.pl -q $BUILT_PRODUCTS_DIR/$PRODUCT_NAME$WRAPPER_SUFFIX\n";
+                       showEnvVarsInLog = 0;
+               };
                AFB591B6178B812C00EA4005 /* Run Update Info Plist */ = {
                        isa = PBXShellScriptBuildPhase;
                        alwaysOutOfDate = 1;
                                AF568B1D26E7060500CCBA38 /* voronoi.c in Sources */,
                                AF568B1E26E7060500CCBA38 /* whale.c in Sources */,
                                AF568B1F26E7060500CCBA38 /* winduprobot.c in Sources */,
+                               AF98C0832F00615700484F29 /* xshadertoy.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        files = (
                                AF77784B09B6528100EA3033 /* XScreenSaverSubclass.m in Sources */,
                                AF77787C09B654F800EA3033 /* carousel.c in Sources */,
+                               AF5E58792EFDE99D0056DEDC /* xftwrap.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                AF918AB2158FC47B002B5D1E /* voronoi.c in Sources */,
                                AF918AB3158FC47B002B5D1E /* whale.c in Sources */,
                                AF39E2B8198A15EE0064A58D /* winduprobot.c in Sources */,
+                               AF98C0862F00615700484F29 /* xshadertoy.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AF98C0672F005FB900484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0842F00615700484F29 /* xshadertoy.c in Sources */,
+                               AF98C0692F005FB900484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C08D2F00644500484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C08E2F00644500484F29 /* xshadertoy.c in Sources */,
+                               AF98C08F2F00644500484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0A92F00F1FA00484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0AA2F00F1FA00484F29 /* xshadertoy.c in Sources */,
+                               AF98C0AB2F00F1FA00484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0CC2F01C3E500484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0CD2F01C3E500484F29 /* xshadertoy.c in Sources */,
+                               AF98C0CE2F01C3E500484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C0ED2F01F4AC00484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C0EE2F01F4AC00484F29 /* xshadertoy.c in Sources */,
+                               AF98C0EF2F01F4AC00484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C10C2F01F70E00484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C10D2F01F70E00484F29 /* xshadertoy.c in Sources */,
+                               AF98C10E2F01F70E00484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C12B2F01FA7A00484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C12C2F01FA7A00484F29 /* xshadertoy.c in Sources */,
+                               AF98C12D2F01FA7A00484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C14A2F01FE8800484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C14B2F01FE8800484F29 /* xshadertoy.c in Sources */,
+                               AF98C14C2F01FE8800484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1692F02023600484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C16A2F02023600484F29 /* xshadertoy.c in Sources */,
+                               AF98C16B2F02023600484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AF98C1882F02063500484F29 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AF98C1892F02063500484F29 /* xshadertoy.c in Sources */,
+                               AF98C18A2F02063500484F29 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AF998EDF0A083DB30051049D /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               AFAF119F2F13446500449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11A02F13446500449DD7 /* xshadertoy.c in Sources */,
+                               AFAF11A12F13446500449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11BE2F13459500449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11BF2F13459500449DD7 /* xshadertoy.c in Sources */,
+                               AFAF11C02F13459500449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11DD2F1346CE00449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11DE2F1346CE00449DD7 /* xshadertoy.c in Sources */,
+                               AFAF11DF2F1346CE00449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF11FC2F13477F00449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF11FD2F13477F00449DD7 /* xshadertoy.c in Sources */,
+                               AFAF11FE2F13477F00449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF121B2F13487300449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF121C2F13487300449DD7 /* xshadertoy.c in Sources */,
+                               AFAF121D2F13487300449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF123A2F13495300449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF123B2F13495300449DD7 /* xshadertoy.c in Sources */,
+                               AFAF123C2F13495300449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12592F134AA800449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF125A2F134AA800449DD7 /* xshadertoy.c in Sources */,
+                               AFAF125B2F134AA800449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12782F134B8800449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF12792F134B8800449DD7 /* xshadertoy.c in Sources */,
+                               AFAF127A2F134B8800449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               AFAF12992F134D8100449DD7 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               AFAF129A2F134D8100449DD7 /* xshadertoy.c in Sources */,
+                               AFAF129B2F134D8100449DD7 /* XScreenSaverSubclass.m in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                AFB591AC178B812C00EA4005 /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                AFD51B220F063B4A00471C02 /* XScreenSaverSubclass.m in Sources */,
                                AFD51DB70F063BCE00471C02 /* photopile.c in Sources */,
                                AF241F83107C38DF00046A84 /* dropshadow.c in Sources */,
+                               AF5E58782EFDE9750056DEDC /* xftwrap.c in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        targetProxy = AF975D54099CA0F000B05160 /* PBXContainerItemProxy */;
                };
+               AF98C0632F005FB900484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C0642F005FB900484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C07D2F00601700484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C0622F005FB900484F29 /* XShadertoy */;
+                       targetProxy = AF98C07C2F00601700484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C07F2F00604D00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C0782F00600400484F29 /* All Savers (Shadertoy) */;
+                       targetProxy = AF98C07E2F00604D00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0892F00644500484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C08A2F00644500484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0A42F00F1FA00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C0A52F00F1FA00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0C32F00F37B00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C0A32F00F1FA00484F29 /* HexPlasma */;
+                       targetProxy = AF98C0C22F00F37B00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0C52F00F38500484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C0882F00644500484F29 /* StarNest */;
+                       targetProxy = AF98C0C42F00F38500484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0C72F01C3E500484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C0C82F01C3E500484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0E62F01C57D00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C0C62F01C3E500484F29 /* StarDome */;
+                       targetProxy = AF98C0E52F01C57D00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C0E82F01F4AC00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C0E92F01F4AC00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C1072F01F70E00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C1082F01F70E00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C1262F01FA7A00484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C1272F01FA7A00484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C1452F01FE8800484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C1462F01FE8800484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C1642F02023600484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C1652F02023600484F29 /* PBXContainerItemProxy */;
+               };
+               AF98C1832F02063500484F29 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AF98C1842F02063500484F29 /* PBXContainerItemProxy */;
+               };
                AF998EDB0A083DB30051049D /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
                        target = AFAE146F279275BE00C62683 /* Squirtorus */;
                        targetProxy = AFAE148E2792774700C62683 /* PBXContainerItemProxy */;
                };
+               AFAF119A2F13446500449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF119B2F13446500449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF11B92F13459500449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF11BA2F13459500449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF11D82F1346CE00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF11D92F1346CE00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF11F72F13477F00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF11F82F13477F00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12162F13487300449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF12172F13487300449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12352F13495300449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF12362F13495300449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12542F134AA800449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF12552F134AA800449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12732F134B8800449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF12742F134B8800449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12922F134D8100449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF4808C0098C3B6C00FB32B8 /* jwxyz */;
+                       targetProxy = AFAF12932F134D8100449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12B32F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF11992F13446500449DD7 /* AlienBeacon */;
+                       targetProxy = AFAF12B22F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12B52F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF11B82F13459500449DD7 /* BatteredPlanet */;
+                       targetProxy = AFAF12B42F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12B72F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF11D72F1346CE00449DD7 /* ElementalRing */;
+                       targetProxy = AFAF12B62F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12B92F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF11F62F13477F00449DD7 /* FluxCore */;
+                       targetProxy = AFAF12B82F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12BB2F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF12152F13487300449DD7 /* GimbalHarmonics */;
+                       targetProxy = AFAF12BA2F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12BD2F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C1632F02023600484F29 /* LogarithmicCircles */;
+                       targetProxy = AFAF12BC2F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12BF2F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C1822F02063500484F29 /* NeonGravity */;
+                       targetProxy = AFAF12BE2F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12C12F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C1252F01FA7A00484F29 /* NeonTriangulator */;
+                       targetProxy = AFAF12C02F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12C32F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF12342F13495300449DD7 /* Protophore */;
+                       targetProxy = AFAF12C22F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12C52F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF12532F134AA800449DD7 /* SelfReflect */;
+                       targetProxy = AFAF12C42F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12C72F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF12722F134B8800449DD7 /* Skyline */;
+                       targetProxy = AFAF12C62F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12C92F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C0E72F01F4AC00484F29 /* StripeyTorus */;
+                       targetProxy = AFAF12C82F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12CB2F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C1442F01FE8800484F29 /* SynthwaveCity */;
+                       targetProxy = AFAF12CA2F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12CD2F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AFAF12912F134D8100449DD7 /* Topologica */;
+                       targetProxy = AFAF12CC2F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
+               AFAF12CF2F134EFB00449DD7 /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = AF98C1062F01F70E00484F29 /* TruchetZoom */;
+                       targetProxy = AFAF12CE2F134EFB00449DD7 /* PBXContainerItemProxy */;
+               };
                AFB581B0102F363300342B11 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = AFD571B50996D9DC00BA26F7 /* Juggle */;
                        };
                        name = Release;
                };
+               AF98C0742F005FB900484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C0752F005FB900484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C07A2F00600400484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C07B2F00600400484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C09A2F00644500484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C09B2F00644500484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C0B62F00F1FA00484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C0B72F00F1FA00484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C0D92F01C3E500484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C0DA2F01C3E500484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C0FA2F01F4AC00484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C0FB2F01F4AC00484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C1192F01F70E00484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C11A2F01F70E00484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C1382F01FA7A00484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C1392F01FA7A00484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C1572F01FE8800484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C1582F01FE8800484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C1762F02023600484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C1772F02023600484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AF98C1952F02063500484F29 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AF98C1962F02063500484F29 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AF998EEC0A083DB30051049D /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        };
                        name = Release;
                };
+               AFAF11AC2F13446500449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF11AD2F13446500449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF11CB2F13459500449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF11CC2F13459500449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF11EA2F1346CE00449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF11EB2F1346CE00449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF12092F13477F00449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF120A2F13477F00449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF12282F13487300449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF12292F13487300449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF12472F13495300449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF12482F13495300449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF12662F134AA800449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF12672F134AA800449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF12852F134B8800449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF12862F134B8800449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               AFAF12A62F134D8100449DD7 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               AFAF12A72F134D8100449DD7 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = (
+                                       "USE_GL=1",
+                                       "USE_SHADERTOY=1",
+                                       "$(GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS)",
+                               );
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
                AFB591B8178B812C00EA4005 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AF98C0732F005FB900484F29 /* Build configuration list for PBXNativeTarget "XShadertoy" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C0742F005FB900484F29 /* Debug */,
+                               AF98C0752F005FB900484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C0792F00600400484F29 /* Build configuration list for PBXAggregateTarget "All Savers (Shadertoy)" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C07A2F00600400484F29 /* Debug */,
+                               AF98C07B2F00600400484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C0992F00644500484F29 /* Build configuration list for PBXNativeTarget "StarNest" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C09A2F00644500484F29 /* Debug */,
+                               AF98C09B2F00644500484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C0B52F00F1FA00484F29 /* Build configuration list for PBXNativeTarget "HexPlasma" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C0B62F00F1FA00484F29 /* Debug */,
+                               AF98C0B72F00F1FA00484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C0D82F01C3E500484F29 /* Build configuration list for PBXNativeTarget "StarDome" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C0D92F01C3E500484F29 /* Debug */,
+                               AF98C0DA2F01C3E500484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C0F92F01F4AC00484F29 /* Build configuration list for PBXNativeTarget "StripeyTorus" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C0FA2F01F4AC00484F29 /* Debug */,
+                               AF98C0FB2F01F4AC00484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C1182F01F70E00484F29 /* Build configuration list for PBXNativeTarget "TruchetZoom" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C1192F01F70E00484F29 /* Debug */,
+                               AF98C11A2F01F70E00484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C1372F01FA7A00484F29 /* Build configuration list for PBXNativeTarget "NeonTriangulator" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C1382F01FA7A00484F29 /* Debug */,
+                               AF98C1392F01FA7A00484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C1562F01FE8800484F29 /* Build configuration list for PBXNativeTarget "SynthwaveCity" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C1572F01FE8800484F29 /* Debug */,
+                               AF98C1582F01FE8800484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C1752F02023600484F29 /* Build configuration list for PBXNativeTarget "LogarithmicCircles" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C1762F02023600484F29 /* Debug */,
+                               AF98C1772F02023600484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AF98C1942F02063500484F29 /* Build configuration list for PBXNativeTarget "NeonGravity" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AF98C1952F02063500484F29 /* Debug */,
+                               AF98C1962F02063500484F29 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AF998EEB0A083DB30051049D /* Build configuration list for PBXNativeTarget "TopBlock" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               AFAF11AB2F13446500449DD7 /* Build configuration list for PBXNativeTarget "AlienBeacon" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF11AC2F13446500449DD7 /* Debug */,
+                               AFAF11AD2F13446500449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF11CA2F13459500449DD7 /* Build configuration list for PBXNativeTarget "BatteredPlanet" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF11CB2F13459500449DD7 /* Debug */,
+                               AFAF11CC2F13459500449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF11E92F1346CE00449DD7 /* Build configuration list for PBXNativeTarget "ElementalRing" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF11EA2F1346CE00449DD7 /* Debug */,
+                               AFAF11EB2F1346CE00449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF12082F13477F00449DD7 /* Build configuration list for PBXNativeTarget "FluxCore" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF12092F13477F00449DD7 /* Debug */,
+                               AFAF120A2F13477F00449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF12272F13487300449DD7 /* Build configuration list for PBXNativeTarget "GimbalHarmonics" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF12282F13487300449DD7 /* Debug */,
+                               AFAF12292F13487300449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF12462F13495300449DD7 /* Build configuration list for PBXNativeTarget "Protophore" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF12472F13495300449DD7 /* Debug */,
+                               AFAF12482F13495300449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF12652F134AA800449DD7 /* Build configuration list for PBXNativeTarget "SelfReflect" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF12662F134AA800449DD7 /* Debug */,
+                               AFAF12672F134AA800449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF12842F134B8800449DD7 /* Build configuration list for PBXNativeTarget "Skyline" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF12852F134B8800449DD7 /* Debug */,
+                               AFAF12862F134B8800449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               AFAF12A52F134D8100449DD7 /* Build configuration list for PBXNativeTarget "Topologica" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               AFAF12A62F134D8100449DD7 /* Debug */,
+                               AFAF12A72F134D8100449DD7 /* Release */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                AFB591B7178B812C00EA4005 /* Build configuration list for PBXNativeTarget "Hexadrop" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/AlienBeacon.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/AlienBeacon.xcscheme
new file mode 100644 (file)
index 0000000..c5d5cc3
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF11992F13446500449DD7"
+               BuildableName = "AlienBeacon.saver"
+               BlueprintName = "AlienBeacon"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "AlienBeacon"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/BatteredPlanet.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/BatteredPlanet.xcscheme
new file mode 100644 (file)
index 0000000..94ea751
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF11B82F13459500449DD7"
+               BuildableName = "BatteredPlanet.saver"
+               BlueprintName = "BatteredPlanet"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "BatteredPlanet"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/ElementalRing.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/ElementalRing.xcscheme
new file mode 100644 (file)
index 0000000..10f8834
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF11D72F1346CE00449DD7"
+               BuildableName = "ElementalRing.saver"
+               BlueprintName = "ElementalRing"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "ElementalRing"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/FluxCore.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/FluxCore.xcscheme
new file mode 100644 (file)
index 0000000..9917fa6
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF11F62F13477F00449DD7"
+               BuildableName = "FluxCore.saver"
+               BlueprintName = "FluxCore"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "FluxCore"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/GimbalHarmonics.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/GimbalHarmonics.xcscheme
new file mode 100644 (file)
index 0000000..8031336
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF12152F13487300449DD7"
+               BuildableName = "GimbalHarmonics.saver"
+               BlueprintName = "GimbalHarmonics"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "GimbalHarmonics"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/HexPlasma.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/HexPlasma.xcscheme
new file mode 100644 (file)
index 0000000..7718c14
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C0A32F00F1FA00484F29"
+               BuildableName = "HexPlasma.saver"
+               BlueprintName = "HexPlasma"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "HexPlasma"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/LogarithmicCircles.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/LogarithmicCircles.xcscheme
new file mode 100644 (file)
index 0000000..5c1991c
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C1632F02023600484F29"
+               BuildableName = "LogarithmicCircles.saver"
+               BlueprintName = "LogarithmicCircles"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "LogarithmicCircles"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/NeonGravity.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/NeonGravity.xcscheme
new file mode 100644 (file)
index 0000000..6e66424
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C1822F02063500484F29"
+               BuildableName = "NeonGravity.saver"
+               BlueprintName = "NeonGravity"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "NeonGravity"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/NeonTriangulator.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/NeonTriangulator.xcscheme
new file mode 100644 (file)
index 0000000..66e6ca7
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C1252F01FA7A00484F29"
+               BuildableName = "NeonTriangulator.saver"
+               BlueprintName = "NeonTriangulator"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "NeonTriangulator"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Protophore.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Protophore.xcscheme
new file mode 100644 (file)
index 0000000..b523972
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF12342F13495300449DD7"
+               BuildableName = "Protophore.saver"
+               BlueprintName = "Protophore"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "Protophore"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/SelfReflect.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/SelfReflect.xcscheme
new file mode 100644 (file)
index 0000000..dcb39d6
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF12532F134AA800449DD7"
+               BuildableName = "SelfReflect.saver"
+               BlueprintName = "SelfReflect"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "SelfReflect"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Skyline.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Skyline.xcscheme
new file mode 100644 (file)
index 0000000..5ef8560
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF12722F134B8800449DD7"
+               BuildableName = "Skyline.saver"
+               BlueprintName = "Skyline"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "Skyline"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StarDome.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StarDome.xcscheme
new file mode 100644 (file)
index 0000000..2d8f3c4
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C0C62F01C3E500484F29"
+               BuildableName = "StarDome.saver"
+               BlueprintName = "StarDome"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "StarDome"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StarNest.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StarNest.xcscheme
new file mode 100644 (file)
index 0000000..aefaf53
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C0882F00644500484F29"
+               BuildableName = "StarNest.saver"
+               BlueprintName = "StarNest"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "StarNest"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StripeyTorus.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/StripeyTorus.xcscheme
new file mode 100644 (file)
index 0000000..9c0dfdb
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C0E72F01F4AC00484F29"
+               BuildableName = "StripeyTorus.saver"
+               BlueprintName = "StripeyTorus"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "StripeyTorus"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/SynthwaveCity.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/SynthwaveCity.xcscheme
new file mode 100644 (file)
index 0000000..e154d64
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C1442F01FE8800484F29"
+               BuildableName = "SynthwaveCity.saver"
+               BlueprintName = "SynthwaveCity"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "SynthwaveCity"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Topologica.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/Topologica.xcscheme
new file mode 100644 (file)
index 0000000..1aaf63b
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AFAF12912F134D8100449DD7"
+               BuildableName = "Topologica.saver"
+               BlueprintName = "Topologica"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "Topologica"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/TruchetZoom.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/TruchetZoom.xcscheme
new file mode 100644 (file)
index 0000000..4c993b0
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C1062F01F70E00484F29"
+               BuildableName = "TruchetZoom.saver"
+               BlueprintName = "TruchetZoom"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "TruchetZoom"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/XShadertoy.xcscheme b/OSX/xscreensaver.xcodeproj/xcshareddata/xcschemes/XShadertoy.xcscheme
new file mode 100644 (file)
index 0000000..ec4e9a0
--- /dev/null
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1620"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES"
+      buildArchitectures = "Automatic">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AF98C0622F005FB900484F29"
+               BuildableName = "XShadertoy.saver"
+               BlueprintName = "XShadertoy"
+               ReferencedContainer = "container:xscreensaver.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      shouldAutocreateTestPlan = "YES">
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <EnvironmentVariables>
+         <EnvironmentVariable
+            key = "SELECTED_SAVER"
+            value = "XShadertoy"
+            isEnabled = "YES">
+         </EnvironmentVariable>
+      </EnvironmentVariables>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AF9771D60989DC4A001F8B92"
+            BuildableName = "SaverTester.app"
+            BlueprintName = "SaverTester"
+            ReferencedContainer = "container:xscreensaver.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/README b/README
index 4199de03d8ce16bc5f1b6556fcb72e1b0dddf87e..8f248db739372ed6a8c66a49961a2950f99309a4 100644 (file)
--- a/README
+++ b/README
@@ -28,18 +28,22 @@ To compile for a Unix system with X11:
         ./configure --prefix=/usr
         make
         sudo make install
-        make clean
 
         xscreensaver &
         xscreensaver-settings
 
+    For a debug build:
+
+        make CFLAGS="-g"
+
     There are many compilation dependencies.  The configure script will tell
     you what is missing.  At the least, you will need development versions of
     these libraries.  Append "-dev" or "-devel" to most of these:
 
-        perl pkg-config gettext intltool libx11 libxext libxi libxt libxft
-        libxinerama libxrandr libxxf86vm libgl libglu libgle libgtk-3
-        libgdk-pixbuf2.0 libjpeg libxml2 libpam libsystemd elogind libwayland
+        perl attr pkg-config gettext intltool libx11 libxext libxi libxt
+        libxft libxinerama libxrandr libxxf86vm libgl libglu libgle
+        libgtk-3 libgdk-pixbuf-2.0 libjpeg libxml2 libpam libwayland
+        libsystemd elogind
 
     You can build a package-manager version with "make rpm" or "make deb".
 
@@ -71,7 +75,19 @@ Interested in writing a new screen saver?
 Version History
 ===============================================================================
 
-6.13   * Added a number of historical full chess games to `endgame`.
+6.14   * Added the ability to run shadertoy.com programs as screen savers.
+       * New shader-based savers: `alienbeacon', `batteredplanet',
+         `elementalring', `fluxcore', `gimbalharmonics', `hexplasma',
+         `logarithmiccircles', `neongravity', `neontriangulator',
+         `protophore', `selfreflect', `skyline', `stardome', `starnest',
+         `stripeytorus', `synthwavecity', `topologica' and `truchetzoom'.
+       * Better label wrapping in `carousel' and `photopile'.
+       * Fixed `glslideshow' preferences and title display.
+       * X11: Decrufted PAM, including /etc/pam.d/xscreensaver.
+       * macOS: Sparkle 2.8.
+       * iOS: Clicking links in preferences opens in Safari again.
+
+6.13   * Added a number of historical full chess games to `endgame'.
        * Rewrote `glslideshow' to add more image-transition effects.
         * Hacks that display images and their filenames will display their
           titles intead, if the image originated in an RSS feed (or has
index f7aa6ad9bb383e62d969c39e2fdeadacaa7ebcf8..857731cc28d46e894e0886347478f6a0aad27752 100644 (file)
@@ -61,6 +61,7 @@ ANDROID_BASE_HACKS=           \
 export ANDROID_HACKS=          \
        $(ANDROID_BASE_HACKS)   \
        abstractile             \
+       alienbeacon             \
        anemone                 \
        anemotaxis              \
        antinspect              \
@@ -71,6 +72,7 @@ export ANDROID_HACKS=         \
        attraction              \
        atunnel                 \
        barcode                 \
+       batteredplanet          \
        beats                   \
        binaryhorizon           \
        binaryring              \
@@ -124,6 +126,7 @@ export ANDROID_HACKS=               \
        droste                  \
        dumpsterfire            \
        dymaxionmap             \
+       elementalring           \
        endgame                 \
        energystream            \
        engine                  \
@@ -142,6 +145,7 @@ export ANDROID_HACKS=               \
        fliptext                \
        flow                    \
        fluidballs              \
+       fluxcore                \
        flyingtoasters          \
        fontglide               \
        fuzzyflakes             \
@@ -151,6 +155,7 @@ export ANDROID_HACKS=               \
        geodesicgears           \
        gflux                   \
        gibson                  \
+       gimbalharmonics         \
        glblur                  \
        glcells                 \
        gleidescope             \
@@ -172,12 +177,14 @@ export ANDROID_HACKS=             \
        headroom                \
        helix                   \
        hexadrop                \
+       hexplasma               \
        hexstrut                \
        hextrail                \
        highvoltage             \
        hilbert                 \
        hopalong                \
        hopffibration           \
+       hydrostat               \
        hypertorus              \
        hypnowheel              \
        ifs                     \
@@ -197,6 +204,8 @@ export ANDROID_HACKS=               \
        kumppa                  \
        lament                  \
        lavalite                \
+       lockward                \
+       logarithmiccircles      \
        loop                    \
        m6502                   \
        marbling                \
@@ -215,6 +224,8 @@ export ANDROID_HACKS=               \
        mountain                \
        munch                   \
        nakagin                 \
+       neongravity             \
+       neontriangulator        \
        nerverot                \
        noof                    \
        noseguy                 \
@@ -233,6 +244,7 @@ export ANDROID_HACKS=               \
        pong                    \
        popsquares              \
        projectiveplane         \
+       protophore              \
        providence              \
        pulsar                  \
        pyro                    \
@@ -250,10 +262,12 @@ export ANDROID_HACKS=             \
        rubikblocks             \
        sballs                  \
        scooter                 \
+       selfreflect             \
        shadebobs               \
        sierpinski              \
        sierpinski3d            \
        skulloop                \
+       skyline                 \
        skytentacles            \
        slidescreen             \
        slip                    \
@@ -265,20 +279,26 @@ export ANDROID_HACKS=             \
        squiral                 \
        squirtorus              \
        stairs                  \
+       stardome                \
+       starnest                \
        starwars                \
        stonerview              \
        strange                 \
+       stripeytorus            \
        substrate               \
        superquadrics           \
        surfaces                \
        swirl                   \
+       synthwavecity           \
        tangram                 \
        tessellimage            \
        timetunnel              \
        topblock                \
+       topologica              \
        triangle                \
        tronbit                 \
        truchet                 \
+       truchetzoom             \
        twang                   \
        unicrud                 \
        unknownpleasures        \
@@ -303,11 +323,17 @@ export ANDROID_HACKS=             \
 # These don't work well enough to turn on by default:
 #
 ANDROID_TODO=                  \
+       extrusion               \
+       flurry                  \
+       lcdscrub                \
        pedal                   \
        phosphor                \
        qix                     \
        speedmine               \
        starfish                \
+       mapscroller             \
+       vidwhacker              \
+       webcollage              \
 
 
 # If we are making the m6502 hack, create the header file for Android
@@ -326,7 +352,7 @@ images_png_h:
 # Largely duplicated in OSX/Makefile.
 # This saves us having to include 4MB of images in the tar file that
 # will only be used by a vast minority of people building from source.
-# Android actually wants these to be 160x160 but our source is 720p.
+# Android wants these to be 256x256 but our source is 720p.
 
 BASE = xscreensaver/screenshots/
 URL = https://cdn.jwz.org/$(BASE)
@@ -438,6 +464,7 @@ list_tarfiles:
                -o -name obj                    \
                -o -name settings.xml           \
                -o -name strings.xml            \
+               -o -name '*.glsl'               \
                \) -prune \)                    \
                -o \( \( -type f -o -type l \)  \
                      -print \)                 \
index 10a1f049c554a27753e3a21d52359f98aa13013c..4aae569cfd82153d532762b0dac07a16d8972005 100644 (file)
@@ -164,6 +164,7 @@ us know:
         xscreensaver/res/values/strings.xml
         xscreensaver/res/xml/*.xml
         xscreensaver/src/org/jwz/xscreensaver/gen/*.java
+        xscreensaver/assets/glsl/ (copied and stripped from hacks/glx/glsl/)
 
     Other files generated as a part of the build process:
 
@@ -302,6 +303,12 @@ When adding a new hack, edit android/Makefile, then "make clean" and "make".
     - petri is similar, except with tons of XFillRectangle, which, at two
       triangles each, is a lot of geometry.
 
+    - extrusion doesn't work because no libGLE.
+    - glitchpeg is just too hard.
+    - mapscroller requires perl.
+    - vidwhacker requires perl.
+    - webcollage requires perl.
+
   - Undiagnosed problems:
 
       - antinspect has some kind of masking problem. Maybe only in emulator?
@@ -309,6 +316,7 @@ When adding a new hack, edit android/Makefile, then "make clean" and "make".
       - discoball doesn't draw rays.
       - endgame is insanely slow.
       - esper images display as black.
+      - flurry is all black.
       - glblur is grayscale instead of color.  Endian or packing problem?
       - queens is insanely slow.
       - sonar doesn't display properly, but once it does, test icmp.
index 92f906629f10d5f5afc0a54810eede47efb1228b..de0c45f6b5f14b0999fa9b1456b4d62663249eb9 100644 (file)
@@ -131,6 +131,16 @@ LOCAL_SRC_FILES += \
     hacks/glx/whale.c \
     hacks/glx/sphereeversion-analytic.c \
     hacks/glx/sphereeversion-corrugations.c \
+    hacks/glx/xshadertoy.c \
+
+# These don't work well enough to turn on by default:
+#
+LOCAL_SRC_FILES_TODO = \
+    hacks/glx/flurry-smoke.c \
+    hacks/glx/flurry-spark.c \
+    hacks/glx/flurry-star.c \
+    hacks/glx/flurry-texture.c \
+
 
 # The source files of the currently active GL hacks:
 LOCAL_SRC_FILES += $(shell \
index b9eb7dd9c3b56a228d1663c9676249bef4005a6b..d0425fc2262b787df2cd656e79cb55a9c61b02a7 100644 (file)
@@ -1,5 +1,5 @@
 /* -*- Mode: java; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * xscreensaver, Copyright © 2016-2024 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright © 2016-2025 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -789,6 +789,37 @@ public class jwxyz
   }
 
 
+  // Returns a list of the asset files under the named subdir.
+  public String[] listAssetFiles (String dir) {
+    AssetManager am = app.getAssets();
+    String[] files = null;
+    try { files = am.list(dir); }
+    catch (Exception e) { LOG("listing assets: %s", e.toString()); }
+    LOG("listed assets in %s", dir);
+    return files;
+  }
+
+  // Returns the contents of the asset files "dir/file".
+  public String readAssetFile (String dir, String file) {
+    if (dir == null || file == null)
+      return null;
+    file = dir.concat("/").concat(file);
+    AssetManager am = app.getAssets();
+    try {
+      InputStream stream = am.open(file);
+      int size = stream.available();
+      byte[] buffer = new byte[size];
+      stream.read(buffer);
+      stream.close();
+      LOG("read asset %s", file);
+      return new String(buffer);
+    } catch (Exception e) {
+      LOG("reading asset %s: %s", file, e.toString());
+      return null;
+    }
+  }
+
+
   // Sadly duplicated from jwxyz.h (and thence X.h and keysymdef.h)
   //
   private static final int ShiftMask =    (1<<0);
index af949bb50526e34863248dbd45aef33b39003e79..591f5af34d082ddc0245568bda81da514cb9859e 100644 (file)
@@ -6,9 +6,6 @@
  */
 
 
-/* Define this to allow root to unlock, when not using PAM. */
-#undef ALLOW_ROOT_PASSWD
-
 /* Define to 1 if translation of program messages to the user's native
    language is requested. */
 #undef ENABLE_NLS
 /* Define this if OpenGL supports the OpenGL Shading Language. */
 #undef HAVE_GLSL
 
+/* Define this if you have the function glXGetProcAddressARB. */
+#undef HAVE_GLXGETPROCADDRESSARB
+
 /* Define this if you have Gtk 2.x. */
 #undef HAVE_GTK
 
 /* Define this if you have libsystemd. */
 #undef HAVE_LIBSYSTEMD
 
-/* Using the MIT-SCREEN-SAVER extension means that the X server will crash at
-   random times, and fading and hysteresis won't work. Don't use this. You'll
-   be sorry. See comment in xscreensaver.c. */
-#undef HAVE_MIT_SAVER_EXTENSION
-
 /* Define this if you have Motif. */
 #undef HAVE_MOTIF
 
 /* Define this if you have pam_fail_delay. */
 #undef HAVE_PAM_FAIL_DELAY
 
-/* Define this if you have a Linux-like /proc/interrupts file which can be
-   examined to determine when keyboard activity has occurred, and you use PS/2
-   input devices instead of USB. */
-#undef HAVE_PROC_INTERRUPTS
-
 /* Define this if you have a Linux-like /proc/.../oom_score_adj file which can
    be adjusted by root to exempt us from the out-of-memory killer. */
 #undef HAVE_PROC_OOM
 /* Define to 1 if you have the 'setrlimit' function. */
 #undef HAVE_SETRLIMIT
 
-/* Define this if you have the SGI SCREEN_SAVER extension. */
-#undef HAVE_SGI_SAVER_EXTENSION
-
-/* Define this if you have the SGI-VIDEO-CONTROL extension. */
-#undef HAVE_SGI_VC_EXTENSION
-
 /* Define this if your system uses /etc/shadow. */
 #undef HAVE_SHADOW_PASSWD
 
 /* Define this if you have the Wayland libraries. */
 #undef HAVE_WAYLAND
 
-/* Define this if you have XF86VidModeGetViewPort, for virtual desktops. */
-#undef HAVE_XF86VMODE
-
-/* Define this if you have XF86VidModeSetGamma, for fading. */
-#undef HAVE_XF86VMODE_GAMMA
-
-/* Define this if you have XF86VidModeSetGammaRamp, for fading. */
-#undef HAVE_XF86VMODE_GAMMA_RAMP
-
 /* Define this if you have libXft2. */
 #undef HAVE_XFT
 
    temporarily disabled. */
 #undef HAVE_XHPDISABLERESET
 
-/* Define this if you have the X11R5 XIDLE extension. */
-#undef HAVE_XIDLE_EXTENSION
-
 /* Define this if you have the Xinerama extension. */
 #undef HAVE_XINERAMA
 
 /* Define to the version of this package. */
 #undef PACKAGE_VERSION
 
-/* Whether PAM should check the result of account modules when authenticating.
-   */
-#undef PAM_CHECK_ACCOUNT_TYPE
-
 /* The name of the "xscreensaver" PAM service. */
 #undef PAM_SERVICE_NAME
 
index 871581edd1bc7f14961ce38e93d18bffa312a541..3152096a6c9ecf2458b6960c7219d0c6021153b3 100755 (executable)
--- a/configure
+++ b/configure
@@ -678,7 +678,6 @@ DEFAULT_IMAGE_DIRECTORY
 DEFAULT_IMAGES_P
 NEW_LOGIN_COMMAND_P
 NEW_LOGIN_COMMAND
-COMMENT_PAM_CHECK_ACCOUNT
 HAVE_PAM_FAIL_DELAY
 GLIB_COMPILE_RESOURCES
 INSTALL_PAM
@@ -864,27 +863,18 @@ with_hackdir
 with_configdir
 with_fontdir
 with_dpms_ext
-with_xf86vmode_ext
 with_xinerama_ext
 with_randr_ext
 with_xinput_ext
-with_xf86gamma_ext
-with_xidle_ext
-with_sgi_ext
-with_sgivc_ext
 with_xshm_ext
 with_xdbe_ext
 with_xkb_ext
-with_proc_interrupts
 with_proc_oom
 with_systemd
 with_elogind
 with_wayland
 enable_locking
-enable_root_passwd
 with_pam
-with_pam_service_name
-enable_pam_check_account_type
 with_kerberos
 with_shadow
 with_gtk
@@ -1472,8 +1462,6 @@ Defaults for the options are specified in brackets.
 
 Configuration:
   -h, --help              display this help and exit
-      --help=short        display options specific to this package
-      --help=recursive    display the short help of all the included packages
   -V, --version           display version information and exit
   -q, --quiet, --silent   do not print 'checking ...' messages
       --cache-file=FILE   cache test results in FILE [disabled]
@@ -1481,31 +1469,11 @@ Configuration:
   -n, --no-create         do not create output files
       --srcdir=DIR        find the sources in DIR [configure dir or '..']
 
-By default, 'make install' will install all the files in
-'$ac_default_prefix/bin', '$ac_default_prefix/lib' etc.  You can specify
-an installation prefix other than '$ac_default_prefix' using '--prefix',
-for instance '--prefix=\$HOME'.
-
-For better control, use the options below.
-
-Fine tuning of the installation directories:
-  --bindir=DIR            user executables [EPREFIX/bin]
-  --libexecdir=DIR        program executables [EPREFIX/libexec]
-  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
-  --libdir=DIR            object code libraries [EPREFIX/lib]
-  --includedir=DIR        C header files [PREFIX/include]
-  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
-  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
-  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
-  --mandir=DIR            man documentation [DATAROOTDIR/man]
-  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]
-_ACEOF
-
-  cat <<\_ACEOF
-
-X features:
-  --x-includes=DIR    X include files are in DIR
-  --x-libraries=DIR   X library files are in DIR
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
 
 System types:
   --build=BUILD     configure for building on BUILD [guessed]
@@ -1518,8 +1486,6 @@ if test -n "$ac_init_help"; then
 
   cat <<\_ACEOF
 
-  --enable-year2038       support timestamps after 2038
-
 Installation Options:
 
   --prefix=PREFIX         Install root of architecture-independent files.
@@ -1529,40 +1495,28 @@ Installation Options:
   --with-configdir=DIR    Where to install the GUI configuration files.
   --with-fontdir=DIR      Where to install the extra font files.
 
+Most of the following options default to "yes" if available.
+
 Server Extension Options:
 
   --with-dpms-ext         Include support for power management.
-  --with-xf86vmode-ext    Include support for virtual screens.
   --with-xinerama-ext     Include support for multiple monitors.
   --with-randr-ext        Include support for multiple monitors.
-  --with-xinput-ext       The XInput2 extension is required.
-  --with-xf86gamma-ext    Include support for XFree86 gamma fading.
-  --with-xidle-ext        Include support for the X11R5 XIDLE extension.
-  --with-sgi-ext          Include support for the SGI SCREEN_SAVER extension.
-  --with-sgivc-ext        Include support for the SGI-VIDEO-CONTROL extension.
   --with-xshm-ext         Include support for the Shared Memory extension.
   --with-xdbe-ext         Include support for the DOUBLE-BUFFER extension.
   --with-xkb-ext          Include support for the X Keyboard extension.
-  --with-proc-interrupts  Include support for consulting /proc/interrupts to
-                          notice activity on PS/2 keyboards and mice.
-  --with-proc-oom         Include support to duck the out-of-memory killer.
+  --with-proc-oom         Include support to avoid the out-of-memory killer.
   --with-systemd          Support systemd requests to lock on suspend, and to
                           allow video players to inhibit the screen saver.
-  --with-elogind          Use elogind instead of systemd.
+  --with-elogind          Use elogind for that instead of systemd.
   --with-wayland          Use native Wayland when available.
 
 Screen Locking Options:
 
   --disable-locking       Do not allow locking of the display at all.
   --with-pam              Use Pluggable Authentication Modules.
-  --with-pam-service-name Set the name of the xscreensaver PAM service.
-  --enable-pam-check-account-type
-                          Whether PAM should check the result of account
-                          modules when authenticating.  Only do this if you
-                          have "account" modules configured on your system.
-  --enable-root-passwd    Allow the root password to unlock, if not using PAM.
-  --with-kerberos         Include support for Kerberos authentication.
-  --with-shadow           Include support for shadow password authentication.
+  --with-kerberos         Use Kerberos authentication instead.
+  --with-shadow           Use shadow password authentication instead.
 
 User Interface Options:
 
@@ -1579,7 +1533,6 @@ Graphics Options:
   --with-gles             Emulate OpenGL 1.3 in terms of OpenGL ES 1.x.
                           Do not do this: it doesn't mean what you think.
   --with-glx              Use GLX to interface OpenGL and X11 instead of EGL.
-                          Do not do this: it will make GLSL fail.
   --with-gle              Include support for the GL Extrusion library.
   --with-jpeg             Include support for the JPEG library.
   --with-png              Include support for the PNG library.
@@ -1600,12 +1553,10 @@ Some influential environment variables:
   CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
               you have headers in a nonstandard directory <include dir>
   CPP         C preprocessor
-  XMKMF       Path to xmkmf, Makefile generator for X Window System
 
 Use these variables to override the choices made by 'configure' or to help
 it to find libraries and programs with nonstandard names/locations.
 
-Report bugs to the package provider.
 _ACEOF
 ac_status=$?
 fi
@@ -2894,11 +2845,11 @@ fi
 # X11 server stuff.
 #
 
-# This only ever existed in X11R4 and X11R5.
+#AH_TEMPLATE([HAVE_XF86VMODE_GAMMA],
+#          [Define this if you have XF86VidModeSetGamma, for fading.])
 
-# This only ever existed on SGI hardware.
-
-# This only ever existed on SGI hardware.
+#AH_TEMPLATE([HAVE_XF86VMODE_GAMMA_RAMP],
+#          [Define this if you have XF86VidModeSetGammaRamp, for fading.])
 
 #AH_TEMPLATE([HAVE_XCOMPOSITE_EXTENSION],
 #          [Define this if you have the X Composite Extension.])
@@ -2919,6 +2870,9 @@ fi
 # Locking.
 #
 
+#AH_TEMPLATE([ALLOW_ROOT_PASSWD],
+#          [Define this to allow root to unlock, when not using PAM.])
+
 # After checking to see that --srcdir is correct (which AC_INIT does)
 # check for some random other files that come later in the tar file,
 # to make sure everything is here.
@@ -10622,180 +10576,6 @@ elif test "$with_dpms" != no; then
   exit 1
 fi
 
-###############################################################################
-#
-#       Check for the XF86VMODE server extension (for virtual screens.)
-#
-###############################################################################
-
-have_xf86vmode=no
-with_xf86vmode_req=unspecified
-
-# Check whether --with-xf86vmode-ext was given.
-if test ${with_xf86vmode_ext+y}
-then :
-  withval=$with_xf86vmode_ext; with_xf86vmode="$withval"; with_xf86vmode_req="$withval"
-else case e in #(
-  e) with_xf86vmode=yes ;;
-esac
-fi
-
-   case "$with_xf86vmode" in
-    yes) ;;
-    no)  ;;
-
-    /*)
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for xf86vmode headers" >&5
-printf %s "checking for xf86vmode headers... " >&6; }
-     d=$with_xf86vmode/include
-     if test -d $d; then
-       X_CFLAGS="-I$d $X_CFLAGS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for xf86vmode libs" >&5
-printf %s "checking for xf86vmode libs... " >&6; }
-     d=$with_xf86vmode/lib
-     if test -d $d; then
-       X_LIBS="-L$d $X_LIBS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     # replace the directory string with "yes".
-     with_xf86vmode_req="yes"
-     with_xf86vmode=$with_xf86vmode_req
-     ;;
-
-    *)
-     echo ""
-     echo "error: argument to --with-xf86vmode-ext must be \"yes\", \"no\", or a directory."
-     echo "       If it is a directory, then \`DIR/include' will be added to"
-     echo "       the -I list, and \`DIR/lib' will be added to the -L list."
-     exit 1
-     ;;
-   esac
-
-VIDMODE_LIBS=""
-
-if test "$with_xf86vmode" = yes; then
-
-  # first check for xf86vmode.h
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  ac_fn_c_check_header_compile "$LINENO" "X11/extensions/xf86vmode.h" "ac_cv_header_X11_extensions_xf86vmode_h" "#include <X11/Xlib.h>
-"
-if test "x$ac_cv_header_X11_extensions_xf86vmode_h" = xyes
-then :
-  have_xf86vmode=yes
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-
-  # if that succeeded, then check for the -lXxf86vm
-  if test "$have_xf86vmode" = yes; then
-    have_xf86vmode=no
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XF86VidModeGetViewPort in -lXxf86vm" >&5
-printf %s "checking for XF86VidModeGetViewPort in -lXxf86vm... " >&6; }
-if test ${ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXxf86vm -lXext -lX11 $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XF86VidModeGetViewPort (void);
-int
-main (void)
-{
-return XF86VidModeGetViewPort ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort=yes
-else case e in #(
-  e) ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort" >&5
-printf "%s\n" "$ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort" >&6; }
-if test "x$ac_cv_lib_Xxf86vm_XF86VidModeGetViewPort" = xyes
-then :
-  have_xf86vmode=yes;
-                   VIDMODE_LIBS="-lXxf86vm";
-                   SAVER_LIBS="$SAVER_LIBS $VIDMODE_LIBS"
-else case e in #(
-  e) true ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-  fi
-
-  # if that succeeded, then we've really got it.
-  if test "$have_xf86vmode" = yes; then
-    printf "%s\n" "#define HAVE_XF86VMODE 1" >>confdefs.h
-
-  fi
-
-elif test "$with_xf86vmode" != no; then
-  echo "error: must be yes or no: --with-xf86vmode-ext=$with_xf86vmode"
-  exit 1
-fi
-
 ###############################################################################
 #
 #       Check for the XINERAMA server extension.
@@ -11572,899 +11352,10 @@ esac
 fi
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xi_XISelectEvents" >&5
 printf "%s\n" "$ac_cv_lib_Xi_XISelectEvents" >&6; }
-if test "x$ac_cv_lib_Xi_XISelectEvents" = xyes
-then :
-  have_xinput=yes; xinput_halfassed=no;
-                    SAVER_LIBS="$SAVER_LIBS -lXi"
-else case e in #(
-  e) true ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-  fi
-
-  # if that succeeded, then we've really got it.
-  if test "$have_xinput" = yes; then
-    printf "%s\n" "#define HAVE_XINPUT 1" >>confdefs.h
-
-  fi
-
-elif test "$with_xinput" = no; then
-  echo "error: --without-xinput-ext is not supported."
-  exit 1
-
-elif test "$with_xinput" != no; then
-  echo "error: must be yes or no: --with-xinput-ext=$with_xinput"
-  exit 1
-fi
-
-###############################################################################
-#
-#       Check for the XF86VMODE server extension (for gamma fading.)
-#
-###############################################################################
-
-have_xf86gamma=no
-have_xf86gamma_ramp=no
-with_xf86gamma_req=unspecified
-
-# Check whether --with-xf86gamma-ext was given.
-if test ${with_xf86gamma_ext+y}
-then :
-  withval=$with_xf86gamma_ext; with_xf86gamma="$withval"; with_xf86gamma_req="$withval"
-else case e in #(
-  e) with_xf86gamma=yes ;;
-esac
-fi
-
-   case "$with_xf86gamma" in
-    yes) ;;
-    no)  ;;
-
-    /*)
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for xf86gamma headers" >&5
-printf %s "checking for xf86gamma headers... " >&6; }
-     d=$with_xf86gamma/include
-     if test -d $d; then
-       X_CFLAGS="-I$d $X_CFLAGS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for xf86gamma libs" >&5
-printf %s "checking for xf86gamma libs... " >&6; }
-     d=$with_xf86gamma/lib
-     if test -d $d; then
-       X_LIBS="-L$d $X_LIBS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     # replace the directory string with "yes".
-     with_xf86gamma_req="yes"
-     with_xf86gamma=$with_xf86gamma_req
-     ;;
-
-    *)
-     echo ""
-     echo "error: argument to --with-xf86gamma-ext must be \"yes\", \"no\", or a directory."
-     echo "       If it is a directory, then \`DIR/include' will be added to"
-     echo "       the -I list, and \`DIR/lib' will be added to the -L list."
-     exit 1
-     ;;
-   esac
-
-if test "$with_xf86gamma" = yes; then
-
-  # first check for xf86vmode.h, if we haven't already
-  if test "$have_xf86vmode" = yes; then
-    have_xf86gamma=yes
-  else
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  ac_fn_c_check_header_compile "$LINENO" "X11/extensions/xf86vmode.h" "ac_cv_header_X11_extensions_xf86vmode_h" "#include <X11/Xlib.h>
-"
-if test "x$ac_cv_header_X11_extensions_xf86vmode_h" = xyes
-then :
-  have_xf86gamma=yes
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  fi
-
-  # if that succeeded, then check for the -lXxf86vm
-  if test "$have_xf86gamma" = yes; then
-    have_xf86gamma=no
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XF86VidModeSetGamma in -lXxf86vm" >&5
-printf %s "checking for XF86VidModeSetGamma in -lXxf86vm... " >&6; }
-if test ${ac_cv_lib_Xxf86vm_XF86VidModeSetGamma+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXxf86vm -lXext -lX11 $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XF86VidModeSetGamma (void);
-int
-main (void)
-{
-return XF86VidModeSetGamma ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_Xxf86vm_XF86VidModeSetGamma=yes
-else case e in #(
-  e) ac_cv_lib_Xxf86vm_XF86VidModeSetGamma=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xxf86vm_XF86VidModeSetGamma" >&5
-printf "%s\n" "$ac_cv_lib_Xxf86vm_XF86VidModeSetGamma" >&6; }
-if test "x$ac_cv_lib_Xxf86vm_XF86VidModeSetGamma" = xyes
-then :
-  have_xf86gamma=yes
-else case e in #(
-  e) true ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-  fi
-
-  # check for the Ramp versions of the functions too.
-  if test "$have_xf86gamma" = yes; then
-    have_xf86gamma_ramp=no
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XF86VidModeSetGammaRamp in -lXxf86vm" >&5
-printf %s "checking for XF86VidModeSetGammaRamp in -lXxf86vm... " >&6; }
-if test ${ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXxf86vm -lXext -lX11 $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XF86VidModeSetGammaRamp (void);
-int
-main (void)
-{
-return XF86VidModeSetGammaRamp ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp=yes
-else case e in #(
-  e) ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp" >&5
-printf "%s\n" "$ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp" >&6; }
-if test "x$ac_cv_lib_Xxf86vm_XF86VidModeSetGammaRamp" = xyes
-then :
-  have_xf86gamma_ramp=yes
-else case e in #(
-  e) true ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-  fi
-
-  # if those tests succeeded, then we've really got the functions.
-  if test "$have_xf86gamma" = yes; then
-    printf "%s\n" "#define HAVE_XF86VMODE_GAMMA 1" >>confdefs.h
-
-  fi
-
-  if test "$have_xf86gamma_ramp" = yes; then
-    printf "%s\n" "#define HAVE_XF86VMODE_GAMMA_RAMP 1" >>confdefs.h
-
-  fi
-
-  # pull in the lib, if we haven't already
-  if test "$have_xf86gamma" = yes -a "$have_xf86vmode" = no; then
-    SAVER_LIBS="$SAVER_LIBS -lXxf86vm"
-  fi
-
-elif test "$with_xf86gamma" != no; then
-  echo "error: must be yes or no: --with-xf86gamma-ext=$with_xf86vmode"
-  exit 1
-fi
-
-###############################################################################
-#
-#       Check for the XIDLE server extension.
-#
-###############################################################################
-
-have_xidle=no
-with_xidle_req=unspecified
-
-# Check whether --with-xidle-ext was given.
-if test ${with_xidle_ext+y}
-then :
-  withval=$with_xidle_ext; with_xidle="$withval"; with_xidle_req="$withval"
-else case e in #(
-  e) with_xidle=yes ;;
-esac
-fi
-
-   case "$with_xidle" in
-    yes) ;;
-    no)  ;;
-
-    /*)
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XIDLE headers" >&5
-printf %s "checking for XIDLE headers... " >&6; }
-     d=$with_xidle/include
-     if test -d $d; then
-       X_CFLAGS="-I$d $X_CFLAGS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XIDLE libs" >&5
-printf %s "checking for XIDLE libs... " >&6; }
-     d=$with_xidle/lib
-     if test -d $d; then
-       X_LIBS="-L$d $X_LIBS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     # replace the directory string with "yes".
-     with_xidle_req="yes"
-     with_xidle=$with_xidle_req
-     ;;
-
-    *)
-     echo ""
-     echo "error: argument to --with-xidle-ext must be \"yes\", \"no\", or a directory."
-     echo "       If it is a directory, then \`DIR/include' will be added to"
-     echo "       the -I list, and \`DIR/lib' will be added to the -L list."
-     exit 1
-     ;;
-   esac
-
-if test "$with_xidle" = yes; then
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  ac_fn_c_check_header_compile "$LINENO" "X11/extensions/xidle.h" "ac_cv_header_X11_extensions_xidle_h" "#include <X11/Xlib.h>
-"
-if test "x$ac_cv_header_X11_extensions_xidle_h" = xyes
-then :
-  have_xidle=yes
-                     printf "%s\n" "#define HAVE_XIDLE_EXTENSION 1" >>confdefs.h
-
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-elif test "$with_xidle" != no; then
-  echo "error: must be yes or no: --with-xidle-ext=$with_xidle"
-  exit 1
-fi
-
-###############################################################################
-#
-#       Check for the MIT-SCREEN-SAVER server extension.
-#
-###############################################################################
-
-have_mit=no
-with_mit=no
-with_mit_req=unspecified
-#AC_ARG_WITH(mit-ext,
-#[  --with-mit-ext          Include support for the MIT-SCREEN-SAVER extension.],
-#  [with_mit="$withval"; with_mit_req="$withval"],[with_mit=no])
-#HANDLE_X_PATH_ARG(with_mit, --with-mit-ext, MIT-SCREEN-SAVER)
-
-if test "$with_mit" = yes; then
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  ac_fn_c_check_header_compile "$LINENO" "X11/extensions/scrnsaver.h" "ac_cv_header_X11_extensions_scrnsaver_h" "#include <X11/Xlib.h>
-"
-if test "x$ac_cv_header_X11_extensions_scrnsaver_h" = xyes
-then :
-  have_mit=yes
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-
-  # Now check to see if it's really in the library; XF86Free-3.3 ships
-  # scrnsaver.h, but doesn't include the code in libXext.a, the idiots!
-  #
-  if test "$have_mit" = yes; then
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XScreenSaverRegister in -lXext" >&5
-printf %s "checking for XScreenSaverRegister in -lXext... " >&6; }
-if test ${ac_cv_lib_Xext_XScreenSaverRegister+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXext -lm $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XScreenSaverRegister (void);
-int
-main (void)
-{
-return XScreenSaverRegister ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_Xext_XScreenSaverRegister=yes
-else case e in #(
-  e) ac_cv_lib_Xext_XScreenSaverRegister=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xext_XScreenSaverRegister" >&5
-printf "%s\n" "$ac_cv_lib_Xext_XScreenSaverRegister" >&6; }
-if test "x$ac_cv_lib_Xext_XScreenSaverRegister" = xyes
-then :
-  true
-else case e in #(
-  e) have_mit=no ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-    if test "$have_mit" = no; then
-      # Fuck!  Looks like XF86Free-3.3 actually puts it in XExExt instead
-      # of in Xext.  Thank you master, may I have another.
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XScreenSaverRegister in -lXExExt" >&5
-printf %s "checking for XScreenSaverRegister in -lXExExt... " >&6; }
-if test ${ac_cv_lib_XExExt_XScreenSaverRegister+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXExExt -lX11 -lXext -lm $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XScreenSaverRegister (void);
-int
-main (void)
-{
-return XScreenSaverRegister ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_XExExt_XScreenSaverRegister=yes
-else case e in #(
-  e) ac_cv_lib_XExExt_XScreenSaverRegister=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_XExExt_XScreenSaverRegister" >&5
-printf "%s\n" "$ac_cv_lib_XExExt_XScreenSaverRegister" >&6; }
-if test "x$ac_cv_lib_XExExt_XScreenSaverRegister" = xyes
-then :
-  have_mit=yes; SAVER_LIBS="$SAVER_LIBS -lXExExt"
-else case e in #(
-  e) true ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-    fi
-
-    if test "$have_mit" = no; then
-      # Double fuck!  Looks like some versions of XFree86 (whichever version
-      # it is that comes with RedHat Linux 2.0 -- I can't find a version
-      # number) put this garbage in Xss instead of Xext.  Thank you master,
-      #  may I have another.
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XScreenSaverRegister in -lXss" >&5
-printf %s "checking for XScreenSaverRegister in -lXss... " >&6; }
-if test ${ac_cv_lib_Xss_XScreenSaverRegister+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXss -lX11 -lXext -lm $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XScreenSaverRegister (void);
-int
-main (void)
-{
-return XScreenSaverRegister ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_Xss_XScreenSaverRegister=yes
-else case e in #(
-  e) ac_cv_lib_Xss_XScreenSaverRegister=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xss_XScreenSaverRegister" >&5
-printf "%s\n" "$ac_cv_lib_Xss_XScreenSaverRegister" >&6; }
-if test "x$ac_cv_lib_Xss_XScreenSaverRegister" = xyes
-then :
-  have_mit=yes; SAVER_LIBS="$SAVER_LIBS -lXss"
-else case e in #(
-  e) true ;;
-esac
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-  LDFLAGS="$ac_save_LDFLAGS"
-#  LIBS="$ac_save_LIBS"
-
-    fi
-
-    if test "$have_mit" = yes; then
-#     AC_DEFINE(HAVE_MIT_SAVER_EXTENSION)
-      echo "Using the MIT-SCREEN-SAVER extension will crash your server. Don't."
-      exit 1
-    fi
-
-  fi
-
-elif test "$with_mit" != no; then
-  echo "error: must be yes or no: --with-mit-ext=$with_mit"
-  exit 1
-fi
-
-###############################################################################
-#
-#       Check for the SGI SCREEN_SAVER server extension.
-#
-###############################################################################
-
-have_sgi=no
-with_sgi_req=unspecified
-
-# Check whether --with-sgi-ext was given.
-if test ${with_sgi_ext+y}
-then :
-  withval=$with_sgi_ext; with_sgi="$withval"; with_sgi_req="$withval"
-else case e in #(
-  e) with_sgi=$ac_irix ;;
-esac
-fi
-
-   case "$with_sgi" in
-    yes) ;;
-    no)  ;;
-
-    /*)
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SGI SCREEN_SAVER headers" >&5
-printf %s "checking for SGI SCREEN_SAVER headers... " >&6; }
-     d=$with_sgi/include
-     if test -d $d; then
-       X_CFLAGS="-I$d $X_CFLAGS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SGI SCREEN_SAVER libs" >&5
-printf %s "checking for SGI SCREEN_SAVER libs... " >&6; }
-     d=$with_sgi/lib
-     if test -d $d; then
-       X_LIBS="-L$d $X_LIBS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     # replace the directory string with "yes".
-     with_sgi_req="yes"
-     with_sgi=$with_sgi_req
-     ;;
-
-    *)
-     echo ""
-     echo "error: argument to --with-sgi-ext must be \"yes\", \"no\", or a directory."
-     echo "       If it is a directory, then \`DIR/include' will be added to"
-     echo "       the -I list, and \`DIR/lib' will be added to the -L list."
-     exit 1
-     ;;
-   esac
-
-if test "$with_sgi" = yes; then
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  ac_fn_c_check_header_compile "$LINENO" "X11/extensions/XScreenSaver.h" "ac_cv_header_X11_extensions_XScreenSaver_h" "#include <X11/Xlib.h>
-"
-if test "x$ac_cv_header_X11_extensions_XScreenSaver_h" = xyes
-then :
-  have_sgi=yes
-                     printf "%s\n" "#define HAVE_SGI_SAVER_EXTENSION 1" >>confdefs.h
-
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-
-elif test "$with_sgi" != no; then
-  echo "error: must be yes or no: --with-sgi-ext=$with_sgi"
-  exit 1
-fi
-
-###############################################################################
-#
-#       Check for the SGI-VIDEO-CONTROL server extension.
-#
-###############################################################################
-
-have_sgivc=no
-with_sgivc_req=unspecified
-
-# Check whether --with-sgivc-ext was given.
-if test ${with_sgivc_ext+y}
-then :
-  withval=$with_sgivc_ext; with_sgivc="$withval"; with_sgivc_req="$withval"
-else case e in #(
-  e) with_sgivc=$ac_irix ;;
-esac
-fi
-
-   case "$with_sgivc" in
-    yes) ;;
-    no)  ;;
-
-    /*)
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SGI-VIDEO-CONTROL headers" >&5
-printf %s "checking for SGI-VIDEO-CONTROL headers... " >&6; }
-     d=$with_sgivc/include
-     if test -d $d; then
-       X_CFLAGS="-I$d $X_CFLAGS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SGI-VIDEO-CONTROL libs" >&5
-printf %s "checking for SGI-VIDEO-CONTROL libs... " >&6; }
-     d=$with_sgivc/lib
-     if test -d $d; then
-       X_LIBS="-L$d $X_LIBS"
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $d" >&5
-printf "%s\n" "$d" >&6; }
-     else
-       { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: not found ($d: no such directory)" >&5
-printf "%s\n" "not found ($d: no such directory)" >&6; }
-     fi
-
-     # replace the directory string with "yes".
-     with_sgivc_req="yes"
-     with_sgivc=$with_sgivc_req
-     ;;
-
-    *)
-     echo ""
-     echo "error: argument to --with-sgivc-ext must be \"yes\", \"no\", or a directory."
-     echo "       If it is a directory, then \`DIR/include' will be added to"
-     echo "       the -I list, and \`DIR/lib' will be added to the -L list."
-     exit 1
-     ;;
-   esac
-
-if test "$with_sgivc" = yes; then
-
-  # first check for XSGIvc.h
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  ac_fn_c_check_header_compile "$LINENO" "X11/extensions/XSGIvc.h" "ac_cv_header_X11_extensions_XSGIvc_h" "#include <X11/Xlib.h>
-"
-if test "x$ac_cv_header_X11_extensions_XSGIvc_h" = xyes
-then :
-  have_sgivc=yes
-fi
-
-  CPPFLAGS="$ac_save_CPPFLAGS"
-
-  # if that succeeded, then check for the -lXsgivc
-  if test "$have_sgivc" = yes; then
-    have_sgivc=no
-
-  ac_save_CPPFLAGS="$CPPFLAGS"
-  ac_save_LDFLAGS="$LDFLAGS"
-#  ac_save_LIBS="$LIBS"
-
-  if test \! -z "$includedir" ; then
-    CPPFLAGS="$CPPFLAGS -I$includedir"
-  fi
-  # note: $X_CFLAGS includes $x_includes
-  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
-
-  if test \! -z "$libdir" ; then
-    LDFLAGS="$LDFLAGS -L$libdir"
-  fi
-  # note: $X_LIBS includes $x_libraries
-  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
-
-  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
-  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for XSGIvcQueryGammaMap in -lXsgivc" >&5
-printf %s "checking for XSGIvcQueryGammaMap in -lXsgivc... " >&6; }
-if test ${ac_cv_lib_Xsgivc_XSGIvcQueryGammaMap+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lXsgivc -lXext -lX11 $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-/* Override any GCC internal prototype to avoid an error.
-   Use char because int might match the return type of a GCC
-   builtin and then its argument prototype would still apply.
-   The 'extern "C"' is for builds by C++ compilers;
-   although this is not generally supported in C code supporting it here
-   has little cost and some practical benefit (sr 110532).  */
-#ifdef __cplusplus
-extern "C"
-#endif
-char XSGIvcQueryGammaMap (void);
-int
-main (void)
-{
-return XSGIvcQueryGammaMap ();
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"
-then :
-  ac_cv_lib_Xsgivc_XSGIvcQueryGammaMap=yes
-else case e in #(
-  e) ac_cv_lib_Xsgivc_XSGIvcQueryGammaMap=no ;;
-esac
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam \
-    conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xsgivc_XSGIvcQueryGammaMap" >&5
-printf "%s\n" "$ac_cv_lib_Xsgivc_XSGIvcQueryGammaMap" >&6; }
-if test "x$ac_cv_lib_Xsgivc_XSGIvcQueryGammaMap" = xyes
+if test "x$ac_cv_lib_Xi_XISelectEvents" = xyes
 then :
-  have_sgivc=yes; SAVER_LIBS="$SAVER_LIBS -lXsgivc"
+  have_xinput=yes; xinput_halfassed=no;
+                    SAVER_LIBS="$SAVER_LIBS -lXi"
 else case e in #(
   e) true ;;
 esac
   fi
 
   # if that succeeded, then we've really got it.
-  if test "$have_sgivc" = yes; then
-    printf "%s\n" "#define HAVE_SGI_VC_EXTENSION 1" >>confdefs.h
+  if test "$have_xinput" = yes; then
+    printf "%s\n" "#define HAVE_XINPUT 1" >>confdefs.h
 
   fi
 
-elif test "$with_sgivc" != no; then
-  echo "error: must be yes or no: --with-sgivc-ext=$with_sgivc"
+elif test "$with_xinput" = no; then
+  echo "error: --without-xinput-ext is not supported."
+  exit 1
+
+elif test "$with_xinput" != no; then
+  echo "error: must be yes or no: --with-xinput-ext=$with_xinput"
   exit 1
 fi
 
+###############################################################################
+#
+#       Check for the XF86VMODE server extension (for gamma fading.)
+#
+###############################################################################
+
+#have_xf86gamma=no
+#have_xf86gamma_ramp=no
+#with_xf86gamma_req=unspecified
+#AC_ARG_WITH(xf86gamma-ext,
+#[  --with-xf86gamma-ext    Include support for XFree86 gamma fading.],
+#  [with_xf86gamma="$withval"; with_xf86gamma_req="$withval"],
+#  [with_xf86gamma=yes])
+#
+#HANDLE_X_PATH_ARG(with_xf86gamma, --with-xf86gamma-ext, xf86gamma)
+#
+#if test "$with_xf86gamma" = yes; then
+#
+#  # first check for xf86vmode.h, if we haven't already
+#  if test "$have_xf86vmode" = yes; then
+#    have_xf86gamma=yes
+#  else
+#    AC_CHECK_X_HEADER(X11/extensions/xf86vmode.h, [have_xf86gamma=yes],,
+#                      [#include <X11/Xlib.h>])
+#  fi
+#
+#  # if that succeeded, then check for the -lXxf86vm
+#  if test "$have_xf86gamma" = yes; then
+#    have_xf86gamma=no
+#    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGamma,
+#                  [have_xf86gamma=yes],
+#                   [true], -lXext -lX11)
+#  fi
+#
+#  # check for the Ramp versions of the functions too.
+#  if test "$have_xf86gamma" = yes; then
+#    have_xf86gamma_ramp=no
+#    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGammaRamp,
+#                  [have_xf86gamma_ramp=yes],
+#                   [true], -lXext -lX11)
+#  fi
+#
+#  # if those tests succeeded, then we've really got the functions.
+#  if test "$have_xf86gamma" = yes; then
+#    AC_DEFINE(HAVE_XF86VMODE_GAMMA)
+#  fi
+#
+#  if test "$have_xf86gamma_ramp" = yes; then
+#    AC_DEFINE(HAVE_XF86VMODE_GAMMA_RAMP)
+#  fi
+#
+#  # pull in the lib, if we haven't already
+#  if test "$have_xf86gamma" = yes -a "$have_xf86vmode" = no; then
+#    SAVER_LIBS="$SAVER_LIBS -lXxf86vm"
+#  fi
+#
+#elif test "$with_xf86gamma" != no; then
+#  echo "error: must be yes or no: --with-xf86gamma-ext=$with_xf86vmode"
+#  exit 1
+#fi
+
 ###############################################################################
 #
 #       Check for the XSHM server extension.
@@ -12944,61 +11900,6 @@ rm -rf conftest*
 
   CPPFLAGS="$ac_save_CPPFLAGS"
 
-###############################################################################
-#
-#       Check for /proc/interrupts.
-#
-###############################################################################
-
-have_proc_interrupts=no
-with_proc_interrupts_req=unspecified
-
-# Check whether --with-proc-interrupts was given.
-if test ${with_proc_interrupts+y}
-then :
-  withval=$with_proc_interrupts; with_proc_interrupts="$withval"; with_proc_interrupts_req="$withval"
-else case e in #(
-  e) with_proc_interrupts=no ;;
-esac
-fi
-
-if test "$with_proc_interrupts" = yes; then
-
-  # Note that we may be building in an environment (e.g. Debian buildd chroot)
-  # without a proper /proc filesystem. If /proc/interrupts exists, then we'll
-  # check that it has the bits we need, but otherwise we'll just go on faith.
-  #
-  have_proc_interrupts=yes
-
-  if test -f /proc/interrupts; then
-   { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking whether /proc/interrupts contains keyboard data" >&5
-printf %s "checking whether /proc/interrupts contains keyboard data... " >&6; }
-if test ${ac_cv_have_proc_interrupts+y}
-then :
-  printf %s "(cached) " >&6
-else case e in #(
-  e) ac_cv_have_proc_interrupts=no
-     if grep 'keyboard\|i8042' /proc/interrupts >/dev/null 2>&1 ; then
-       ac_cv_have_proc_interrupts=yes
-     fi
-     ;;
-esac
-fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_have_proc_interrupts" >&5
-printf "%s\n" "$ac_cv_have_proc_interrupts" >&6; }
-   have_proc_interrupts=$ac_cv_have_proc_interrupts
-  fi
-
-  if test "$have_proc_interrupts" = yes; then
-    printf "%s\n" "#define HAVE_PROC_INTERRUPTS 1" >>confdefs.h
-
-  fi
-
-elif test "$with_proc_interrupts" != no; then
-  echo "error: must be yes or no: --with-proc-interrupts=$with_proc_interrupts"
-  exit 1
-fi
-
 ###############################################################################
 #
 #       Check for /proc/*/oom_score_adj.
 #
 ###############################################################################
 
-# Check whether --enable-root-passwd was given.
-if test ${enable_root_passwd+y}
-then :
-  enableval=$enable_root_passwd; # This is documented elsewhere because of --enable/--with option sorting.
-  enable_root_passwd="$enableval"
-else case e in #(
-  e) enable_root_passwd=no ;;
-esac
-fi
-
-if test "$enable_root_passwd" = yes; then
-  printf "%s\n" "#define ALLOW_ROOT_PASSWD 1" >>confdefs.h
-
-  true
-elif test "$enable_root_passwd" != no; then
-  echo "error: must be yes or no: --enable-root-passwd=$enable_root_passwd"
-  exit 1
-fi
+# Survey says no.
+#AC_ARG_ENABLE(root-passwd,
+#[],  # This is documented elsewhere because of --enable/--with option sorting.
+#  [enable_root_passwd="$enableval"],[enable_root_passwd=no])
+#if test "$enable_root_passwd" = yes; then
+#  AC_DEFINE(ALLOW_ROOT_PASSWD)
+#  true
+#elif test "$enable_root_passwd" != no; then
+#  echo "error: must be yes or no: --enable-root-passwd=$enable_root_passwd"
+#  exit 1
+#fi
 
 ###############################################################################
 #
@@ -13851,33 +12745,12 @@ else case e in #(
 esac
 fi
 
-# Check whether --with-pam_service_name was given.
-if test ${with_pam_service_name+y}
-then :
-  withval=$with_pam_service_name; pam_service_name="$withval"
-else case e in #(
-  e) pam_service_name="xscreensaver" ;;
-esac
-fi
-
-# Check whether --enable-pam-check-account-type was given.
-if test ${enable_pam_check_account_type+y}
-then :
-  enableval=$enable_pam_check_account_type; # This is documented elsewhere because of --enable/--with option sorting.
-  enable_pam_check_account_type="$enableval"
-else case e in #(
-  e) enable_pam_check_account_type=no ;;
-esac
-fi
-
-if test "$enable_pam_check_account_type" = yes ; then
-  printf "%s\n" "#define PAM_CHECK_ACCOUNT_TYPE 1" >>confdefs.h
-
-  true
-elif test "$enable_pam_check_account_type" != no ; then
-  echo "error: must be yes or no: --enable-pam-check-account-type=$enable_pam_check_account_type"
-  exit 1
-fi
+# There's no good argument for ever changing this.
+pam_service_name="xscreensaver"
+#AC_ARG_WITH([pam_service_name],
+#[  --with-pam-service-name Set the name of the xscreensaver PAM service.
+#  --enable-root-passwd    Allow the root password to unlock, if not using PAM.],
+#  [pam_service_name="$withval"],[pam_service_name="xscreensaver"])
 
    case "$with_pam" in
     yes) ;;
 
 have_glx=no
 have_egl=no
-with_egl_req=unspecified
+with_glx_req=unspecified
 
 # Check whether --with-glx was given.
 if test ${with_glx+y}
 then :
-  withval=$with_glx; with_egl="$withval"; with_egl_req="$withval"
+  withval=$with_glx; with_glx="$withval"; with_glx_req="$withval"
 else case e in #(
   e) with_glx=no ;;
 esac
@@ -18800,7 +17673,9 @@ fi
 
 if test "$have_gl" = yes; then
 
-  # See if GLX functions are in -LGL.
+  # See if EGL functions are in -LGL.
+  egl_lib=""
+  if test "$with_glx" = no; then
 
   ac_save_CPPFLAGS="$CPPFLAGS"
   ac_save_LDFLAGS="$LDFLAGS"
@@ -18820,9 +17695,9 @@ if test "$have_gl" = yes; then
 
   CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
   LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  as_ac_Lib=`printf "%s\n" "ac_cv_lib_$gl_lib_1""_glXCreateContext" | sed "$as_sed_sh"`
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXCreateContext in -l$gl_lib_1" >&5
-printf %s "checking for glXCreateContext in -l$gl_lib_1... " >&6; }
+  as_ac_Lib=`printf "%s\n" "ac_cv_lib_$gl_lib_1""_eglCreatePlatformWindowSurface" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for eglCreatePlatformWindowSurface in -l$gl_lib_1" >&5
+printf %s "checking for eglCreatePlatformWindowSurface in -l$gl_lib_1... " >&6; }
 if eval test \${$as_ac_Lib+y}
 then :
   printf %s "(cached) " >&6
@@ -18841,11 +17716,11 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char glXCreateContext (void);
+char eglCreatePlatformWindowSurface (void);
 int
 main (void)
 {
-return glXCreateContext ();
+return eglCreatePlatformWindowSurface ();
   ;
   return 0;
 }
@@ -18867,9 +17742,9 @@ eval ac_res=\$$as_ac_Lib
 printf "%s\n" "$ac_res" >&6; }
 if eval test \"x\$"$as_ac_Lib"\" = x"yes"
 then :
-  have_glx=yes
+  have_egl=yes
 else case e in #(
-  e) have_glx=no ;;
+  e) have_egl=no ;;
 esac
 fi
 
@@ -18877,8 +17752,8 @@ fi
   LDFLAGS="$ac_save_LDFLAGS"
 #  LIBS="$ac_save_LIBS"
 
-  # See if EGL functions are in -LGL.
-  egl_lib=""
+    if test "$have_egl" = no; then
+      # See if EGL functions are in -lEGL.
 
   ac_save_CPPFLAGS="$CPPFLAGS"
   ac_save_LDFLAGS="$LDFLAGS"
 
   CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
   LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  as_ac_Lib=`printf "%s\n" "ac_cv_lib_$gl_lib_1""_eglCreatePlatformWindowSurface" | sed "$as_sed_sh"`
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for eglCreatePlatformWindowSurface in -l$gl_lib_1" >&5
-printf %s "checking for eglCreatePlatformWindowSurface in -l$gl_lib_1... " >&6; }
-if eval test \${$as_ac_Lib+y}
+  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for eglCreatePlatformWindowSurface in -lEGL" >&5
+printf %s "checking for eglCreatePlatformWindowSurface in -lEGL... " >&6; }
+if test ${ac_cv_lib_EGL_eglCreatePlatformWindowSurface+y}
 then :
   printf %s "(cached) " >&6
 else case e in #(
   e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-l$gl_lib_1 $GL_LIBS -lm $LIBS"
+LIBS="-lEGL $GL_LIBS -lm $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -18930,9 +17804,9 @@ return eglCreatePlatformWindowSurface ();
 _ACEOF
 if ac_fn_c_try_link "$LINENO"
 then :
-  eval "$as_ac_Lib=yes"
+  ac_cv_lib_EGL_eglCreatePlatformWindowSurface=yes
 else case e in #(
-  e) eval "$as_ac_Lib=no" ;;
+  e) ac_cv_lib_EGL_eglCreatePlatformWindowSurface=no ;;
 esac
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam \
@@ -18940,12 +17814,12 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
 LIBS=$ac_check_lib_save_LIBS ;;
 esac
 fi
-eval ac_res=\$$as_ac_Lib
-              { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-printf "%s\n" "$ac_res" >&6; }
-if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_EGL_eglCreatePlatformWindowSurface" >&5
+printf "%s\n" "$ac_cv_lib_EGL_eglCreatePlatformWindowSurface" >&6; }
+if test "x$ac_cv_lib_EGL_eglCreatePlatformWindowSurface" = xyes
 then :
   have_egl=yes
+                      egl_lib="EGL"
 else case e in #(
   e) have_egl=no ;;
 esac
   LDFLAGS="$ac_save_LDFLAGS"
 #  LIBS="$ac_save_LIBS"
 
+    fi
+  fi
+
+  # See if GLX functions are in -LGL.
   if test "$have_egl" = no; then
-    # See if EGL functions are in -lEGL.
 
   ac_save_CPPFLAGS="$CPPFLAGS"
   ac_save_LDFLAGS="$LDFLAGS"
 
   CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
   LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
-  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for eglCreatePlatformWindowSurface in -lEGL" >&5
-printf %s "checking for eglCreatePlatformWindowSurface in -lEGL... " >&6; }
-if test ${ac_cv_lib_EGL_eglCreatePlatformWindowSurface+y}
+  as_ac_Lib=`printf "%s\n" "ac_cv_lib_$gl_lib_1""_glXCreateContext" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXCreateContext in -l$gl_lib_1" >&5
+printf %s "checking for glXCreateContext in -l$gl_lib_1... " >&6; }
+if eval test \${$as_ac_Lib+y}
 then :
   printf %s "(cached) " >&6
 else case e in #(
   e) ac_check_lib_save_LIBS=$LIBS
-LIBS="-lEGL $GL_LIBS -lm $LIBS"
+LIBS="-l$gl_lib_1 $GL_LIBS -lm $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -18996,20 +17874,20 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 #ifdef __cplusplus
 extern "C"
 #endif
-char eglCreatePlatformWindowSurface (void);
+char glXCreateContext (void);
 int
 main (void)
 {
-return eglCreatePlatformWindowSurface ();
+return glXCreateContext ();
   ;
   return 0;
 }
 _ACEOF
 if ac_fn_c_try_link "$LINENO"
 then :
-  ac_cv_lib_EGL_eglCreatePlatformWindowSurface=yes
+  eval "$as_ac_Lib=yes"
 else case e in #(
-  e) ac_cv_lib_EGL_eglCreatePlatformWindowSurface=no ;;
+  e) eval "$as_ac_Lib=no" ;;
 esac
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.beam \
@@ -19017,14 +17895,14 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam \
 LIBS=$ac_check_lib_save_LIBS ;;
 esac
 fi
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_EGL_eglCreatePlatformWindowSurface" >&5
-printf "%s\n" "$ac_cv_lib_EGL_eglCreatePlatformWindowSurface" >&6; }
-if test "x$ac_cv_lib_EGL_eglCreatePlatformWindowSurface" = xyes
+eval ac_res=\$$as_ac_Lib
+              { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
 then :
-  have_egl=yes
-                    egl_lib="EGL"
+  have_glx=yes
 else case e in #(
-  e) have_egl=no ;;
+  e) have_glx=no ;;
 esac
 fi
 
 
   fi
 
-  # If both GLX and EGL exist, use GLX only if requested.
-  if test "$with_glx" = yes -a "$have_glx" = yes; then
-    have_egl=no
-  fi
-
   if test "$have_egl" = yes; then
     printf "%s\n" "#define HAVE_EGL 1" >>confdefs.h
 
     have_gl=no
     gl_halfassed=yes
   fi
+fi
 
-  # --with-gles means that we are emulating a system that supports GLES but
-  # does not support OpenGL 1.3 (e.g., using Linux to simulate an Android-like
-  # environment).  On such a system, GLE is required and GLX wouldn't exist.
-  # There is no way to request a GLES 3.0 runtime context using GLX.
-  #
-  if test "$have_jwzgles" = yes -a "$have_egl" = no; then
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: Using --with-glx and --with-gles together is a bad idea." >&5
-printf "%s\n" "$as_me: WARNING: Using --with-glx and --with-gles together is a bad idea." >&2;}
+if test "$have_glx" = yes; then
+
+  ac_save_CPPFLAGS="$CPPFLAGS"
+  ac_save_LDFLAGS="$LDFLAGS"
+#  ac_save_LIBS="$LIBS"
+
+  if test \! -z "$includedir" ; then
+    CPPFLAGS="$CPPFLAGS -I$includedir"
+  fi
+  # note: $X_CFLAGS includes $x_includes
+  CPPFLAGS="$CPPFLAGS $X_CFLAGS"
+
+  if test \! -z "$libdir" ; then
+    LDFLAGS="$LDFLAGS -L$libdir"
   fi
+  # note: $X_LIBS includes $x_libraries
+  LDFLAGS="$LDFLAGS $X_LIBS $X_EXTRA_LIBS"
+
+  CPPFLAGS=`eval eval eval eval eval eval eval eval eval echo $CPPFLAGS`
+  LDFLAGS=`eval eval eval eval eval eval eval eval eval echo $LDFLAGS`
+  as_ac_Lib=`printf "%s\n" "ac_cv_lib_$gl_lib_1""_glXGetProcAddressARB" | sed "$as_sed_sh"`
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for glXGetProcAddressARB in -l$gl_lib_1" >&5
+printf %s "checking for glXGetProcAddressARB in -l$gl_lib_1... " >&6; }
+if eval test \${$as_ac_Lib+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) ac_check_lib_save_LIBS=$LIBS
+LIBS="-l$gl_lib_1 $GL_LIBS -lm $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.
+   The 'extern "C"' is for builds by C++ compilers;
+   although this is not generally supported in C code supporting it here
+   has little cost and some practical benefit (sr 110532).  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char glXGetProcAddressARB (void);
+int
+main (void)
+{
+return glXGetProcAddressARB ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  eval "$as_ac_Lib=yes"
+else case e in #(
+  e) eval "$as_ac_Lib=no" ;;
+esac
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS ;;
+esac
+fi
+eval ac_res=\$$as_ac_Lib
+              { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+printf "%s\n" "$ac_res" >&6; }
+if eval test \"x\$"$as_ac_Lib"\" = x"yes"
+then :
+  printf "%s\n" "#define HAVE_GLXGETPROCADDRESSARB 1" >>confdefs.h
+
+fi
+
+  CPPFLAGS="$ac_save_CPPFLAGS"
+  LDFLAGS="$ac_save_LDFLAGS"
+#  LIBS="$ac_save_LIBS"
 
 fi
 
@@ -21448,8 +20387,8 @@ if test "$record_anim" = yes; then
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: --with-record-animation requires the ffmpeg libraries" >&5
 printf "%s\n" "$as_me: WARNING: --with-record-animation requires the ffmpeg libraries" >&2;}
   else
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabling --with-record-animation" >&5
-printf "%s\n" "enabling --with-record-animation" >&6; }
+    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: enabling --record-animation" >&5
+printf "%s\n" "enabling --record-animation" >&6; }
     printf "%s\n" "#define HAVE_RECORD_ANIM 1" >>confdefs.h
 
     ANIM_OBJS='$(ANIM_OBJS)'
@@ -21496,11 +20435,6 @@ if test "$have_pam" = yes; then
   PASSWD_OBJS="$PASSWD_OBJS \$(PAM_OBJS)"
   INSTALL_PAM="install-pam"
 fi
-if test "$enable_pam_check_account_type" = yes; then
-  COMMENT_PAM_CHECK_ACCOUNT=""
-else
-  COMMENT_PAM_CHECK_ACCOUNT="#"
-fi
 PASSWD_SRCS="$PASSWD_SRCS \$(PWENT_SRCS)"
 PASSWD_OBJS="$PASSWD_OBJS \$(PWENT_OBJS)"
 
@@ -21617,7 +20551,7 @@ INCLUDES=`echo "$INCLUDES" | sed 's@ -I${prefix}/include@@g;'`
 
 APPDEFAULTS=$ac_x_app_defaults
 
-ac_config_files="$ac_config_files Makefile utils/Makefile jwxyz/Makefile hacks/Makefile hacks/fonts/Makefile hacks/images/Makefile hacks/glx/Makefile po/Makefile.in driver/Makefile driver/xscreensaver.pam driver/XScreenSaver.ad"
+ac_config_files="$ac_config_files Makefile utils/Makefile jwxyz/Makefile hacks/Makefile hacks/fonts/Makefile hacks/images/Makefile hacks/glx/Makefile po/Makefile.in driver/Makefile driver/XScreenSaver.ad"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -22325,7 +21259,6 @@ do
     "hacks/glx/Makefile") CONFIG_FILES="$CONFIG_FILES hacks/glx/Makefile" ;;
     "po/Makefile.in") CONFIG_FILES="$CONFIG_FILES po/Makefile.in" ;;
     "driver/Makefile") CONFIG_FILES="$CONFIG_FILES driver/Makefile" ;;
-    "driver/xscreensaver.pam") CONFIG_FILES="$CONFIG_FILES driver/xscreensaver.pam" ;;
     "driver/XScreenSaver.ad") CONFIG_FILES="$CONFIG_FILES driver/XScreenSaver.ad" ;;
     "po/stamp-it") CONFIG_COMMANDS="$CONFIG_COMMANDS po/stamp-it" ;;
 
@@ -23132,11 +22065,6 @@ if test "$with_sgi_req" = yes -a "$have_sgi" = no ; then
   CONF_STATUS=1
 fi
 
-if test "$with_xidle_req" = yes -a "$have_xidle" = no ; then
-  warn 'The XIdle extension was requested, but was not found.'
-  CONF_STATUS=1
-fi
-
 if test "$with_mit_req" = yes -a "$have_mit" = no ; then
   warn 'The MIT-SCREEN-SAVER extension was requested, but was not found.'
   CONF_STATUS=1
@@ -23177,21 +22105,11 @@ if test "$with_xinerama_req" = yes -a "$have_xinerama" = no ; then
   CONF_STATUS=1
 fi
 
-if test "$with_xf86vmode_req" = yes -a "$have_xf86vmode" = no ; then
-  warn 'The XF86VMODE extension was requested, but was not found.'
-  CONF_STATUS=1
-fi
-
 if test "$with_randr_req" = yes -a "$have_randr" = no ; then
   warn 'The RANDR extension was requested, but was not found.'
   CONF_STATUS=1
 fi
 
-if test "$with_proc_interrupts_req" = yes -a "$have_proc_interrupts" = no; then
-  warn "Checking of /proc/interrupts was requested, but it's bogus."
-  CONF_STATUS=1
-fi
-
 if test "$pkg_config" = false ; then
   warnL 'The "pkg-config" program was not found.  Without that,'
   warn2 "detection of the various GTK libraries won't work."
@@ -23444,6 +22362,7 @@ if test "$have_gl" = no ; then
   echo ''
   warn2 'Those demos which use 3D will not be built or installed.'
   warn2 'That is most of them.'
+
 fi
 
 if test "$have_gl" = yes -a "$have_gle" = no ; then
 # Fucking Gentoo...
 if test "$have_jwzgles" = yes ; then
   warn_prefix="$warn_prefix_3"
-  warn "The --with-gles option does not do what you think. Do not use it."
-  exit 1
-fi
-
-if test "$have_egl" = no; then
-  warn_prefix="$warn_prefix_3"
-  warn "Using --with-glx means GLSL won't work. Don't do it!"
-  exit 1
-fi
-
-if test "$have_jwzgles" = yes ; then
-  warn  "Do not use --with-gles unless you are sure that you know"
-  warn2 "what you are doing!  It is not recommended on normal X11"
-  warn2 "systems."
-
-  if test "$have_egl" = no; then
-    warn2 ""
-    warn2 "Using --with-gles and --with-glx probably won't work."
-  fi
+  warn "The --with-gles option doesn't do what you think. Don't use it."
+  CONF_STATUS=1
 fi
 
 if test "$setuid_hacks" = no; then
index e49200f4e8703291a66f0402f968598f5ed0de8a..08d914e845dfef5d5df80a39207fe4599c5069c7 100644 (file)
@@ -68,35 +68,14 @@ AH_TEMPLATE([XPointer],
 AH_TEMPLATE([HAVE_XINPUT],
            [Define this if you have the XInput2 extension.])
 
-# This only ever existed in X11R4 and X11R5.
-AH_TEMPLATE([HAVE_XIDLE_EXTENSION],
-           [Define this if you have the X11R5 XIDLE extension.])
-
-# This only ever existed on SGI hardware.
-AH_TEMPLATE([HAVE_SGI_SAVER_EXTENSION],
-           [Define this if you have the SGI SCREEN_SAVER extension.])
-
-# This only ever existed on SGI hardware.
-AH_TEMPLATE([HAVE_SGI_VC_EXTENSION],
-           [Define this if you have the SGI-VIDEO-CONTROL extension.])
-
-AH_TEMPLATE([HAVE_MIT_SAVER_EXTENSION],
-           [Using the MIT-SCREEN-SAVER extension means that the X server
-            will crash at random times, and fading and hysteresis won't work.
-            Don't use this.  You'll be sorry.  See comment in xscreensaver.c.])
-
 AH_TEMPLATE([HAVE_DPMS_EXTENSION],
            [Define this if you have the XDPMS extension.])
 
-AH_TEMPLATE([HAVE_XF86VMODE],
-           [Define this if you have XF86VidModeGetViewPort, for
-            virtual desktops.])
-
-AH_TEMPLATE([HAVE_XF86VMODE_GAMMA],
-           [Define this if you have XF86VidModeSetGamma, for fading.])
+#AH_TEMPLATE([HAVE_XF86VMODE_GAMMA],
+#          [Define this if you have XF86VidModeSetGamma, for fading.])
 
-AH_TEMPLATE([HAVE_XF86VMODE_GAMMA_RAMP],
-           [Define this if you have XF86VidModeSetGammaRamp, for fading.])
+#AH_TEMPLATE([HAVE_XF86VMODE_GAMMA_RAMP],
+#          [Define this if you have XF86VidModeSetGammaRamp, for fading.])
 
 AH_TEMPLATE([HAVE_XINERAMA],
            [Define this if you have the Xinerama extension.])
@@ -129,11 +108,6 @@ AH_TEMPLATE([HAVE_LIBSYSTEMD],
 AH_TEMPLATE([HAVE_LIBELOGIND],
            [Define this if you have libelogind.])
 
-AH_TEMPLATE([HAVE_PROC_INTERRUPTS],
-           [Define this if you have a Linux-like /proc/interrupts file which
-           can be examined to determine when keyboard activity has
-           occurred, and you use PS/2 input devices instead of USB.])
-
 AH_TEMPLATE([HAVE_PROC_OOM],
            [Define this if you have a Linux-like /proc/.../oom_score_adj file
            which can be adjusted by root to exempt us from the out-of-memory
@@ -202,6 +176,9 @@ AH_TEMPLATE([HAVE_EGL],
 AH_TEMPLATE([HAVE_GLSL],
            [Define this if OpenGL supports the OpenGL Shading Language.])
 
+AH_TEMPLATE([HAVE_GLXGETPROCADDRESSARB],
+           [Define this if you have the function glXGetProcAddressARB.])
+
 AH_TEMPLATE([HAVE_GLBINDTEXTURE],
            [Define this if the OpenGL version is 1.1 or newer.])
 
@@ -236,10 +213,6 @@ AH_TEMPLATE([PAM_SERVICE_NAME],
 AH_TEMPLATE([HAVE_PAM_FAIL_DELAY],
            [Define this if you have pam_fail_delay.])
 
-AH_TEMPLATE([PAM_CHECK_ACCOUNT_TYPE],
-            [Whether PAM should check the result of account modules
-           when authenticating.])
-
 AH_TEMPLATE([PAM_STRERROR_TWO_ARGS],
            [Define if pam_strerror requires two arguments.])
 
@@ -250,8 +223,8 @@ AH_TEMPLATE([HAVE_KERBEROS],
 AH_TEMPLATE([HAVE_KERBEROS5],
            [Define this if you have Kerberos 5.])
 
-AH_TEMPLATE([ALLOW_ROOT_PASSWD],
-           [Define this to allow root to unlock, when not using PAM.])
+#AH_TEMPLATE([ALLOW_ROOT_PASSWD],
+#          [Define this to allow root to unlock, when not using PAM.])
 
 AH_TEMPLATE([HAVE_SHADOW_PASSWD],
            [Define this if your system uses /etc/shadow.])
@@ -1333,6 +1306,8 @@ have_dpms=no
 with_dpms_req=unspecified
 AC_ARG_WITH(dpms-ext,
 [
+Most of the following options default to "yes" if available.
+
 Server Extension Options:
 
   --with-dpms-ext         Include support for power management.],
@@ -1374,50 +1349,6 @@ elif test "$with_dpms" != no; then
 fi
 
 
-###############################################################################
-#
-#       Check for the XF86VMODE server extension (for virtual screens.)
-#
-###############################################################################
-
-have_xf86vmode=no
-with_xf86vmode_req=unspecified
-AC_ARG_WITH(xf86vmode-ext,
-[  --with-xf86vmode-ext    Include support for virtual screens.],
-  [with_xf86vmode="$withval"; with_xf86vmode_req="$withval"],
-  [with_xf86vmode=yes])
-
-HANDLE_X_PATH_ARG(with_xf86vmode, --with-xf86vmode-ext, xf86vmode)
-
-VIDMODE_LIBS=""
-
-if test "$with_xf86vmode" = yes; then
-
-  # first check for xf86vmode.h
-  AC_CHECK_X_HEADER(X11/extensions/xf86vmode.h, [have_xf86vmode=yes],,
-                    [#include <X11/Xlib.h>])
-
-  # if that succeeded, then check for the -lXxf86vm
-  if test "$have_xf86vmode" = yes; then
-    have_xf86vmode=no
-    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeGetViewPort,
-                  [have_xf86vmode=yes;
-                   VIDMODE_LIBS="-lXxf86vm";
-                   SAVER_LIBS="$SAVER_LIBS $VIDMODE_LIBS"],
-                   [true], -lXext -lX11)
-  fi
-
-  # if that succeeded, then we've really got it.
-  if test "$have_xf86vmode" = yes; then
-    AC_DEFINE(HAVE_XF86VMODE)
-  fi
-
-elif test "$with_xf86vmode" != no; then
-  echo "error: must be yes or no: --with-xf86vmode-ext=$with_xf86vmode"
-  exit 1
-fi
-
-
 ###############################################################################
 #
 #       Check for the XINERAMA server extension.
 #
 ###############################################################################
 
-have_xf86gamma=no
-have_xf86gamma_ramp=no
-with_xf86gamma_req=unspecified
-AC_ARG_WITH(xf86gamma-ext,
-[  --with-xf86gamma-ext    Include support for XFree86 gamma fading.],
-  [with_xf86gamma="$withval"; with_xf86gamma_req="$withval"],
-  [with_xf86gamma=yes])
-
-HANDLE_X_PATH_ARG(with_xf86gamma, --with-xf86gamma-ext, xf86gamma)
-
-if test "$with_xf86gamma" = yes; then
-
-  # first check for xf86vmode.h, if we haven't already
-  if test "$have_xf86vmode" = yes; then
-    have_xf86gamma=yes
-  else
-    AC_CHECK_X_HEADER(X11/extensions/xf86vmode.h, [have_xf86gamma=yes],,
-                      [#include <X11/Xlib.h>])
-  fi
-
-  # if that succeeded, then check for the -lXxf86vm
-  if test "$have_xf86gamma" = yes; then
-    have_xf86gamma=no
-    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGamma,
-                  [have_xf86gamma=yes],
-                   [true], -lXext -lX11)
-  fi
-
-  # check for the Ramp versions of the functions too.
-  if test "$have_xf86gamma" = yes; then
-    have_xf86gamma_ramp=no
-    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGammaRamp,
-                  [have_xf86gamma_ramp=yes],
-                   [true], -lXext -lX11)
-  fi
-
-  # if those tests succeeded, then we've really got the functions.
-  if test "$have_xf86gamma" = yes; then
-    AC_DEFINE(HAVE_XF86VMODE_GAMMA)
-  fi
-
-  if test "$have_xf86gamma_ramp" = yes; then
-    AC_DEFINE(HAVE_XF86VMODE_GAMMA_RAMP)
-  fi
-
-  # pull in the lib, if we haven't already
-  if test "$have_xf86gamma" = yes -a "$have_xf86vmode" = no; then
-    SAVER_LIBS="$SAVER_LIBS -lXxf86vm"
-  fi
-
-elif test "$with_xf86gamma" != no; then
-  echo "error: must be yes or no: --with-xf86gamma-ext=$with_xf86vmode"
-  exit 1
-fi
-
-
-###############################################################################
+#have_xf86gamma=no
+#have_xf86gamma_ramp=no
+#with_xf86gamma_req=unspecified
+#AC_ARG_WITH(xf86gamma-ext,
+#[  --with-xf86gamma-ext    Include support for XFree86 gamma fading.],
+#  [with_xf86gamma="$withval"; with_xf86gamma_req="$withval"],
+#  [with_xf86gamma=yes])
 #
-#       Check for the XIDLE server extension.
+#HANDLE_X_PATH_ARG(with_xf86gamma, --with-xf86gamma-ext, xf86gamma)
 #
-###############################################################################
-
-have_xidle=no
-with_xidle_req=unspecified
-AC_ARG_WITH(xidle-ext,
-[  --with-xidle-ext        Include support for the X11R5 XIDLE extension.],
-  [with_xidle="$withval"; with_xidle_req="$withval"],[with_xidle=yes])
-
-HANDLE_X_PATH_ARG(with_xidle, --with-xidle-ext, XIDLE)
-
-if test "$with_xidle" = yes; then
-  AC_CHECK_X_HEADER(X11/extensions/xidle.h,
-                    [have_xidle=yes
-                     AC_DEFINE(HAVE_XIDLE_EXTENSION)],,
-                    [#include <X11/Xlib.h>])
-elif test "$with_xidle" != no; then
-  echo "error: must be yes or no: --with-xidle-ext=$with_xidle"
-  exit 1
-fi
-
-
-###############################################################################
+#if test "$with_xf86gamma" = yes; then
 #
-#       Check for the MIT-SCREEN-SAVER server extension.
+#  # first check for xf86vmode.h, if we haven't already
+#  if test "$have_xf86vmode" = yes; then
+#    have_xf86gamma=yes
+#  else
+#    AC_CHECK_X_HEADER(X11/extensions/xf86vmode.h, [have_xf86gamma=yes],,
+#                      [#include <X11/Xlib.h>])
+#  fi
 #
-###############################################################################
-
-have_mit=no
-with_mit=no
-with_mit_req=unspecified
-#AC_ARG_WITH(mit-ext,
-#[  --with-mit-ext          Include support for the MIT-SCREEN-SAVER extension.],
-#  [with_mit="$withval"; with_mit_req="$withval"],[with_mit=no])
-#HANDLE_X_PATH_ARG(with_mit, --with-mit-ext, MIT-SCREEN-SAVER)
-
-if test "$with_mit" = yes; then
-  AC_CHECK_X_HEADER(X11/extensions/scrnsaver.h, [have_mit=yes],,
-                    [#include <X11/Xlib.h>])
-
-  # Now check to see if it's really in the library; XF86Free-3.3 ships
-  # scrnsaver.h, but doesn't include the code in libXext.a, the idiots!
-  #
-  if test "$have_mit" = yes; then
-    AC_CHECK_X_LIB(Xext, XScreenSaverRegister, [true], [have_mit=no], -lm)
-
-    if test "$have_mit" = no; then
-      # Fuck!  Looks like XF86Free-3.3 actually puts it in XExExt instead
-      # of in Xext.  Thank you master, may I have another.
-      AC_CHECK_X_LIB(XExExt, XScreenSaverRegister,
-                     [have_mit=yes; SAVER_LIBS="$SAVER_LIBS -lXExExt"],
-                     [true], -lX11 -lXext -lm)
-    fi
-
-    if test "$have_mit" = no; then
-      # Double fuck!  Looks like some versions of XFree86 (whichever version
-      # it is that comes with RedHat Linux 2.0 -- I can't find a version 
-      # number) put this garbage in Xss instead of Xext.  Thank you master,
-      #  may I have another.
-      AC_CHECK_X_LIB(Xss, XScreenSaverRegister,
-                     [have_mit=yes; SAVER_LIBS="$SAVER_LIBS -lXss"],
-                     [true], -lX11 -lXext -lm)
-    fi
-
-    if test "$have_mit" = yes; then
-#     AC_DEFINE(HAVE_MIT_SAVER_EXTENSION)
-      echo "Using the MIT-SCREEN-SAVER extension will crash your server. Don't."
-      exit 1
-    fi
-
-  fi
-
-elif test "$with_mit" != no; then
-  echo "error: must be yes or no: --with-mit-ext=$with_mit"
-  exit 1
-fi
-
-
-###############################################################################
+#  # if that succeeded, then check for the -lXxf86vm
+#  if test "$have_xf86gamma" = yes; then
+#    have_xf86gamma=no
+#    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGamma,
+#                  [have_xf86gamma=yes],
+#                   [true], -lXext -lX11)
+#  fi
 #
-#       Check for the SGI SCREEN_SAVER server extension.
+#  # check for the Ramp versions of the functions too.
+#  if test "$have_xf86gamma" = yes; then
+#    have_xf86gamma_ramp=no
+#    AC_CHECK_X_LIB(Xxf86vm, XF86VidModeSetGammaRamp,
+#                  [have_xf86gamma_ramp=yes],
+#                   [true], -lXext -lX11)
+#  fi
 #
-###############################################################################
-
-have_sgi=no
-with_sgi_req=unspecified
-AC_ARG_WITH(sgi-ext,
-[  --with-sgi-ext          Include support for the SGI SCREEN_SAVER extension.],
-  [with_sgi="$withval"; with_sgi_req="$withval"],[with_sgi=$ac_irix])
-
-HANDLE_X_PATH_ARG(with_sgi, --with-sgi-ext, SGI SCREEN_SAVER)
-
-if test "$with_sgi" = yes; then
-  AC_CHECK_X_HEADER(X11/extensions/XScreenSaver.h,
-                    [have_sgi=yes
-                     AC_DEFINE(HAVE_SGI_SAVER_EXTENSION)],,
-                    [#include <X11/Xlib.h>])
-
-elif test "$with_sgi" != no; then
-  echo "error: must be yes or no: --with-sgi-ext=$with_sgi"
-  exit 1
-fi
-
-
-###############################################################################
+#  # if those tests succeeded, then we've really got the functions.
+#  if test "$have_xf86gamma" = yes; then
+#    AC_DEFINE(HAVE_XF86VMODE_GAMMA)
+#  fi
 #
-#       Check for the SGI-VIDEO-CONTROL server extension.
+#  if test "$have_xf86gamma_ramp" = yes; then
+#    AC_DEFINE(HAVE_XF86VMODE_GAMMA_RAMP)
+#  fi
 #
-###############################################################################
-
-have_sgivc=no
-with_sgivc_req=unspecified
-AC_ARG_WITH(sgivc-ext,
-[  --with-sgivc-ext        Include support for the SGI-VIDEO-CONTROL extension.],
-  [with_sgivc="$withval"; with_sgivc_req="$withval"],[with_sgivc=$ac_irix])
-
-HANDLE_X_PATH_ARG(with_sgivc, --with-sgivc-ext, SGI-VIDEO-CONTROL)
-
-if test "$with_sgivc" = yes; then
-
-  # first check for XSGIvc.h
-  AC_CHECK_X_HEADER(X11/extensions/XSGIvc.h, [have_sgivc=yes],,
-                    [#include <X11/Xlib.h>])
-
-  # if that succeeded, then check for the -lXsgivc
-  if test "$have_sgivc" = yes; then
-    have_sgivc=no
-    AC_CHECK_X_LIB(Xsgivc, XSGIvcQueryGammaMap,
-                  [have_sgivc=yes; SAVER_LIBS="$SAVER_LIBS -lXsgivc"], [true],
-                  -lXext -lX11)
-  fi
-
-  # if that succeeded, then we've really got it.
-  if test "$have_sgivc" = yes; then
-    AC_DEFINE(HAVE_SGI_VC_EXTENSION)
-  fi
-
-elif test "$with_sgivc" != no; then
-  echo "error: must be yes or no: --with-sgivc-ext=$with_sgivc"
-  exit 1
-fi
+#  # pull in the lib, if we haven't already
+#  if test "$have_xf86gamma" = yes -a "$have_xf86vmode" = no; then
+#    SAVER_LIBS="$SAVER_LIBS -lXxf86vm"
+#  fi
+#
+#elif test "$with_xf86gamma" != no; then
+#  echo "error: must be yes or no: --with-xf86gamma-ext=$with_xf86vmode"
+#  exit 1
+#fi
 
 
 ###############################################################################
@@ -1957,49 +1742,6 @@ AC_EGREP_X_HEADER(XHPDisableReset, X11/XHPlib.h,
                   [AC_MSG_RESULT(no)])
 
 
-###############################################################################
-#
-#       Check for /proc/interrupts.
-#
-###############################################################################
-
-have_proc_interrupts=no
-with_proc_interrupts_req=unspecified
-AC_ARG_WITH(proc-interrupts,
-[  --with-proc-interrupts  Include support for consulting /proc/interrupts to
-                          notice activity on PS/2 keyboards and mice.],
-  [with_proc_interrupts="$withval"; with_proc_interrupts_req="$withval"],
-  [with_proc_interrupts=no])
-
-if test "$with_proc_interrupts" = yes; then
-
-  # Note that we may be building in an environment (e.g. Debian buildd chroot)
-  # without a proper /proc filesystem. If /proc/interrupts exists, then we'll
-  # check that it has the bits we need, but otherwise we'll just go on faith.
-  #
-  have_proc_interrupts=yes
-
-  if test -f /proc/interrupts; then
-   AC_CACHE_CHECK([whether /proc/interrupts contains keyboard data],
-    ac_cv_have_proc_interrupts,
-    [ac_cv_have_proc_interrupts=no
-     if grep 'keyboard\|i8042' /proc/interrupts >/dev/null 2>&1 ; then
-       ac_cv_have_proc_interrupts=yes
-     fi
-    ])
-   have_proc_interrupts=$ac_cv_have_proc_interrupts
-  fi
-
-  if test "$have_proc_interrupts" = yes; then
-    AC_DEFINE(HAVE_PROC_INTERRUPTS)
-  fi
-
-elif test "$with_proc_interrupts" != no; then
-  echo "error: must be yes or no: --with-proc-interrupts=$with_proc_interrupts"
-  exit 1
-fi
-
-
 ###############################################################################
 #
 #       Check for /proc/*/oom_score_adj.
@@ -2010,7 +1752,7 @@ setuid_auth=no
 have_proc_oom=no
 with_proc_oom_req=unspecified
 AC_ARG_WITH(proc-oom,
-[  --with-proc-oom         Include support to duck the out-of-memory killer.],
+[  --with-proc-oom         Include support to avoid the out-of-memory killer.],
   [with_proc_oom="$withval"; with_proc_oom_req="$withval"],
   [with_proc_oom=yes])
 
@@ -2144,7 +1886,7 @@ with_elogind_req=unspecified
 elogind_halfassed=no
 elogind_too_old=no
 AC_ARG_WITH(elogind,
-[  --with-elogind          Use elogind instead of systemd.],
+[  --with-elogind          Use elogind for that instead of systemd.],
   [with_elogind="$withval"; with_elogind_req="$withval"],
   [with_elogind=yes])
 
@@ -2329,16 +2071,17 @@ fi
 #
 ###############################################################################
 
-AC_ARG_ENABLE(root-passwd,
-[],  # This is documented elsewhere because of --enable/--with option sorting.
-  [enable_root_passwd="$enableval"],[enable_root_passwd=no])
-if test "$enable_root_passwd" = yes; then
-  AC_DEFINE(ALLOW_ROOT_PASSWD)
-  true
-elif test "$enable_root_passwd" != no; then
-  echo "error: must be yes or no: --enable-root-passwd=$enable_root_passwd"
-  exit 1
-fi
+# Survey says no.
+#AC_ARG_ENABLE(root-passwd,
+#[],  # This is documented elsewhere because of --enable/--with option sorting.
+#  [enable_root_passwd="$enableval"],[enable_root_passwd=no])
+#if test "$enable_root_passwd" = yes; then
+#  AC_DEFINE(ALLOW_ROOT_PASSWD)
+#  true
+#elif test "$enable_root_passwd" != no; then
+#  echo "error: must be yes or no: --enable-root-passwd=$enable_root_passwd"
+#  exit 1
+#fi
 
 
 ###############################################################################
@@ -2375,26 +2118,12 @@ Screen Locking Options:
   --with-pam              Use Pluggable Authentication Modules.],
   [with_pam="$withval"; with_pam_req="$withval"],[with_pam=$with_pam_default])
 
-AC_ARG_WITH([pam_service_name],
-[  --with-pam-service-name Set the name of the xscreensaver PAM service.
-  --enable-pam-check-account-type
-                          Whether PAM should check the result of account
-                          modules when authenticating.  Only do this if you
-                          have "account" modules configured on your system.
-  --enable-root-passwd    Allow the root password to unlock, if not using PAM.],
-  [pam_service_name="$withval"],[pam_service_name="xscreensaver"])
-
-AC_ARG_ENABLE(pam-check-account-type,
-[],  # This is documented elsewhere because of --enable/--with option sorting.
-  [enable_pam_check_account_type="$enableval"],
-  [enable_pam_check_account_type=no])
-if test "$enable_pam_check_account_type" = yes ; then
-  AC_DEFINE(PAM_CHECK_ACCOUNT_TYPE)
-  true
-elif test "$enable_pam_check_account_type" != no ; then
-  echo "error: must be yes or no: --enable-pam-check-account-type=$enable_pam_check_account_type"
-  exit 1
-fi
+# There's no good argument for ever changing this.
+pam_service_name="xscreensaver"
+#AC_ARG_WITH([pam_service_name],
+#[  --with-pam-service-name Set the name of the xscreensaver PAM service.
+#  --enable-root-passwd    Allow the root password to unlock, if not using PAM.],
+#  [pam_service_name="$withval"],[pam_service_name="xscreensaver"])
 
 HANDLE_X_PATH_ARG(with_pam, --with-pam, PAM)
 
@@ -2488,7 +2217,7 @@ have_kerberos5=no
 with_kerberos_req=unspecified
 
 AC_ARG_WITH(kerberos, 
-[  --with-kerberos         Include support for Kerberos authentication.],
+[  --with-kerberos         Use Kerberos authentication instead.],
   [with_kerberos="$withval"; with_kerberos_req="$withval"],[with_kerberos=yes])
 
 HANDLE_X_PATH_ARG(with_kerberos, --with-kerberos, Kerberos)
@@ -2567,7 +2296,7 @@ have_shadow=no
 with_shadow_req=unspecified
 
 AC_ARG_WITH(shadow,
-[  --with-shadow           Include support for shadow password authentication.],
+[  --with-shadow           Use shadow password authentication instead.],
   [with_shadow="$withval"; with_shadow_req="$withval"],[with_shadow=yes])
 
 HANDLE_X_PATH_ARG(with_shadow, --with-shadow, shadow password)
@@ -3596,11 +3325,10 @@ fi
 
 have_glx=no
 have_egl=no
-with_egl_req=unspecified
+with_glx_req=unspecified
 AC_ARG_WITH(glx,
-[  --with-glx              Use GLX to interface OpenGL and X11 instead of EGL.
-                          Do not do this: it will make GLSL fail.],
-  [with_egl="$withval"; with_egl_req="$withval"],
+[  --with-glx              Use GLX to interface OpenGL and X11 instead of EGL.],
+  [with_glx="$withval"; with_glx_req="$withval"],
   [with_glx=no])
 
 HANDLE_X_PATH_ARG(with_glx, --with-glx, GLX)
@@ -3614,30 +3342,29 @@ fi
 
 if test "$have_gl" = yes; then
 
-  # See if GLX functions are in -LGL.
-  AC_CHECK_X_LIB($gl_lib_1, glXCreateContext,
-                 [have_glx=yes],
-                 [have_glx=no],
-                 $GL_LIBS -lm)
-
   # See if EGL functions are in -LGL.
   egl_lib=""
-  AC_CHECK_X_LIB($gl_lib_1, eglCreatePlatformWindowSurface,
-                 [have_egl=yes],
-                 [have_egl=no],
-                 $GL_LIBS -lm)
-  if test "$have_egl" = no; then
-    # See if EGL functions are in -lEGL.
-    AC_CHECK_X_LIB(EGL, eglCreatePlatformWindowSurface,
-                   [have_egl=yes
-                    egl_lib="EGL"],
+  if test "$with_glx" = no; then
+    AC_CHECK_X_LIB($gl_lib_1, eglCreatePlatformWindowSurface,
+                   [have_egl=yes],
                    [have_egl=no],
                    $GL_LIBS -lm)
+    if test "$have_egl" = no; then
+      # See if EGL functions are in -lEGL.
+      AC_CHECK_X_LIB(EGL, eglCreatePlatformWindowSurface,
+                     [have_egl=yes
+                      egl_lib="EGL"],
+                     [have_egl=no],
+                     $GL_LIBS -lm)
+    fi
   fi
 
-  # If both GLX and EGL exist, use GLX only if requested.
-  if test "$with_glx" = yes -a "$have_glx" = yes; then
-    have_egl=no
+  # See if GLX functions are in -LGL.
+  if test "$have_egl" = no; then
+    AC_CHECK_X_LIB($gl_lib_1, glXCreateContext,
+                   [have_glx=yes],
+                   [have_glx=no],
+                   $GL_LIBS -lm)
   fi
 
   if test "$have_egl" = yes; then
@@ -3652,18 +3379,14 @@ if test "$have_gl" = yes; then
     have_gl=no
     gl_halfassed=yes
   fi
-
-  # --with-gles means that we are emulating a system that supports GLES but
-  # does not support OpenGL 1.3 (e.g., using Linux to simulate an Android-like
-  # environment).  On such a system, GLE is required and GLX wouldn't exist.
-  # There is no way to request a GLES 3.0 runtime context using GLX.
-  #
-  if test "$have_jwzgles" = yes -a "$have_egl" = no; then
-    AC_MSG_WARN([Using --with-glx and --with-gles together is a bad idea.])
-  fi
-
 fi
 
+if test "$have_glx" = yes; then
+    AC_CHECK_X_LIB($gl_lib_1, glXGetProcAddressARB,
+                   [AC_DEFINE(HAVE_GLXGETPROCADDRESSARB)],
+                   [],
+                   $GL_LIBS -lm)
+fi
 
 # Restore flags after testing OpenGL libraries.
 #
@@ -4352,7 +4075,7 @@ if test "$record_anim" = yes; then
   if test "$have_ffmpeg" != yes; then
     AC_MSG_WARN(--with-record-animation requires the ffmpeg libraries)
   else
-    AC_MSG_RESULT(enabling --with-record-animation)
+    AC_MSG_RESULT(enabling --record-animation)
     AC_DEFINE(HAVE_RECORD_ANIM)
     ANIM_OBJS='$(ANIM_OBJS)'
     ANIM_LIBS='$(ANIM_LIBS)'
@@ -4402,11 +4125,6 @@ if test "$have_pam" = yes; then
   PASSWD_OBJS="$PASSWD_OBJS \$(PAM_OBJS)"
   INSTALL_PAM="install-pam"
 fi
-if test "$enable_pam_check_account_type" = yes; then
-  COMMENT_PAM_CHECK_ACCOUNT=""
-else
-  COMMENT_PAM_CHECK_ACCOUNT="#"
-fi
 PASSWD_SRCS="$PASSWD_SRCS \$(PWENT_SRCS)"
 PASSWD_OBJS="$PASSWD_OBJS \$(PWENT_OBJS)"
 
@@ -4564,7 +4282,6 @@ AC_SUBST(INSTALL_DIRS)
 AC_SUBST(INSTALL_PAM)
 AC_SUBST(GLIB_COMPILE_RESOURCES)
 AC_SUBST(HAVE_PAM_FAIL_DELAY)
-AC_SUBST(COMMENT_PAM_CHECK_ACCOUNT)
 AC_SUBST(NEW_LOGIN_COMMAND)
 AC_SUBST(NEW_LOGIN_COMMAND_P)
 AC_SUBST(DEFAULT_IMAGES_P)
@@ -4628,7 +4345,6 @@ AC_CONFIG_FILES([Makefile
           hacks/glx/Makefile
           po/Makefile.in
           driver/Makefile
-          driver/xscreensaver.pam
           driver/XScreenSaver.ad])
 AC_OUTPUT
 
@@ -4714,11 +4430,6 @@ if test "$with_sgi_req" = yes -a "$have_sgi" = no ; then
   CONF_STATUS=1
 fi
 
-if test "$with_xidle_req" = yes -a "$have_xidle" = no ; then
-  warn 'The XIdle extension was requested, but was not found.'
-  CONF_STATUS=1
-fi
-
 if test "$with_mit_req" = yes -a "$have_mit" = no ; then
   warn 'The MIT-SCREEN-SAVER extension was requested, but was not found.'
   CONF_STATUS=1
@@ -4759,21 +4470,11 @@ if test "$with_xinerama_req" = yes -a "$have_xinerama" = no ; then
   CONF_STATUS=1
 fi
 
-if test "$with_xf86vmode_req" = yes -a "$have_xf86vmode" = no ; then
-  warn 'The XF86VMODE extension was requested, but was not found.'
-  CONF_STATUS=1
-fi
-
 if test "$with_randr_req" = yes -a "$have_randr" = no ; then
   warn 'The RANDR extension was requested, but was not found.'
   CONF_STATUS=1
 fi
 
-if test "$with_proc_interrupts_req" = yes -a "$have_proc_interrupts" = no; then
-  warn "Checking of /proc/interrupts was requested, but it's bogus."
-  CONF_STATUS=1
-fi
-
 if test "$pkg_config" = false ; then
   warnL 'The "pkg-config" program was not found.  Without that,'
   warn2 "detection of the various GTK libraries won't work."
@@ -5035,8 +4736,10 @@ if test "$have_gl" = no ; then
   echo ''
   warn2 'Those demos which use 3D will not be built or installed.'
   warn2 'That is most of them.'
+
 fi
 
+
 if test "$have_gl" = yes -a "$have_gle" = no ; then
 
  # nobody cares about this; don't print the warning unless it was
@@ -5107,25 +4810,8 @@ fi
 # Fucking Gentoo...
 if test "$have_jwzgles" = yes ; then
   warn_prefix="$warn_prefix_3"
-  warn "The --with-gles option does not do what you think. Do not use it."
-  exit 1
-fi
-
-if test "$have_egl" = no; then
-  warn_prefix="$warn_prefix_3"
-  warn "Using --with-glx means GLSL won't work. Don't do it!"
-  exit 1
-fi
-
-if test "$have_jwzgles" = yes ; then
-  warn  "Do not use --with-gles unless you are sure that you know"
-  warn2 "what you are doing!  It is not recommended on normal X11"
-  warn2 "systems."
-
-  if test "$have_egl" = no; then
-    warn2 ""
-    warn2 "Using --with-gles and --with-glx probably won't work."
-  fi
+  warn "The --with-gles option doesn't do what you think. Don't use it."
+  CONF_STATUS=1
 fi
 
 if test "$setuid_hacks" = no; then
index 927b6d57cd307bfc4846b8ed5fdf6821464b76fc..ceb81c7416201376a992ff029e0e13bbad98186a 100644 (file)
@@ -1,4 +1,4 @@
-xscreensaver (6.13-1) unstable; urgency=medium
+xscreensaver (6.14-1) unstable; urgency=medium
 
   * Splitting this into multiple packages is a support nightmare, please don't.
 
index 860266f75351945b2d522303742745bf77dd2991..762382652820f8c7ea8991b59172b255c4881477 100644 (file)
@@ -20,7 +20,7 @@ Build-Depends: debhelper-compat (= 13),
                libglu-dev,
                libgle-dev,
                libgtk-3-dev,
-               libgdk-pixbuf2.0-dev,
+               libgdk-pixbuf-2.0-dev,
                libjpeg-dev,
                libxml2-dev,
                libpam-dev,
index 59b22545053492213dd57de3685983ed458baa58..260bc89c6dc5e568b44744ad0ccc1aaaba2bd82f 100755 (executable)
@@ -4,6 +4,22 @@ set -e
 
 case "$1" in
     configure)
+
       killall -HUP xscreensaver 2>&-
+
+      # I think that without this, newly-installed icons don't show up in
+      # desktop menus or in xscreensaver-settings.  Is there a better way?
+      #
+      for f in /usr/share/icons/index.theme     \
+               /usr/share/icons/*/index.theme   \
+               /usr/share/pixmaps/index.theme   \
+               /usr/share/pixmaps/*/index.theme \
+      ; do
+        if [ -f "$f" ]; then
+          f=`dirname "$f"`
+          gtk-update-icon-cache --force --quiet "$f"
+        fi
+      done
+
     ;;
 esac
index be913067a4be3ada0087e026dfaa69b35a878ec5..6a0a4469ba42ceeb500f88c4e0b257efd11bdb91 100755 (executable)
@@ -4,6 +4,8 @@ set -e
 
 case "$1" in 
   remove|purge)
-       killall -q /usr/bin/xscreensaver || true
-       ;;
+    killall -q /usr/bin/xscreensaver          || true
+    killall -q /usr/bin/xscreensaver-settings || true
+    killall -q /usr/bin/xscreensaver-command  || true
+  ;;
 esac
index 1ec5bc89ffd7cadefa74532648f15cc1362aab17..295b572dc80f76b3266b993a9f757eff13ae7448 100755 (executable)
@@ -9,9 +9,13 @@ export DH_OPTIONS=-v
 override_dh_auto_configure:
        ./configure --prefix=/usr
 
+override_dh_auto_install:
+       dh_auto_install -- UPDATE_ICON_CACHE=true SUID_FLAGS=
+
 override_dh_installdirs:
        dh_installdirs
        mkdir -p debian/xscreensaver/etc/pam.d
+       mkdir -p debian/xscreensaver/usr/lib/systemd/user
 
 override_dh_fixperms-arch:
        dh_fixperms
index dc7e56661035dc3eaaceab909db22ddfda34f754..ce4fe9f1a694060a68efd7779942e32d60be4948 100644 (file)
@@ -20,6 +20,8 @@ localedir     = @PO_DATADIR@/locale
 mandir         = @mandir@
 libexecdir     = @libexecdir@
 sysconfdir     = @sysconfdir@
+# Not @libdir@ which might be /usr/lib64
+libdir         = $(exec_prefix)/lib
 
 # A = suffix for user commands in /usr/bin/
 # B = suffix for helper programs in /usr/libexec/xscreensaver/
@@ -33,6 +35,8 @@ GTK_SHAREDIR  = $(GTK_DATADIR)/xscreensaver
 UPDATE_ICON_CACHE = gtk-update-icon-cache
 GLIB_COMPILE_RESOURCES = @GLIB_COMPILE_RESOURCES@
 
+SYSTEMD_DIR    = $(libdir)/systemd/user
+
 WAYLAND_CFLAGS = @WAYLAND_CFLAGS@
 WAYLAND_LIBS   = @WAYLAND_LIBS@
 WAYLAND_DATADIR        = @WAYLAND_DATADIR@
@@ -131,7 +135,6 @@ AD_DIR              = @APPDEFAULTS@
 # $(sysconfdir) is either /usr/local/etc or /usr/etc but this must be /etc.
 PAM_ROOT       = /etc
 PAM_DIR                = $(PAM_ROOT)/pam.d
-PAM_CONF       = $(PAM_ROOT)/pam.conf
 
 ICON_SRC        = $(UTILS_SRC)/images
 LOGO           = $(ICON_SRC)/logo-512.png
@@ -275,7 +278,9 @@ UTIL_EXES   = xscreensaver-gfx @EXES_SYSTEMD@
 SETUID_EXES    = xscreensaver-auth
 DEMO_EXES      = @ALL_DEMO_PROGRAMS@
 EXES_SYSTEMD   = xscreensaver-systemd
-DESKS          = xscreensaver.desktop xscreensaver.service
+DESKS          = xscreensaver.desktop \
+                 xscreensaver-settings.desktop \
+                 xscreensaver.service
 
 HDRS           = XScreenSaver_ad.h XScreenSaver_Xm_ad.h \
                  xscreensaver.h prefs.h remote.h exec.h \
@@ -289,7 +294,7 @@ MENB                = xscreensaver-gfx.man xscreensaver-auth.man \
                  xscreensaver-systemd.man
 
 EXTRAS         = README Makefile.in \
-                 XScreenSaver.ad.in XScreenSaver-Xm.ad xscreensaver.pam.in \
+                 XScreenSaver.ad.in XScreenSaver-Xm.ad xscreensaver.pam \
                  demo.ui prefs.ui gresource.xml xscreensaver.desktop.in \
                  xscreensaver-settings.desktop.in xscreensaver.service.in \
                  $(WAYLAND_GEN_XML)
@@ -315,50 +320,49 @@ tests::   $(TEST_EXES)
 ##############################################################################
 
 install:   install-program   install-ad   install-man   install-xml    \
-          install-pam  install-gnome
+          install-pam  install-gnome install-systemd
 uninstall: uninstall-program uninstall-ad uninstall-man uninstall-xml  \
-          uninstall-gnome
+          uninstall-gnome uninstall-systemd
 
 install-strip:
        $(MAKE2) INSTALL_PROGRAM='$(INSTALL_PROGRAM) -s' install
 
 install-program:: $(EXES)
-       @if [ ! -d $(DESTDIR)$(bindir) ]; then                                \
-          $(INSTALL_DIRS) $(DESTDIR)$(bindir) ;                              \
+       @if [ ! -d "$(DESTDIR)$(bindir)" ]; then                              \
+          echo $(INSTALL_DIRS) "$(DESTDIR)$(bindir)" ;                       \
+               $(INSTALL_DIRS) "$(DESTDIR)$(bindir)" ;                       \
         fi ;                                                                 \
         if [ ! -d $(DESTDIR)$(HACKDIR) ]; then                               \
-          $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ;                             \
+          echo $(INSTALL_DIRS) "$(DESTDIR)$(HACKDIR)" ;                      \
+               $(INSTALL_DIRS) "$(DESTDIR)$(HACKDIR)" ;                      \
         fi
 
 install-program:: $(EXES)
-       @inst="$(INSTALL_PROGRAM)" ;                                          \
-       for exe in $(EXES); do                                                \
-         echo $$inst $$exe $(DESTDIR)$(bindir)/$$exe ;                       \
-              $$inst $$exe $(DESTDIR)$(bindir)/$$exe ;                       \
+       @for exe in $(EXES); do                                               \
+         echo $(INSTALL_PROGRAM) "$$exe" "$(DESTDIR)$(bindir)/$$exe" ;       \
+              $(INSTALL_PROGRAM) "$$exe" "$(DESTDIR)$(bindir)/$$exe" ;       \
        done
 
 install-program:: $(UTIL_EXES)
-       @inst="$(INSTALL_PROGRAM)" ;                                          \
-        for exe in $(UTIL_EXES); do                                          \
-           echo $$inst $$exe $(DESTDIR)$(HACKDIR)/$$exe ;                    \
-                $$inst $$exe $(DESTDIR)$(HACKDIR)/$$exe ;                    \
+       @for exe in $(UTIL_EXES); do                                          \
+           echo $(INSTALL_PROGRAM) "$$exe" "$(DESTDIR)$(HACKDIR)/$$exe" ;    \
+                $(INSTALL_PROGRAM) "$$exe" "$(DESTDIR)$(HACKDIR)/$$exe" ;    \
         done
 
 install-program:: $(SETUID_EXES)
        @inst="$(INSTALL_PROGRAM)" ;                                          \
         idir="$(DESTDIR)$(HACKDIR)" ;                                        \
-        if [ @SETUID_AUTH@ = yes ]; then                                     \
+        if [ "@SETUID_AUTH@" = yes ]; then                                   \
           inst="$(INSTALL_SETUID)" ;                                         \
-        else                                                                 \
-          inst="$(INSTALL_PROGRAM)" ;                                        \
         fi ;                                                                 \
         for exe in $(SETUID_EXES); do                                        \
-          echo $$inst $$exe $$idir/$$exe ;                                   \
-          if   $$inst $$exe $$idir/$$exe ; then                              \
+          echo $$inst "$$exe" "$$idir/$$exe" ;                               \
+          if   $$inst "$$exe" "$$idir/$$exe" ; then                          \
             true ;                                                           \
           elif [ @SETUID_AUTH@ = yes ]; then                                 \
-            echo $(INSTALL_PROGRAM) $$exe $$idir/$$exe ;                     \
-            if   $(INSTALL_PROGRAM) $$exe $$idir/$$exe ; then                \
+            inst="$(INSTALL_PROGRAM)" ;                                      \
+            echo $$inst "$$exe" "$$idir/$$exe" ;                             \
+            if   $$inst "$$exe" "$$idir/$$exe" ; then                        \
               echo "" ;                                                      \
               echo "WARNING: unable to install $$exe setuid." ;              \
               echo "WARNING: authentication may not work!" ;                 \
@@ -374,25 +378,25 @@ install-program:: $(SETUID_EXES)
 
 # Symlink from xscreensaver-demo -> xscreensaver-settings in /usr/bin/
 install-program::
-       @D=$(DESTDIR)$(bindir) ;                                              \
-        echo ln -sf xscreensaver-settings $$D/xscreensaver-demo ;            \
-             ln -sf xscreensaver-settings $$D/xscreensaver-demo
+       @D="$(DESTDIR)$(bindir)" ;                                            \
+        echo ln -sf xscreensaver-settings "$$D"/xscreensaver-demo ;          \
+             ln -sf xscreensaver-settings "$$D"/xscreensaver-demo
 
 install-ad: XScreenSaver.ad
-       @if [ ! -d $(DESTDIR)$(AD_DIR) ]; then                                \
-         $(INSTALL_DIRS) $(DESTDIR)$(AD_DIR) ;                               \
+       @dir="$(DESTDIR)$(AD_DIR)" ;                                          \
+        name1="XScreenSaver.ad" ;                                            \
+        name2="XScreenSaver" ;                                               \
+        if [ ! -d "$$dir" ]; then                                            \
+          echo $(INSTALL_DIRS) "$$dir" ;                                     \
+               $(INSTALL_DIRS) "$$dir" ;                                     \
         fi ;                                                                 \
-       echo $(INSTALL_DATA) XScreenSaver.ad                                  \
-         $(DESTDIR)$(AD_DIR)/XScreenSaver ;                                  \
-       if $(INSTALL_DATA) XScreenSaver.ad                                    \
-         $(DESTDIR)$(AD_DIR)/XScreenSaver ; then                             \
-         true ;                                                              \
-       else                                                                  \
-         e=echo ;                                                            \
-         if [ -f $(DESTDIR)$(AD_DIR)/XScreenSaver ]; then                    \
+       echo  $(INSTALL_DATA) "$$name1" "$$dir/$$name2" ;                     \
+       if  ! $(INSTALL_DATA) "$$name1" "$$dir/$$name2" ; then                \
+         e="echo" ;                                                          \
+         if [ -f "$$dir"/$$name2 ]; then                                     \
  $$e ""                                                                             ;\
  $$e "  ####################################################################";\
- $$e "  Warning: unable to install $(DESTDIR)$(AD_DIR)/XScreenSaver"        ;\
+ $$e "  Warning: unable to install $$dir/$$name2"                           ;\
  $$e "           That file exists, and is unwritable.  It is probably from"  ;\
  $$e "           an older version of xscreensaver, and could cause things"   ;\
  $$e "           to malfunction.  Please delete it!"                        ;\
@@ -402,7 +406,7 @@ install-ad: XScreenSaver.ad
          else                                                                \
  $$e ""                                                                             ;\
  $$e "  ####################################################################";\
- $$e "  Warning: unable to install $(DESTDIR)$(AD_DIR)/XScreenSaver"        ;\
+ $$e "  Warning: unable to install $$dir/$$name2"                           ;\
  $$e "           This is probably ok; it should work without that file."     ;\
  $$e "  ####################################################################";\
  $$e ""                                                                             ;\
@@ -422,38 +426,38 @@ install-man:: $(MENA) $(MENB)
        U=$(UTILS_SRC)/version.h ;                                      \
        V=`sed -n 's/.*xscreensaver \([0-9]\.[^)]*)\).*/\1/p' < $$U |   \
            head -1` ;                                                  \
-       T=/tmp/xs$$$$.man ;                                             \
-       SUFA=$(mansuffixA) ;                                            \
-       SUFB=$(mansuffixB) ;                                            \
+       T="/tmp/xs$$$$.man" ;                                           \
+       SUFA="$(mansuffixA)" ;                                          \
+       SUFB="$(mansuffixB)" ;                                          \
                                                                        \
        INST() {                                                        \
          TH=".TH XScreenSaver $$SUF \"$$V\" \"X Version 11\"" ;        \
          DIR="$(DESTDIR)$(mandir)/man$$SUF" ;                          \
-         if [ ! -d $$DIR ]; then                                       \
-           echo $(INSTALL_DIRS) $$DIR ;                                \
-                $(INSTALL_DIRS) $$DIR ;                                \
+         if [ ! -d "$$DIR" ]; then                                     \
+           echo $(INSTALL_DIRS) "$$DIR" ;                              \
+                $(INSTALL_DIRS) "$$DIR" ;                              \
           fi ;                                                         \
                                                                        \
          sed -e "s/^\.TH.*/$$TH/"                                      \
              -e "s/^\(\.BR xscreens[^ ]* (\)[0-9]\(.*\)/\1$$SUFA\2/"   \
              -e "s@(MANSUFFIX)@($$SUFB)@g"                             \
-           < $(srcdir)/$$man > $$T ;                                   \
-         manbase=`echo $$man | sed 's/\.man$$//'` ;                    \
-         echo $(INSTALL_DATA) $$man $$DIR/$$manbase.$$SUF ;            \
-              $(INSTALL_DATA) $$T   $$DIR/$$manbase.$$SUF ;            \
+           < "$(srcdir)/$$man" > "$$T" ;                               \
+         manbase=`echo "$$man" | sed 's/\.man$$//'` ;                  \
+         echo $(INSTALL_DATA) "$$man" "$$DIR/$$manbase.$$SUF" ;        \
+              $(INSTALL_DATA) "$$T"   "$$DIR/$$manbase.$$SUF" ;        \
        } ;                                                             \
                                                                        \
-       SUF=$$SUFA ; for man in $(MENA); do INST ; done ;               \
-       SUF=$$SUFB ; for man in $(MENB); do INST ; done ;               \
-       rm -f $$T
+       SUF="$$SUFA" ; for man in $(MENA); do INST ; done ;             \
+       SUF="$$SUFB" ; for man in $(MENB); do INST ; done ;             \
+       rm -f "$$T"
 
 # Symlink from xscreensaver-demo.1 -> xscreensaver-settings.1 in /usr/man/man1/
 install-man::
-       @D=$(DESTDIR)$(mandir)/man$(mansuffixA) ;                       \
-        F1=xscreensaver-settings.$(mansuffixA) ;                       \
-        F2=xscreensaver-demo.$(mansuffixA) ;                           \
-        echo ln -sf $$F1 $$D/$$F2 ;                                    \
-             ln -sf $$F1 $$D/$$F2
+       @D="$(DESTDIR)$(mandir)/man$(mansuffixA)" ;                     \
+        F1="xscreensaver-settings.$(mansuffixA)" ;                     \
+        F2="xscreensaver-demo.$(mansuffixA)" ;                         \
+        echo ln -sf "$$F1" "$$D/$$F2" ;                                \
+             ln -sf "$$F1" "$$D/$$F2"
 
 # These used to be in driver/ and installed into /usr/bin/
 # Now they are in hacks/ and are installed into /usr/libexec/xscreensaver/
@@ -465,170 +469,108 @@ OLD_MEN  = xscreensaver-getimage.man xscreensaver-getimage-file.man \
           xscreensaver-demo.man
 uninstall-program::
        @for program in $(EXES) $(OLD_EXES); do                         \
-         echo rm -f $(DESTDIR)$(bindir)/$$program ;                    \
-         rm -f $(DESTDIR)$(bindir)/$$program ;                         \
+         echo rm -f "$(DESTDIR)$(bindir)/$$program" ;                  \
+              rm -f "$(DESTDIR)$(bindir)/$$program" ;                  \
        done
 
 uninstall-program::
        @for program in $(UTIL_EXES) $(SETUID_EXES); do                 \
-         echo rm -f $(DESTDIR)$(HACKDIR)/$$program ;                   \
-              rm -f $(DESTDIR)$(HACKDIR)/$$program ;                   \
+         echo rm -f "$(DESTDIR)$(HACKDIR)/$$program" ;                 \
+              rm -f "$(DESTDIR)$(HACKDIR)/$$program" ;                 \
        done
 
 uninstall-ad:
-       rm -f $(DESTDIR)$(AD_DIR)/XScreenSaver
+       rm -f "$(DESTDIR)$(AD_DIR)/XScreenSaver"
 
 uninstall-man:
        @men="$(MEN) $(OLD_MEN)" ;                                      \
        for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         echo rm -f $(DESTDIR)$(manAdir)/$$instname* ;                 \
-              rm -f $(DESTDIR)$(manAdir)/$$instname* ;                 \
+         instname=`echo "$$man" | sed 's/\.man$$/\.$(mansuffix)/'` ;   \
+         echo rm -f "$(DESTDIR)$(manAdir)/$$instname"* ;               \
+              rm -f "$(DESTDIR)$(manAdir)/$$instname"* ;               \
        done
 
+# xscreensaver.pam
+# into /etc/pam.d/xscreensaver
 install-pam: xscreensaver.pam
-       @src="xscreensaver.pam" ;                                       \
-       name=`sed -n 's/.*PAM_SERVICE_NAME[     ]*"\([^"]*\)".*$$/\1/p' \
+       @name=`sed -n 's/.*PAM_SERVICE_NAME[    ]*"\([^"]*\)".*$$/\1/p' \
           < ../config.h` ;                                             \
-       dir="$(DESTDIR)$(PAM_DIR)" ;                                    \
-       conf="$(PAM_CONF)" ;                                            \
-                                                                       \
-       if [ -z "$$name" ]; then                                        \
-         echo "PAM not configured, not installing" >&2 ;               \
-         exit 0 ;                                                      \
-       fi ;                                                            \
+        src="$<" ;                                                     \
+        dst="$(PAM_DIR)/$$name" ;                                      \
                                                                        \
-       if [ ! -d $(DESTDIR)$(PAM_ROOT) ]; then                         \
-         echo $(INSTALL_DIRS) $(DESTDIR)$(PAM_ROOT) ;                  \
-              $(INSTALL_DIRS) $(DESTDIR)$(PAM_ROOT) ;                  \
-       fi ;                                                            \
-                                                                       \
-       if [ -d $(PAM_DIR) ] ; then                                     \
-                                                                       \
-         if [ -f $(PAM_DIR)/xdm ]; then                                \
-           src2=$(PAM_DIR)/xdm ;                                       \
-         elif [ -f $(PAM_DIR)/login ]; then                            \
-           src2=$(PAM_DIR)/login ;                                     \
-         fi ;                                                          \
+        if [ -z "$$name" ]; then                                       \
+          echo "PAM not configured, not installing" >&2 ;              \
+          exit 0 ;                                                     \
+        fi ;                                                           \
                                                                        \
-         if [ -z "$$src2" ]; then                                      \
-           echo $(INSTALL_DATA) $$src $$dir/$$name ;                   \
-                $(INSTALL_DATA) $$src $$dir/$$name ;                   \
-         else                                                          \
-           tmp="xscreensaver.pam.$$$$" ;                               \
-           grep '^#%\|^auth\|^@include' $$src2 > $$tmp ;               \
-           if cmp -s $$tmp $$dir/$$name ; then                         \
-             echo "$$dir/$$name unchanged" ;                           \
-           else                                                        \
-             echo "Updating contents of $$dir/$$name from $$src2" ;    \
-             $(INSTALL_DATA) $$tmp $$dir/$$name ;                      \
-           fi ;                                                        \
-           rm -f $$tmp ;                                               \
-         fi ;                                                          \
+        if [ ! -d "$(DESTDIR)$(PAM_DIR)" ]; then                       \
+          echo $(INSTALL_DIRS) "$(DESTDIR)$(PAM_DIR)" ;                \
+               $(INSTALL_DIRS) "$(DESTDIR)$(PAM_DIR)" ;                \
+        fi ;                                                           \
                                                                        \
-         if [ ! -f $$dir/$$name ]; then                                \
-           e=echo ;                                                    \
- $$e ""                                                                             ;\
- $$e "  ####################################################################";\
- $$e "  Warning: xscreensaver has been compiled with support for Pluggable"  ;\
- $$e "           Authentication Modules (PAM).  However, we were unable to"  ;\
- $$e "           install the file \"$$dir/$$name\".  XScreenSaver is"        ;\
- $$e "           unlikely to work without this file."                       ;\
- $$e "  ####################################################################";\
- $$e ""                                                                             ;\
-         fi ;                                                          \
-       elif [ -f $$conf -a "x$$name" != "x" ]; then                    \
-         if ( grep $$name $$conf >/dev/null ); then                    \
-          echo "$$conf unchanged: already has an entry for $$name" ;   \
-         else                                                          \
-           tmp="pam.conf.$$$$" ;                                       \
-           grep -v $$name $$conf > $$tmp ;                             \
-           extras=`sed -n "s/^login\(.*auth.*\)$$/$$name\1/p" $$conf`; \
-           echo "$$extras" >> $$tmp ;                                  \
-           if [ "x$$extras" = "x" ]; then                              \
-             echo "Error: no login rules in $$conf?" >&2 ;             \
-           else                                                        \
-             echo "adding $$name rules to $$conf:" ;                   \
-             echo "" ;                                                 \
-             echo "$$extras" | sed 's/^/       /' ;                    \
-           fi ;                                                        \
-           $(INSTALL_DATA) $$tmp $$conf ;                              \
-           rm -f $$tmp ;                                               \
-         fi ;                                                          \
-         if ( grep $$name $$conf >/dev/null ); then                    \
-           echo ;                                                      \
-         else                                                          \
-           e=echo ;                                                    \
- $$e ""                                                                             ;\
- $$e "  ####################################################################";\
- $$e "  Warning: xscreensaver has been compiled with support for Pluggable"  ;\
- $$e "           Authentication Modules (PAM).  However, we were unable to"  ;\
- $$e "           install xscreensaver rules in the file $$conf."            ;\
- $$e "           XScreenSaver is unlikely to work without this."            ;\
- $$e "  ####################################################################";\
- $$e ""                                                                             ;\
-         fi ;                                                          \
-       else                                                            \
-           e=echo ;                                                    \
- $$e ""                                                                             ;\
- $$e "  ####################################################################";\
- $$e "  Warning: $$dir/ does not exist, not installing PAM config."          ;\
- $$e "  ####################################################################";\
- $$e ""                                                                             ;\
-       fi
+        echo $(INSTALL_DATA) "$$src" "$(DESTDIR)$$dst" ;               \
+             $(INSTALL_DATA) "$$src" "$(DESTDIR)$$dst" ;               \
 
 
 # xscreensaver.desktop
 # xscreensaver-settings.desktop
 # into /usr/share/applications/
 install-gnome:: xscreensaver.desktop xscreensaver-settings.desktop
-       @if [ "$(GTK_DATADIR)" != "" ]; then                                  \
+       @if [ ! -z "$(GTK_DATADIR)" ]; then                                   \
           if [ ! -d "$(DESTDIR)$(GTK_APPDIR)" ]; then                        \
             echo $(INSTALL_DIRS) "$(DESTDIR)$(GTK_APPDIR)"                  ;\
                  $(INSTALL_DIRS) "$(DESTDIR)$(GTK_APPDIR)"                  ;\
           fi                                                                ;\
-          old=xscreensaver-properties.desktop                               ;\
+          old="xscreensaver-properties.desktop"                             ;\
           if [ -f "$(DESTDIR)$(GTK_APPDIR)/$$old" ]; then                    \
             echo rm -f "$(DESTDIR)$(GTK_APPDIR)/$$old"                      ;\
                  rm -f "$(DESTDIR)$(GTK_APPDIR)/$$old"                      ;\
           fi                                                                ;\
           for name in xscreensaver.desktop xscreensaver-settings.desktop ; do\
-           echo $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_APPDIR)/$$name       ;\
-                $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_APPDIR)/$$name       ;\
-           echo chmod a+x $(DESTDIR)$(GTK_APPDIR)/$$name                    ;\
-                chmod a+x $(DESTDIR)$(GTK_APPDIR)/$$name                    ;\
+           echo $(INSTALL_DATA) "$$name" "$(DESTDIR)$(GTK_APPDIR)/$$name"   ;\
+                $(INSTALL_DATA) "$$name" "$(DESTDIR)$(GTK_APPDIR)/$$name"   ;\
+           echo chmod a+x "$(DESTDIR)$(GTK_APPDIR)/$$name"                  ;\
+                chmod a+x "$(DESTDIR)$(GTK_APPDIR)/$$name"                  ;\
           done                                                              ;\
         fi
 
+# xscreensaver.service
+# into /usr/lib/systemd/user/
+# This is the standard spot for multi-user installations.
+# For single user installations, it can go in $HOME/.config/systemd/user/
+install-systemd:: xscreensaver.service
+       @dir="$(DESTDIR)$(SYSTEMD_DIR)"                                      ;\
+        name="$<"                                                           ;\
+        if [ -d "$$dir" ]; then                                              \
+          echo $(INSTALL_DATA) "$$name" "$$dir/$$name"                      ;\
+               $(INSTALL_DATA) "$$name" "$$dir/$$name"                      ;\
+        fi
+
 # xscreensaver.service
 # into /usr/share/xscreensaver/
-# But maybe it should instead be installed as:
-# $(prefix)/share/dbus-1/system-services/org.jwz.xscreensaver.service
-# Or would that make it be enabled by default?
-#
-install-gnome:: xscreensaver.service
-       @if [ ! -d "$(DESTDIR)$(GTK_SHAREDIR)" ]; then                        \
-          echo $(INSTALL_DIRS) "$(DESTDIR)$(GTK_SHAREDIR)"                  ;\
-               $(INSTALL_DIRS) "$(DESTDIR)$(GTK_SHAREDIR)"                  ;\
+# Nothing uses this, but the manual's installation instructions reference it.
+install-systemd:: xscreensaver.service
+       @dir="$(DESTDIR)$(GTK_SHAREDIR)"                                     ;\
+        name="$<"                                                           ;\
+        if [ ! -d "$$dir" ]; then                                            \
+          echo $(INSTALL_DIRS) "$$dir"                                      ;\
+               $(INSTALL_DIRS) "$$dir"                                      ;\
         fi                                                                  ;\
-        name=xscreensaver.service                                           ;\
-        echo $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_SHAREDIR)/$$name        ;\
-             $(INSTALL_DATA) $$name $(DESTDIR)$(GTK_SHAREDIR)/$$name
+        echo $(INSTALL_DATA) "$$name" "$$dir/$$name"                        ;\
+             $(INSTALL_DATA) "$$name" "$$dir/$$name"
 
 # xscreensaver.png
 # into /usr/share/pixmaps/
 install-gnome:: $(LOGO)
-       @if [ "$(GTK_DATADIR)" != "" ]; then                                  \
+       @if [ ! -z "$(GTK_DATADIR)" ]; then                                   \
            if [ ! -d "$(DESTDIR)$(GTK_ICONDIR)" ]; then                              \
              echo $(INSTALL_DIRS) "$(DESTDIR)$(GTK_ICONDIR)"                ;\
                   $(INSTALL_DIRS) "$(DESTDIR)$(GTK_ICONDIR)"                ;\
            fi                                                                ;\
-          target=xscreensaver.png                                           ;\
-          echo $(INSTALL_DATA) $(LOGO)                                       \
-                 $(DESTDIR)$(GTK_ICONDIR)/$$target                          ;\
-               $(INSTALL_DATA) $(LOGO)                                       \
-                 $(DESTDIR)$(GTK_ICONDIR)/$$target                          ;\
-        fi
+          file="xscreensaver.png"                                           ;\
+          echo $(INSTALL_DATA) "$(LOGO)" "$(DESTDIR)$(GTK_ICONDIR)/$$file"  ;\
+               $(INSTALL_DATA) "$(LOGO)" "$(DESTDIR)$(GTK_ICONDIR)/$$file"  ;\
+         fi
 
 install-gnome:: uninstall-old-gnome-icons
 install-gnome:: update-icon-caches
@@ -639,10 +581,10 @@ update-icon-caches::
                  /usr/share/pixmaps/index.theme                              \
                  /usr/share/pixmaps/*/index.theme                            \
         ; do                                                                 \
-          if [ -f $$f ]; then                                                \
-            f=`dirname $$f`                                                 ;\
-            echo $(UPDATE_ICON_CACHE) --force --quiet $$f                   ;\
-                 $(UPDATE_ICON_CACHE) --force --quiet $$f                   ;\
+          if [ -f "$$f" ]; then                                              \
+            f="`dirname "$$f"`"                                             ;\
+            echo $(UPDATE_ICON_CACHE) --force --quiet "$$f"                 ;\
+                 $(UPDATE_ICON_CACHE) --force --quiet "$$f"                 ;\
           fi                                                                ;\
         done
 
@@ -651,14 +593,14 @@ update-icon-caches::
 # into /usr/share/applications/
 uninstall-gnome::
        @if [ "$(GTK_DATADIR)" != "" ]; then                                  \
-         old=xscreensaver-properties.desktop                                ;\
+         old="xscreensaver-properties.desktop"                              ;\
          if [ -f "$old" ]; then                                              \
-           echo rm -f $(DESTDIR)$(GTK_APPDIR)/$$old                         ;\
-                rm -f $(DESTDIR)$(GTK_APPDIR)/$$old                         ;\
+           echo rm -f "$(DESTDIR)$(GTK_APPDIR)/$$old"                       ;\
+                rm -f "$(DESTDIR)$(GTK_APPDIR)/$$old"                       ;\
          fi                                                                 ;\
          for f in xscreensaver.desktop xscreensaver-settings.desktop; do     \
-           echo rm -f $(DESTDIR)$(GTK_APPDIR)/$$f                           ;\
-                rm -f $(DESTDIR)$(GTK_APPDIR)/$$f                           ;\
+           echo rm -f "$(DESTDIR)$(GTK_APPDIR)/$$f"                         ;\
+                rm -f "$(DESTDIR)$(GTK_APPDIR)/$$f"                         ;\
          done                                                               ;\
        fi
 
@@ -666,16 +608,16 @@ uninstall-gnome::
 # from /usr/share/pixmaps/
 uninstall-gnome::
        @if [ "$(GTK_ICONDIR)" != "" ]; then                                  \
-         target=xscreensaver.xpm                                            ;\
-         echo rm -f $(DESTDIR)$(GTK_ICONDIR)/$$target                       ;\
-              rm -f $(DESTDIR)$(GTK_ICONDIR)/$$target                       ;\
+         target="xscreensaver.xpm"                                           ;\
+         echo rm -f "$(DESTDIR)$(GTK_ICONDIR)/$$target"                     ;\
+              rm -f "$(DESTDIR)$(GTK_ICONDIR)/$$target"                     ;\
         fi
 
 # /usr/share/xscreensaver/ui/*.png and *.ui no longer used as of 2022, 6.05.
 uninstall-gnome::
        @if [ "$(GTK_ICONDIR)" != "" ]; then                                  \
-         echo rm -rf $(DESTDIR)$(GTK_SHAREDIR)/ui                           ;\
-              rm -rf $(DESTDIR)$(GTK_SHAREDIR)/ui                           ;\
+         echo rm -rf "$(DESTDIR)$(GTK_SHAREDIR)/ui"                         ;\
+              rm -rf "$(DESTDIR)$(GTK_SHAREDIR)/ui"                         ;\
         fi
 
 # What is all this crap with the wrong logo?
@@ -697,23 +639,24 @@ uninstall-old-gnome-icons::
 
 # /usr/share/xscreensaver/glade/ no longer used as of 2022.
 uninstall-gnome::
-       -rm -rf $(GTK_DATADIR)/xscreensaver/glade
+       -rm -rf "$(GTK_DATADIR)/xscreensaver/glade"
 
 
 # /usr/share/xscreensaver/config/README
 install-xml:
-       @dest=$(DESTDIR)$(HACK_CONF_DIR) ;                              \
-        if [ ! -d $$dest ]; then                                       \
-          $(INSTALL_DIRS) $$dest ;                                     \
+       @dest="$(DESTDIR)$(HACK_CONF_DIR)" ;                            \
+        if [ ! -d "$$dest" ]; then                                     \
+          echo $(INSTALL_DIRS) "$$dest" ;                              \
+               $(INSTALL_DIRS) "$$dest" ;                              \
         fi ;                                                           \
         src=$(srcdir)/../hacks/config ;                                \
-        echo $(INSTALL_DATA) $$src/README $$dest/README ;              \
-             $(INSTALL_DATA) $$src/README $$dest/README
+        echo $(INSTALL_DATA) "$$src/README" "$$dest/README" ;          \
+             $(INSTALL_DATA) "$$src/README" "$$dest/README"
 
 
 # /usr/share/xscreensaver/config/README
 uninstall-xml:
-       rm -f $(DESTDIR)$(HACK_CONF_DIR)/README
+       -rm -f "$(DESTDIR)$(HACK_CONF_DIR)/README"
 
 
 ##############################################################################
@@ -723,13 +666,13 @@ uninstall-xml:
 ##############################################################################
 
 clean:
-       -rm -f *.o a.out core $(EXES) $(UTIL_EXES) $(SETUID_EXES) \
+       -rm -f ./*.o a.out core $(EXES) $(UTIL_EXES) $(SETUID_EXES) \
        $(DEMO_EXES) $(TEST_EXES) \
        XScreenSaver_ad.h XScreenSaver_Xm_ad.h
 
 distclean: clean
        -rm -f \
-       TAGS *~ "#"* *.rej *.orig \
+       TAGS ./*~ "#"* ./*.rej ./*.orig \
        Makefile \
        XScreenSaver.ad \
        xscreensaver.pam
@@ -748,7 +691,7 @@ depend: XScreenSaver_ad.h XScreenSaver_Xm_ad.h
 # to include only dependencies on files which are themselves a part of this
 # package.
 distdepend: check_men update_ad_version XScreenSaver_ad.h XScreenSaver_Xm_ad.h
-       @echo updating dependencies in `pwd`/Makefile.in... ;               \
+       @echo "updating dependencies in `pwd`/Makefile.in..." ;             \
        $(DEPEND) -w 0 -f -                                                 \
        -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \
        $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --    \
@@ -767,8 +710,8 @@ distdepend: check_men update_ad_version XScreenSaver_ad.h XScreenSaver_Xm_ad.h
              -e 's@$$.*\(XScreenSaver_Xm_ad\)@\1@g'                        \
              -e 's@ $$(srcdir)/\(.*config\.h\)@ \1@g' ;                    \
          echo ''                                                           \
-       ) > /tmp/distdepend.$$$$ &&                                         \
-       mv /tmp/distdepend.$$$$ Makefile.in
+       ) > "/tmp/distdepend.$$$$" &&                                       \
+       mv "/tmp/distdepend.$$$$" Makefile.in
 
 # Updates the version number in the app-defaults file to be in sync with 
 # the version number in version.h.  This is so people can tell when they
@@ -777,31 +720,31 @@ distdepend: check_men update_ad_version XScreenSaver_ad.h XScreenSaver_Xm_ad.h
 update_ad_version::
        @                                                                   \
   files="XScreenSaver.ad.in ../hacks/config/README ../OSX/bindist.rtf" ;    \
-  U=$(UTILS_SRC)/version.h ;                                               \
+  U="$(UTILS_SRC)/version.h" ;                                             \
   V=`sed -n 's/[^0-9]*\([0-9]\.[0-9][^ ]*\).*/\1/p' < $$U | head -1` ;     \
-  Y=`date '+%Y'` ;                                                         \
-  D=`date '+%d-%b-%Y'` ;                                                   \
+  Y="`date '+%Y'`" ;                                                       \
+  D="`date '+%d-%b-%Y'`" ;                                                 \
   for S in $$files ; do                                                            \
-    T=/tmp/xs.$$$$ ;                                                       \
+    T="/tmp/xs.$$$$" ;                                                     \
     sed -e "s/\(.*version \)[0-9][0-9]*\.[0-9.]*[ab]*[0-9]*\(.*\)/\1$$V\2/" \
         -e "s/\([0-9][0-9]-[A-Z][a-z][a-z]-[0-9][0-9][0-9]*\)/$$D/"        \
         -e "s/\( [0-9][0-9][0-9][0-9]-\)[0-9][0-9][0-9][0-9] /\1$$Y /"     \
-      < $$S > $$T ;                                                        \
-    if cmp -s $$S $$T ; then                                               \
+      < "$$S" > "$$T" ;                                                            \
+    if cmp -s "$$S" "$$T" ; then                                           \
       true ;                                                               \
     else                                                                   \
-      cat $$T > $$S ;                                                      \
+      cat "$$T" > "$$S" ;                                                  \
       echo "updated $$S to $$V $$D" ;                                      \
     fi ;                                                                   \
   done ;                                                                   \
-  rm $$T
+  rm "$$T"
 
 TAGS: tags
 tags:
        find $(srcdir) -name '*.[chly]' -print | xargs etags -a
 
 list_tarfiles:
-       @$(MAKE2) XScreenSaver_ad.h XScreenSaver_Xm_ad.h 2>&1 >/dev/null
+       @$(MAKE2) XScreenSaver_ad.h XScreenSaver_Xm_ad.h 2>&- >&-
        @find $(TARFILES) -type f -print | sort
 
 check_men:
@@ -966,9 +909,9 @@ xscreensaver-settings: @PREFERRED_DEMO_PROGRAM@
               "therefore no xscreensaver-settings!"                  ; \
          rm -f $@@EXEEXT@                                            ; \
        else                                                            \
-              rm -f $@@EXEEXT@                                       ; \
-         echo cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@      ; \
-              cp -p @PREFERRED_DEMO_PROGRAM@@EXEEXT@ $@@EXEEXT@      ; \
+              rm -f "$@@EXEEXT@"                                     ; \
+         echo cp -p "@PREFERRED_DEMO_PROGRAM@@EXEEXT@" "$@@EXEEXT@"  ; \
+              cp -p "@PREFERRED_DEMO_PROGRAM@@EXEEXT@" "$@@EXEEXT@"  ; \
        fi
 
 
@@ -979,23 +922,23 @@ XScreenSaver_ad.h::
        IN="XScreenSaver.ad" ;                                          \
        OUT=XScreenSaver_ad.h ;                                         \
        $(UTILS_SRC)/ad2c $$IN > $$TMP ;                                \
-       if cmp -s $$TMP $$OUT ; then                                    \
+       if cmp -s "$$TMP" "$$OUT" ; then                                \
          rm -f "$$TMP" ;                                               \
        else                                                            \
-         echo $(UTILS_SRC)/ad2c $$IN \> $$OUT ;                        \
-         mv $$TMP $$OUT ;                                              \
+         echo $(UTILS_SRC)/ad2c "$$IN" \> "$$OUT" ;                    \
+         mv "$$TMP" "$$OUT" ;                                          \
        fi
 
 XScreenSaver_Xm_ad.h::
        @TMP=/tmp/xs$$$$.h ;                                            \
        IN="XScreenSaver-Xm.ad" ;                                       \
        OUT=XScreenSaver_Xm_ad.h ;                                      \
-       $(UTILS_SRC)/ad2c $$IN > $$TMP ;                                \
-       if cmp -s $$TMP $$OUT ; then                                    \
+       $(UTILS_SRC)/ad2c "$$IN" > "$$TMP" ;                            \
+       if cmp -s "$$TMP" "$$OUT" ; then                                \
          rm -f "$$TMP" ;                                               \
        else                                                            \
-         echo $(UTILS_SRC)/ad2c $$IN \> $$OUT ;                        \
-         mv $$TMP $$OUT ;                                              \
+         echo $(UTILS_SRC)/ad2c "$$IN" \> "$$OUT" ;                    \
+         mv "$$TMP" "$$OUT" ;                                          \
        fi
 
 @INTLTOOL_DESKTOP_RULE@
index 115900d753a6d079984bf3838cec70fcb4797d42..3488bd2d8a557f20bac1d47b12f93ae00e6bc600 100644 (file)
@@ -4,8 +4,8 @@
 !            a screen saver and locker for the X window system
 !                            by Jamie Zawinski
 !
-!                              version 6.13
-!                              02-Dec-2025
+!                              version 6.14
+!                              15-Jan-2026
 !
 ! See "man xscreensaver" for more info.  The latest version is always
 ! available at https://www.jwz.org/xscreensaver/
@@ -530,19 +530,27 @@ XScreenSaver.bourneShell:         /bin/sh
                                hexadrop --root                             \n\
 @GL_KLUDGE@ GL:                                kaleidocycle --root                         \n\
 @GL_KLUDGE@ GL:                                quasicrystal --root                         \n\
+@GL_KLUDGE@ GL:                                starnest --root                             \n\
 @GL_KLUDGE@ GL:                                unknownpleasures --root                     \n\
+@GL_KLUDGE@ GL:                                alienbeacon --root                          \n\
                                binaryring --root                           \n\
 @GL_KLUDGE@ GL:                                cityflow --root                             \n\
 @GL_KLUDGE@ GL:                                geodesicgears --root                        \n\
 @GL_KLUDGE@ GL:                                projectiveplane --root                      \n\
 @GL_KLUDGE@ GL:                                romanboy --root                             \n\
                                tessellimage --root                         \n\
+@GL_KLUDGE@ GL:                                topologica --root                           \n\
 @GL_KLUDGE@ GL:                                winduprobot --root                          \n\
+@GL_KLUDGE@ GL:                                fluxcore --root                             \n\
+@GL_KLUDGE@ GL:                                gimbalharmonics --root                      \n\
+@GL_KLUDGE@ GL:                                protophore --root                           \n\
+@GL_KLUDGE@ GL:                                skyline --root                              \n\
 @GL_KLUDGE@ GL:                                splitflap --root                            \n\
 @GL_KLUDGE@ GL:                                cubestack --root                            \n\
 @GL_KLUDGE@ GL:                                cubetwist --root                            \n\
 @GL_KLUDGE@ GL:                                discoball --root                            \n\
 @GL_KLUDGE@ GL:                                dymaxionmap --root                          \n\
+@GL_KLUDGE@ GL:                                elementalring --root                        \n\
 @GL_KLUDGE@ GL:                                energystream --root                         \n\
 @GL_KLUDGE@ GL:                                hexstrut --root                             \n\
 @GL_KLUDGE@ GL:                                hydrostat --root                            \n\
@@ -561,6 +569,8 @@ XScreenSaver.bourneShell:           /bin/sh
                                vfeedback --root                            \n\
 @GL_KLUDGE@ GL:                                deepstars --root                            \n\
 @GL_KLUDGE@ GL:                                gravitywell --root                          \n\
+@GL_KLUDGE@ GL:                                synthwavecity --root                        \n\
+@GL_KLUDGE@ GL:                                batteredplanet --root                       \n\
 @GL_KLUDGE@ GL:                                beats --root                                \n\
 @GL_KLUDGE@ GL:                                covid19 --root                              \n\
 @GL_KLUDGE@ GL:                                etruscanvenus --root                        \n\
@@ -569,19 +579,27 @@ XScreenSaver.bourneShell:         /bin/sh
 @GL_KLUDGE@ GL:                                sphereeversion --root                       \n\
                                binaryhorizon --root                        \n\
                                marbling --root                             \n\
+@GL_KLUDGE@ GL:                                neontriangulator --root                     \n\
+@GL_KLUDGE@ GL:                                stripeytorus --root                         \n\
 @GL_KLUDGE@ GL:                                chompytower --root                          \n\
 @GL_KLUDGE@ GL:                                hextrail --root                             \n\
 @GL_KLUDGE@ GL:                                mapscroller --root                          \n\
 @GL_KLUDGE@ GL:                                nakagin --root                              \n\
 @GL_KLUDGE@ GL:                                squirtorus --root                           \n\
+@GL_KLUDGE@ GL:                                stardome --root                             \n\
 @GL_KLUDGE@ GL:                                cubocteversion --root                       \n\
                                droste --root                               \n\
+@GL_KLUDGE@ GL:                                logarithmiccircles --root                   \n\
+@GL_KLUDGE@ GL:                                neongravity --root                          \n\
 @GL_KLUDGE@ GL:                                papercube --root                            \n\
 @GL_KLUDGE@ GL:                                skulloop --root                             \n\
 @GL_KLUDGE@ GL:                                highvoltage --root                          \n\
 @GL_KLUDGE@ GL:                                kallisti --root                             \n\
 @GL_KLUDGE@ GL:                                klondike --root                             \n\
+@GL_KLUDGE@ GL:                                selfreflect --root                          \n\
+@GL_KLUDGE@ GL:                                truchetzoom --root                          \n\
 @GL_KLUDGE@ GL:                                dumpsterfire --root                         \n\
+@GL_KLUDGE@ GL:                                hexplasma --root                            \n\
 @GL_KLUDGE@ GL:                                hopffibration --root                        \n\
 @GL_KLUDGE@ GL:                                platonicfolding --root                      \n
 
@@ -594,10 +612,12 @@ XScreenSaver.bourneShell:         /bin/sh
 !
 !=============================================================================
 
+*hacks.alienbeacon.name:    Alien Beacon
 *hacks.antinspect.name:     Ant Inspect
 *hacks.antmaze.name:        Ant Maze
 *hacks.antspotlight.name:   Ant Spotlight
 *hacks.apple2.name:         Apple ][
+*hacks.batteredplanet.name: Battered Planet
 *hacks.binaryhorizon.name:  Binary Horizon
 *hacks.binaryring.name:     Binary Ring
 *hacks.blinkbox.name:       Blink Box
@@ -626,6 +646,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.dnalogo.name:        DNA Logo
 *hacks.dumpsterfire.name:   Dumpster Fire
 *hacks.dymaxionmap.name:    Dymaxion Map
+*hacks.elementalring.name:  Elemental Ring
 *hacks.energystream.name:   Energy Stream
 *hacks.etruscanvenus.name:  Etruscan Venus
 *hacks.euler2d.name:        Euler 2D
@@ -636,11 +657,13 @@ XScreenSaver.bourneShell:         /bin/sh
 *hacks.flipscreen3d.name:   Flip Screen 3D
 *hacks.fliptext.name:       Flip Text
 *hacks.fluidballs.name:     Fluid Balls
+*hacks.fluxcore.name:       Flux Core
 *hacks.flyingtoasters.name: Flying Toasters
 *hacks.fontglide.name:      Font Glide
 *hacks.fuzzyflakes.name:    Fuzzy Flakes
 *hacks.geodesicgears.name:  Geodesic Gears
 *hacks.gflux.name:          GFlux
+*hacks.gimbalharmonics.name:Gimbal Harmonics
 *hacks.glblur.name:         GL Blur
 *hacks.glcells.name:        GL Cells
 *hacks.gleidescope.name:    Gleidescope
@@ -655,6 +678,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.glsnake.name:        GL Snake
 *hacks.gltext.name:         GL Text
 *hacks.gravitywell.name:    Gravity Well
+*hacks.hexplasma.name:      Hex Plasma
 *hacks.hexstrut.name:       Hex Strut
 *hacks.hextrail.name:       Hex Trail
 *hacks.highvoltage.name:    High Voltage
@@ -665,6 +689,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.juggler3d.name:      Juggler 3D
 *hacks.lcdscrub.name:       LCD Scrub
 *hacks.lmorph.name:         LMorph
+*hacks.logarithmiccircles.name:Logarithmic Circles
 *hacks.m6502.name:          m6502
 *hacks.mapscroller.name:    Map Scroller
 *hacks.maze3d.name:         Maze 3D
@@ -676,6 +701,8 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.moire.name:          Moiré
 *hacks.moire2.name:         Moiré 2
 *hacks.morph3d.name:        Morph 3D
+*hacks.neongravity.name:    Neon Gravity
+*hacks.neontriangulator.name:Neon Triangulator
 *hacks.nerverot.name:       Nerve Rot
 *hacks.noseguy.name:        Nose Guy
 *hacks.pacman.name:         Pac-Man
@@ -692,6 +719,7 @@ XScreenSaver.bourneShell:           /bin/sh
 *hacks.rotzoomer.name:      Rot Zoomer
 *hacks.rubikblocks.name:    Rubik Blocks
 *hacks.sballs.name:         SBalls
+*hacks.selfreflect.name:    Self Reflect
 *hacks.shadebobs.name:      Shade Bobs
 *hacks.sierpinski3d.name:   Sierpinski 3D
 *hacks.skytentacles.name:   Sky Tentacles
@@ -699,13 +727,18 @@ XScreenSaver.bourneShell:         /bin/sh
 *hacks.speedmine.name:      Speed Mine
 *hacks.sphereeversion.name: Sphere Eversion
 *hacks.splitflap.name:      Split-Flap
+*hacks.stardome.name:       Star Dome
+*hacks.starnest.name:       Star Nest
 *hacks.starwars.name:       Star Wars
 *hacks.stonerview.name:     Stoner View
+*hacks.stripeytorus.name:   Stripey Torus
+*hacks.synthwavecity.name:  Synthwave City
 *hacks.t3d.name:            T3D
 *hacks.testx11.name:        Test X11
 *hacks.timetunnel.name:     Time Tunnel
 *hacks.topblock.name:       Top Block
 *hacks.tronbit.name:        Tron Bit
+*hacks.truchetzoom.name:    Truchet Zoom
 *hacks.unknownpleasures.name:Unknown Pleasures
 *hacks.vfeedback.name:      VFeedback
 *hacks.vidwhacker.name:     Vid Whacker
index df1c1698737395fd621149b68f1a150f567efc5e..25bdb58b8d4a627ffaaeebec8d55121e76253967 100644 (file)
                                hexadrop --root                             \\n\
   GL:                          kaleidocycle --root                         \\n\
   GL:                          quasicrystal --root                         \\n\
+  GL:                          starnest --root                             \\n\
   GL:                          unknownpleasures --root                     \\n\
+  GL:                          alienbeacon --root                          \\n\
                                binaryring --root                           \\n\
   GL:                          cityflow --root                             \\n\
   GL:                          geodesicgears --root                        \\n\
   GL:                          projectiveplane --root                      \\n\
   GL:                          romanboy --root                             \\n\
                                tessellimage --root                         \\n\
+  GL:                          topologica --root                           \\n\
   GL:                          winduprobot --root                          \\n\
+  GL:                          fluxcore --root                             \\n\
+  GL:                          gimbalharmonics --root                      \\n\
+  GL:                          protophore --root                           \\n\
+  GL:                          skyline --root                              \\n\
   GL:                          splitflap --root                            \\n\
   GL:                          cubestack --root                            \\n\
   GL:                          cubetwist --root                            \\n\
   GL:                          discoball --root                            \\n\
   GL:                          dymaxionmap --root                          \\n\
+  GL:                          elementalring --root                        \\n\
   GL:                          energystream --root                         \\n\
   GL:                          hexstrut --root                             \\n\
   GL:                          hydrostat --root                            \\n\
                                vfeedback --root                            \\n\
   GL:                          deepstars --root                            \\n\
   GL:                          gravitywell --root                          \\n\
+  GL:                          synthwavecity --root                        \\n\
+  GL:                          batteredplanet --root                       \\n\
   GL:                          beats --root                                \\n\
   GL:                          covid19 --root                              \\n\
   GL:                          etruscanvenus --root                        \\n\
   GL:                          sphereeversion --root                       \\n\
                                binaryhorizon --root                        \\n\
                                marbling --root                             \\n\
+  GL:                          neontriangulator --root                     \\n\
+  GL:                          stripeytorus --root                         \\n\
   GL:                          chompytower --root                          \\n\
   GL:                          hextrail --root                             \\n\
   GL:                          mapscroller --root                          \\n\
   GL:                          nakagin --root                              \\n\
   GL:                          squirtorus --root                           \\n\
+  GL:                          stardome --root                             \\n\
   GL:                          cubocteversion --root                       \\n\
                                droste --root                               \\n\
+  GL:                          logarithmiccircles --root                   \\n\
+  GL:                          neongravity --root                          \\n\
   GL:                          papercube --root                            \\n\
   GL:                          skulloop --root                             \\n\
   GL:                          highvoltage --root                          \\n\
   GL:                          kallisti --root                             \\n\
   GL:                          klondike --root                             \\n\
+  GL:                          selfreflect --root                          \\n\
+  GL:                          truchetzoom --root                          \\n\
   GL:                          dumpsterfire --root                         \\n\
+  GL:                          hexplasma --root                            \\n\
   GL:                          hopffibration --root                        \\n\
   GL:                          platonicfolding --root                      \\n",
+"*hacks.alienbeacon.name:    Alien Beacon",
 "*hacks.antinspect.name:     Ant Inspect",
 "*hacks.antmaze.name:        Ant Maze",
 "*hacks.antspotlight.name:   Ant Spotlight",
 "*hacks.apple2.name:         Apple ][",
+"*hacks.batteredplanet.name: Battered Planet",
 "*hacks.binaryhorizon.name:  Binary Horizon",
 "*hacks.binaryring.name:     Binary Ring",
 "*hacks.blinkbox.name:       Blink Box",
 "*hacks.dnalogo.name:        DNA Logo",
 "*hacks.dumpsterfire.name:   Dumpster Fire",
 "*hacks.dymaxionmap.name:    Dymaxion Map",
+"*hacks.elementalring.name:  Elemental Ring",
 "*hacks.energystream.name:   Energy Stream",
 "*hacks.etruscanvenus.name:  Etruscan Venus",
 "*hacks.euler2d.name:        Euler 2D",
 "*hacks.flipscreen3d.name:   Flip Screen 3D",
 "*hacks.fliptext.name:       Flip Text",
 "*hacks.fluidballs.name:     Fluid Balls",
+"*hacks.fluxcore.name:       Flux Core",
 "*hacks.flyingtoasters.name: Flying Toasters",
 "*hacks.fontglide.name:      Font Glide",
 "*hacks.fuzzyflakes.name:    Fuzzy Flakes",
 "*hacks.geodesicgears.name:  Geodesic Gears",
 "*hacks.gflux.name:          GFlux",
+"*hacks.gimbalharmonics.name:Gimbal Harmonics",
 "*hacks.glblur.name:         GL Blur",
 "*hacks.glcells.name:        GL Cells",
 "*hacks.gleidescope.name:    Gleidescope",
 "*hacks.glsnake.name:        GL Snake",
 "*hacks.gltext.name:         GL Text",
 "*hacks.gravitywell.name:    Gravity Well",
+"*hacks.hexplasma.name:      Hex Plasma",
 "*hacks.hexstrut.name:       Hex Strut",
 "*hacks.hextrail.name:       Hex Trail",
 "*hacks.highvoltage.name:    High Voltage",
 "*hacks.juggler3d.name:      Juggler 3D",
 "*hacks.lcdscrub.name:       LCD Scrub",
 "*hacks.lmorph.name:         LMorph",
+"*hacks.logarithmiccircles.name:Logarithmic Circles",
 "*hacks.m6502.name:          m6502",
 "*hacks.mapscroller.name:    Map Scroller",
 "*hacks.maze3d.name:         Maze 3D",
 "*hacks.moire.name:          Moiré",
 "*hacks.moire2.name:         Moiré 2",
 "*hacks.morph3d.name:        Morph 3D",
+"*hacks.neongravity.name:    Neon Gravity",
+"*hacks.neontriangulator.name:Neon Triangulator",
 "*hacks.nerverot.name:       Nerve Rot",
 "*hacks.noseguy.name:        Nose Guy",
 "*hacks.pacman.name:         Pac-Man",
 "*hacks.rotzoomer.name:      Rot Zoomer",
 "*hacks.rubikblocks.name:    Rubik Blocks",
 "*hacks.sballs.name:         SBalls",
+"*hacks.selfreflect.name:    Self Reflect",
 "*hacks.shadebobs.name:      Shade Bobs",
 "*hacks.sierpinski3d.name:   Sierpinski 3D",
 "*hacks.skytentacles.name:   Sky Tentacles",
 "*hacks.speedmine.name:      Speed Mine",
 "*hacks.sphereeversion.name: Sphere Eversion",
 "*hacks.splitflap.name:      Split-Flap",
+"*hacks.stardome.name:       Star Dome",
+"*hacks.starnest.name:       Star Nest",
 "*hacks.starwars.name:       Star Wars",
 "*hacks.stonerview.name:     Stoner View",
+"*hacks.stripeytorus.name:   Stripey Torus",
+"*hacks.synthwavecity.name:  Synthwave City",
 "*hacks.t3d.name:            T3D",
 "*hacks.testx11.name:        Test X11",
 "*hacks.timetunnel.name:     Time Tunnel",
 "*hacks.topblock.name:       Top Block",
 "*hacks.tronbit.name:        Tron Bit",
+"*hacks.truchetzoom.name:    Truchet Zoom",
 "*hacks.unknownpleasures.name:Unknown Pleasures",
 "*hacks.vfeedback.name:      VFeedback",
 "*hacks.vidwhacker.name:     Vid Whacker",
index 9ab785d1353cca92174fecd5d8b515a4cc707260..28e9fe0c2cf628941fd6944c92ec5013ce15727b 100644 (file)
@@ -2581,10 +2581,13 @@ populate_prefs_page (state *s)
 
   Bool dpms_full_p;
   char *lock_why = 0;
+  static Bool logged_p = FALSE;
 
 # ifdef NO_LOCKING
   s->locking_supported_p = FALSE;
   lock_why = _("Not compiled with support for locking");
+# else
+  s->locking_supported_p = TRUE;
 # endif
 
   if (s->backend == WAYLAND_BACKEND ||
@@ -2600,6 +2603,11 @@ populate_prefs_page (state *s)
   if (!s->multi_screen_p && p->mode == RANDOM_HACKS_SAME)
     p->mode = RANDOM_HACKS;
 
+  if (s->debug_p && lock_why && !logged_p)
+    {
+      fprintf (stderr, "%s: %s\n", blurb(), lock_why);
+      logged_p = TRUE;
+    }
 
   /* The file supports timeouts of less than a minute, but the GUI does
      not, so throttle the values to be at least one minute (since "0" is
@@ -2826,21 +2834,20 @@ populate_prefs_page (state *s)
 
 
 /* Creates a human-readable anchor to put on a URL.
+   Duplicated in OSX/XScreenSaverConfigSheet.m.
  */
 static char *
 anchorize (const char *url)
 {
-  const char *wiki1 =  "http://en.wikipedia.org/wiki/";
-  const char *wiki2 = "https://en.wikipedia.org/wiki/";
-  const char *math1 =  "http://mathworld.wolfram.com/";
-  const char *math2 = "https://mathworld.wolfram.com/";
-  if (!strncmp (wiki1, url, strlen(wiki1)) ||
-      !strncmp (wiki2, url, strlen(wiki2))) {
+  const char *wiki  = "https://en.wikipedia.org/wiki/";
+  const char *math  = "https://mathworld.wolfram.com/";
+  const char *shade = "https://www.shadertoy.com/view/";
+  if (!strncmp (wiki, url, strlen(wiki))) {
     char *anchor = (char *) malloc (strlen(url) * 3 + 10);
     const char *in;
     char *out;
     strcpy (anchor, "Wikipedia: \"");
-    in = url + strlen(!strncmp (wiki1, url, strlen(wiki1)) ? wiki1 : wiki2);
+    in = url + strlen(wiki);
     out = anchor + strlen(anchor);
     while (*in) {
       if (*in == '_') {
@@ -2866,13 +2873,12 @@ anchorize (const char *url)
     *out = 0;
     return anchor;
 
-  } else if (!strncmp (math1, url, strlen(math1)) ||
-             !strncmp (math2, url, strlen(math2))) {
+  } else if (!strncmp (math, url, strlen(math))) {
     char *anchor = (char *) malloc (strlen(url) * 3 + 10);
     const char *start, *in;
     char *out;
     strcpy (anchor, "MathWorld: \"");
-    start = url + strlen(!strncmp (math1, url, strlen(math1)) ? math1 : math2);
+    start = url + strlen(math);
     in = start;
     out = anchor + strlen(anchor);
     while (*in) {
@@ -2892,6 +2898,16 @@ anchorize (const char *url)
     *out = 0;
     return anchor;
 
+  } else if (!strncmp (shade, url, strlen(shade))) {
+    char *anchor = (char *) malloc (strlen(url) * 3 + 10);
+    const char *in;
+    char *out;
+    strcpy (anchor, "Shadertoy: ");
+    in = url + strlen(shade);
+    out = anchor + strlen(anchor);
+    strcat (out, in);
+    return anchor;
+
   } else {
     return strdup (url);
   }
index 3674c1f419ed6d68caca126c8046c8f854e844f5..6b6e3f1f3ce16169fae58694b6d304dd88516b0d 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright © 1992-2025 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1992-2026 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -1680,6 +1680,7 @@ xshm_screenshot_grab (Display *dpy, Window window,
 
 
 #ifdef USE_GL
+#ifndef HAVE_JWZGLES
 static void
 opengl_make_current (Display *dpy, xshm_fade_info *info)
 {
@@ -1726,6 +1727,7 @@ check_gl_error (const char *type)
   fprintf (stderr, "%s: %s error: %s\n", progname, type, e);
   return True;
 }
+#endif /* HAVE_JWZGLES */
 #endif /* USE_GL */
 
 
@@ -1843,6 +1845,7 @@ xshm_fade (XtAppContext app, Display *dpy,
                        KeyPressMask | ButtonPressMask); */
 
 # ifdef USE_GL
+#  ifndef HAVE_JWZGLES
       /* Copy the screenshot pixmap to the texture XImage */
       XGetSubImage (dpy, info[screen].screenshot,
                     0, 0, xgwa.width, xgwa.height,
@@ -1869,6 +1872,7 @@ xshm_fade (XtAppContext app, Display *dpy,
       /* Connect the window to an OpenGL context */
       info[screen].glx_context =
         openGL_context_for_window (xgwa.screen, info[screen].window);
+      if (!info[screen].glx_context) goto FAIL;
       opengl_make_current (dpy, &info[screen]);
       if (check_gl_error ("connect")) goto FAIL;
 
@@ -1911,6 +1915,7 @@ xshm_fade (XtAppContext app, Display *dpy,
       glFrontFace (GL_CCW);
       if (check_gl_error ("GL setup")) goto FAIL;
 
+#  endif /* !HAVE_JWZGLES */
 # else /* !USE_GL */
       /* Copy the screenshot pixmap to the source image */
       if (! get_xshm_image (dpy, info[screen].screenshot, info[screen].src,
@@ -2058,7 +2063,8 @@ xshm_fade (XtAppContext app, Display *dpy,
             XDestroyImage (info[screen].src);
           if (info[screen].texid)
             glDeleteTextures (1, &info[screen].texid);
-          openGL_destroy_context (dpy, info[screen].glx_context);
+          if (info[screen].glx_context)
+            openGL_destroy_context (dpy, info[screen].glx_context);
 # else /* !USE_GL */
           if (info[screen].src)
             destroy_xshm_image (dpy, info[screen].src, &shm_info);
@@ -2108,6 +2114,7 @@ xshm_fade (XtAppContext app, Display *dpy,
 static int
 opengl_whack (Display *dpy, xshm_fade_info *info, float ratio)
 {
+# ifndef HAVE_JWZGLES
   GLfloat w = info->texw;
   GLfloat h = info->texh;
 
@@ -2138,6 +2145,9 @@ opengl_whack (Display *dpy, xshm_fade_info *info, float ratio)
 
   if (check_gl_error ("gl whack")) return True;
   return False;
+#else /* HAVE_JWZGLES */
+  return True;
+#endif
 }
 
 
index 4d434db1b5be9c9c54a09c9dc2c5f2b15c713fcd..49bd3e9a7a10979806d48f6037138c399e173b26 100644 (file)
@@ -1,5 +1,5 @@
 /* passwd-pam.c --- verifying typed passwords with PAM
- * xscreensaver, Copyright © 1993-2022 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright © 1993-2025 Jamie Zawinski <jwz@jwz.org>
  * By Bill Nottingham <notting@redhat.com> and jwz.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
 #include "blurb.h"
 #include "auth.h"
 
-
-/* Some time between Red Hat 4.2 and 7.0, the words were transposed 
-   in the various PAM_x_CRED macro names.  Yay!
- */
-#if !defined(PAM_REFRESH_CRED) && defined(PAM_CRED_REFRESH)
-# define PAM_REFRESH_CRED PAM_CRED_REFRESH
-#endif
-#if !defined(PAM_REINITIALIZE_CRED) && defined(PAM_CRED_REINITIALIZE)
-# define PAM_REINITIALIZE_CRED PAM_CRED_REINITIALIZE
-#endif
-
 static int pam_conversation (int nmsgs,
                              const struct pam_message **msg,
                              struct pam_response **resp,
@@ -115,16 +104,6 @@ typedef struct {
 #endif /* !PAM_STRERROR_TWO_ARGS */
 
 
-/* On SunOS 5.6, the `pam_conv.appdata_ptr' slot seems to be ignored, and
-   the `closure' argument to pc.conv always comes in as random garbage.
-   So we get around this by using a global variable instead.  Shoot me!
-
-   (I've been told this is bug 4092227, and is fixed in Solaris 7.)
-   (I've also been told that it's fixed in Solaris 2.6 by patch 106257-05.)
- */
-static void *suns_pam_implementation_blows = 0;
-
-
 /* This function invokes the PAM conversation.  It conducts a full
    authentication round by presenting the GUI with various prompts.
  */
@@ -154,11 +133,6 @@ pam_try_unlock (void *closure,
   pc.appdata_ptr = &conv_closure;
   pc.conv = &pam_conversation;
 
-  /* On SunOS 5.6, the `appdata_ptr' slot seems to be ignored, and the
-     `closure' argument to pc.conv always comes in as random garbage. */
-  suns_pam_implementation_blows = pc.appdata_ptr;
-
-
   /* Initialize PAM.
    */
   status = pam_start (service, user, &pc, &pamh);
@@ -190,66 +164,42 @@ pam_try_unlock (void *closure,
 
   if (status == PAM_SUCCESS)  /* So far so good... */
     {
-      int status2;
-
-      /* On most systems, it doesn't matter whether the account modules
-         are run, or whether they fail or succeed.
-
-         On some systems, the account modules fail, because they were
-         never configured properly, but it's necessary to run them anyway
-         because certain PAM modules depend on side effects of the account
-         modules having been run.
-
-         And on still other systems, the account modules are actually
-         used, and failures in them should be considered to be true!
-
-         So:
-         - We run the account modules on all systems.
-         - Whether we ignore them is a configure option.
-
-         It's all kind of a mess.
+      /* In the distant past, some systems required that we not call
+         pam_acct_mgmt(), and some other systems required that we call
+         it but ignore the error code it returned.  I'm going to assume
+         that this nonsense is no longer ongoing.  -- jwz 2025.
        */
-      status2 = pam_acct_mgmt (pamh, 0);
+      status = pam_acct_mgmt (pamh, 0);
 
       if (verbose_p)
         fprintf (stderr, "%s:   pam_acct_mgmt (...) ==> %d (%s)\n",
-                 blurb(), status2, PAM_STRERROR(pamh, status2));
+                 blurb(), status, PAM_STRERROR(pamh, status));
 
-      /* HPUX for some reason likes to make PAM defines different from
-       * everyone else's. */
-#ifdef PAM_AUTHTOKEN_REQD
-      if (status2 == PAM_AUTHTOKEN_REQD)
-#else
-      if (status2 == PAM_NEW_AUTHTOK_REQD)
-#endif
+      if (status == PAM_NEW_AUTHTOK_REQD)
         {
-          status2 = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
+          status = pam_chauthtok (pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
           if (verbose_p)
             fprintf (stderr, "%s: pam_chauthtok (...) ==> %d (%s)\n",
-                     blurb(), status2, PAM_STRERROR(pamh, status2));
+                     blurb(), status, PAM_STRERROR(pamh, status));
         }
+    }
 
-      /* If 'configure' requested that we believe the results of PAM
-         account module failures, then obey that status code.
-         Otherwise ignore it.
-       */
-#ifdef PAM_CHECK_ACCOUNT_TYPE
-       status = status2;
-#endif
-
+  if (status == PAM_SUCCESS)  /* So far so good... */
+    {
       /* Each time we successfully authenticate, refresh credentials,
          for Kerberos/AFS/DCE/etc.  If this fails, just ignore that
          failure and blunder along; it shouldn't matter.
        */
+      int status2;
 
-#if defined(__linux__)
+# if defined(__sun) && defined(__SVR4)  /* Solaris */
+      status2 = pam_setcred (pamh, PAM_REFRESH_CRED);
+# else
       /* Apparently the Linux PAM library ignores PAM_REFRESH_CRED and only
-         refreshes credentials when using PAM_REINITIALIZE_CRED. */
+         refreshes credentials when using PAM_REINITIALIZE_CRED.  Let's
+         assume that other OSes are more like Linux than like Solaris. */
       status2 = pam_setcred (pamh, PAM_REINITIALIZE_CRED);
-#else
-      /* But Solaris requires PAM_REFRESH_CRED or extra prompts appear. */
-      status2 = pam_setcred (pamh, PAM_REFRESH_CRED);
-#endif
+# endif
 
       if (verbose_p)
         fprintf (stderr, "%s:   pam_setcred (...) ==> %d (%s)\n",
@@ -347,11 +297,7 @@ pam_conversation (int nmsgs,
   auth_message *messages = 0;
   auth_response *authresp = 0;
   struct pam_response *pam_responses;
-  pam_conv_closure *conv_closure;
-
-  /* On SunOS 5.6, the `closure' argument always comes in as random garbage. */
-  closure = suns_pam_implementation_blows;
-  conv_closure = closure;
+  pam_conv_closure *conv_closure = closure;
 
   /* Converting the PAM prompts into the XScreenSaver native format.
    * It was a design goal to collapse (INFO,PROMPT) pairs from PAM
index 7252e5e86dd4e618ca4112d43687cdb665dbd9c8..e7f0e0b20f31a83a8be531836f7fe8d5ec2b88ee 100644 (file)
 # include <X11/extensions/Xinerama.h>
 #endif /* HAVE_XINERAMA */
 
-#ifdef HAVE_XF86VMODE
-# include <X11/extensions/xf86vmode.h>
-#endif /* HAVE_XF86VMODE */
-
 #include "blurb.h"
 #include "screens.h"
 
index 827146a9488fc14c13a77b3b6dc99037fa00ab3c..48e3c1a885a484a002dc9156a9f83fd2867f17a8 100644 (file)
@@ -49,7 +49,7 @@
 #endif
 
 #if defined(USE_GL) && !defined(HAVE_EGL)
-# include <OpenGL/gl.h>                /* For GLXContext in visual-gl.h */
+# include <GL/gl.h>            /* For GLXContext in visual-gl.h */
 # include <GL/glx.h>
 #endif
 
index 119241f2897ad0560a06e39a0a5d56b395d0cd19..60cb810e9d92381ace6c048b37b26182b77e2daa 100644 (file)
 #include <X11/Intrinsic.h>
 #include <time.h>
 
-#ifdef HAVE_XF86VMODE
-# include <X11/extensions/xf86vmode.h>
-#endif /* HAVE_XF86VMODE */
-
-#ifdef HAVE_XINERAMA
-# include <X11/extensions/Xinerama.h>
-#endif /* HAVE_XINERAMA */
-
 #include "xscreensaver.h"
 #include "atoms.h"
 #include "visual.h"
index 72ba13d5f6ad15234c5b00176d17c4d5352a2c2e..1d27e7f91aa4be0d82d542c2374438136dfc4e28 100644 (file)
@@ -241,9 +241,11 @@ If you are not using GNOME, KDE or LXDE, the way to launch XScreenSaver
 at login is probably
 .BR systemd (1).
 
-Copy the file \fI/usr/share/xscreensaver/xscreensaver.service\fP into
-the directory \fI~/.config/systemd/user/\fP.  Create that directory first
-if it doesn't exist.  Then enable it with:
+If the file \fI/usr/lib/systemd/user/xscreensaver.service\fP does not
+already exist, copy the file \fI/usr/share/xscreensaver/xscreensaver.service\fP
+to there or to \fI~/.config/systemd/user/\fP.
+
+Then enable it with:
 .nf
 .sp
        systemctl \-\-user enable xscreensaver
@@ -288,7 +290,7 @@ in, and kill it as soon as someone does log in.  (The user will then
 be responsible for starting XScreenSaver on their own, if they want.)
 
 If that doesn't work, you can edit the config file directly. Edit
-\fI/etc/X11/gdm/gdm.conf\fP to include:
+\fI/etc/X11/gdm/gdm.conf\fP or maybe \fI/etc/gdm3/custom.conf\fP to include:
 .nf
 .sp
        Greeter=/usr/bin/gdmlogin
@@ -359,8 +361,8 @@ Wayland and use the X Window System like in the "good old days".
 The login screen should have a gear-icon menu that lets you change the session
 type from "GNOME" (the Wayland session) to "GNOME on Xorg" (the X11 session).
 
-Alternately, edit \fI/etc/gdm/custom.conf\fP and make sure it includes this
-line:
+Alternately, edit \fI/etc/X11/gdm/gdm.conf\fP or maybe
+\fI/etc/gdm3/custom.conf\fP to include:
 .nf
 .sp
        WaylandEnable=false
diff --git a/driver/xscreensaver.pam b/driver/xscreensaver.pam
new file mode 100644 (file)
index 0000000..acae83c
--- /dev/null
@@ -0,0 +1,14 @@
+#%PAM-1.0
+# Configuration used by XScreenSaver to unlock the screen.
+
+# Use the same mechanisms and restrictions as for logging in on the console:
+
+auth     include login
+account  include login
+password include login
+session  include login
+
+# Do this to unlock GNOME Keyring and KDE Wallet when the screen unlocks:
+
+# auth   optional pam_gnome_keyring.so 
+# auth   optional pam_kwallet5.so
diff --git a/driver/xscreensaver.pam.in b/driver/xscreensaver.pam.in
deleted file mode 100644 (file)
index 0065839..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#%PAM-1.0
-
-# Debian 12:
-# auth       requisite pam_nologin.so
-# auth       optional  pam_group.so
-# @include common-auth
-# @include common-account
-# @include common-session
-# @include common-password
-
-# Ubuntu 18:
-# @include common-auth
-# @include common-account
-
-# AL2023:
-# auth       substack  system-auth
-# auth       include   postlogin
-
-# Fedora Core 5:
-# auth       include   system-auth
-
-# Distant past:
-# auth       required  /lib/security/pam_pwdb.so shadow nullok
-
-# Account validation
-@COMMENT_PAM_CHECK_ACCOUNT@account include system-auth
index efad06c4ef36e36dcedca5606041cf2ff0dff85c..15f866adfdc669998d395a8a348eb206fd43c75c 100644 (file)
@@ -12,6 +12,9 @@ Conflicts=org.gnome.ScreenSaver org.cinnamon.ScreenSaver org.mate.ScreenSaver or
 ExecStart=/usr/bin/xscreensaver
 Restart=on-failure
 OOMScoreAdjust=-1000
+Type=dbus
+BusName=org.jwz.XScreenSaver
+NotifyAccess=all
 
 [Install]
 Alias=org.jwz.xscreensaver.service
index b0825b1c381534b52dab98c9859205a6028bb0a8..be0abb3118eafd3ce0aa4007a6064490bab765fa 100644 (file)
@@ -1,4 +1,4 @@
-# hacks/Makefile.in --- xscreensaver, Copyright © 1997-2025 Jamie Zawinski.
+# hacks/Makefile.in --- xscreensaver, Copyright © 1997-2026 Jamie Zawinski.
 # the `../configure' script generates `hacks/Makefile' from this file.
 
 @SET_MAKE@
@@ -288,45 +288,45 @@ install-strip:
 
 # the hacks, in $HACKDIR
 install-program:: $(EXES)
-       @if [ ! -d $(DESTDIR)$(HACKDIR) ]; then                         \
-         $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ;                        \
+       @dir="$(DESTDIR)$(HACKDIR)" ;                                   \
+        if [ ! -d $$dir ]; then                                        \
+         echo $(INSTALL_DIRS) "$$dir" ;                                \
+              $(INSTALL_DIRS) "$$dir" ;                                \
         fi ;                                                           \
-       for program in $(EXES); do                                      \
-         echo $(INSTALL_PROGRAM) $$program                             \
-           $(DESTDIR)$(HACKDIR)/$$program ;                            \
-         $(INSTALL_PROGRAM) $$program                                  \
-           $(DESTDIR)$(HACKDIR)/$$program ;                            \
-       done
+        for program in $(EXES); do                                     \
+          echo $(INSTALL_PROGRAM) "$$program" "$$dir/$$program" ;      \
+               $(INSTALL_PROGRAM) "$$program" "$$dir/$$program" ;      \
+        done
 
 install-scripts: $(SCRIPTS) munge-scripts
-       @if [ ! -d $(DESTDIR)$(HACKDIR) ]; then                         \
-         $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ;                        \
+       @dir="$(DESTDIR)$(HACKDIR)" ;                                   \
+        if [ ! -d $$dir ]; then                                        \
+         echo $(INSTALL_DIRS) "$$dir" ;                                \
+              $(INSTALL_DIRS) "$$dir" ;                                \
         fi ;                                                           \
-       for program in $(SCRIPTS); do                                   \
-         if [ -r $$program ] ; then                                    \
-           p=$$program ;                                               \
-         else                                                          \
-           p=$(srcdir)/$$program ;                                     \
-         fi ;                                                          \
-         echo $(INSTALL_SCRIPT) $$p                                    \
-           $(DESTDIR)$(HACKDIR)/$$program ;                            \
-         $(INSTALL_SCRIPT) $$p                                         \
-           $(DESTDIR)$(HACKDIR)/$$program ;                            \
-       done
+        for program in $(SCRIPTS); do                                  \
+          if [ -r "$$program" ] ; then                                 \
+            p="$$program" ;                                            \
+          else                                                         \
+            p="$(srcdir)/$$program" ;                                  \
+          fi ;                                                         \
+          echo $(INSTALL_SCRIPT) "$$p" "$$dir/$$program" ;             \
+               $(INSTALL_SCRIPT) "$$p" "$$dir/$$program" ;             \
+        done
 
 munge-scripts: $(SCRIPTS)
-       @tmp=/tmp/mf.$$$$ ;                                             \
+       @tmp="/tmp/mf.$$$$" ;                                           \
        perl="$(PERL)" ;                                                \
-       rm -f $$tmp ;                                                   \
+       rm -f "$$tmp" ;                                                 \
        for program in $(SCRIPTS); do                                   \
          sed "s@^\(#!\)\(/[^ ]*/perl[^ ]*\)\(.*\)\$$@\1$$perl\3@"      \
-             < $(srcdir)/$$program > $$tmp ;                           \
-         if ! cmp -s $(srcdir)/$$program $$tmp ; then                  \
+             < "$(srcdir)/$$program" > "$$tmp" ;                       \
+         if ! cmp -s "$(srcdir)/$$program" "$$tmp" ; then              \
            echo "$$program: setting interpreter to $$perl" >&2 ;       \
-           cat $$tmp > ./$$program ;                                   \
+           cat "$$tmp" > "./$$program" ;                               \
          fi ;                                                          \
        done ;                                                          \
-       rm -f $$tmp
+       rm -f "$$tmp"
 
 # When installing man pages, we install "foo.man" as "foo.N" and update
 # the .TH line in the installed file with one like
@@ -337,30 +337,31 @@ munge-scripts: $(SCRIPTS)
 #
 install-man: $(MEN)
        @men="$(MEN)" ;                                                 \
-       U=$(UTILS_SRC)/version.h ;                                      \
+       U="$(UTILS_SRC)/version.h" ;                                    \
        V=`sed -n 's/.*xscreensaver \([0-9]\.[^)]*)\).*/\1/p' < $$U |   \
            head -1`;                                                   \
-       T=/tmp/xs$$$$.$(mansuffix) ;                                    \
+       T="/tmp/xs$$$$.$(mansuffix)" ;                                  \
        TH=".TH XScreenSaver $(mansuffix) \"$$V\" \"X Version 11\"" ;   \
+       dir="$(DESTDIR)$(manNdir)" ;                                    \
+                                                                       \
        echo "installing man pages: $$TH" ;                             \
                                                                        \
-       if [ ! -d $(DESTDIR)$(manNdir) ]; then                          \
-         $(INSTALL_DIRS) $(DESTDIR)$(manNdir) ;                        \
+       if [ ! -d "$$dir" ]; then                                       \
+         echo $(INSTALL_DIRS) "$$dir" ;                                \
+              $(INSTALL_DIRS) "$$dir" ;                                \
         fi ;                                                           \
                                                                        \
        for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         manbase=`echo $$man | sed 's/\.man$$//'` ;    \
+         instname="`echo "$$man" | sed 's/\.man$$/\.$(mansuffix)/'`" ; \
+         manbase="`echo "$$man" | sed 's/\.man$$//'`" ;                \
          TH=".TH $$manbase $(mansuffix) \"$$V\" \"X Version 11\" \"XScreenSaver manual\"" ;    \
          sed -e "s/^\.TH.*/$$TH/"                                      \
              -e 's@(MANSUFFIX)@($(mansuffix))@g'                       \
-           < $(srcdir)/$$man > $$T ;                                   \
-         echo $(INSTALL_DATA) $(srcdir)/$$man                          \
-          $(DESTDIR)$(manNdir)/$$instname ;                            \
-         $(INSTALL_DATA) $$T                                           \
-           $(DESTDIR)$(manNdir)/$$instname ;                           \
+           < "$(srcdir)/$$man" > "$$T" ;                               \
+         echo $(INSTALL_DATA) "$(srcdir)/$$man" "$$dir/$$instname" ;   \
+              $(INSTALL_DATA) "$$T"             "$$dir/$$instname" ;   \
        done ;                                                          \
-       rm -f $$T
+       rm -f "$$T"
 
 install-xml:
        @dest=$(DESTDIR)$(HACK_CONF_DIR) ;                              \
@@ -369,38 +370,38 @@ install-xml:
         fi ;                                                           \
         src=$(srcdir)/config ;                                         \
         for file in $(EXES) $(SCRIPTS) ; do                            \
-          if [ -f $$src/$$file.xml ]; then                             \
-            echo $(INSTALL_DATA) $$src/$$file.xml $$dest/$$file.xml ;  \
-                 $(INSTALL_DATA) $$src/$$file.xml $$dest/$$file.xml ;  \
+          if [ -f "$$src/$$file.xml" ]; then                           \
+            echo $(INSTALL_DATA) "$$src/$$file.xml" "$$dest/$$file.xml" ;\
+                 $(INSTALL_DATA) "$$src/$$file.xml" "$$dest/$$file.xml" ;\
           fi ;                                                         \
        done
 
 uninstall-program:
        @for program in $(EXES) $(RETIRED_EXES) $(SCRIPTS); do          \
-         echo rm -f $(DESTDIR)$(HACKDIR)/$$program ;                   \
-         rm -f $(DESTDIR)$(HACKDIR)/$$program ;                        \
+         echo rm -f "$(DESTDIR)$(HACKDIR)/$$program" ;                 \
+              rm -f "$(DESTDIR)$(HACKDIR)/$$program" ;                 \
        done
 
 uninstall-man:
        @men="$(MEN) $(RETIRED_MEN)" ;                                  \
        for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         echo rm -f $(DESTDIR)$(manNdir)/$$instname* ;                 \
-         rm -f $(DESTDIR)$(manNdir)/$$instname* ;                      \
+         instname=`echo "$$man" | sed 's/\.man$$/\.$(mansuffix)/'` ;   \
+         echo rm -f "$(DESTDIR)$(manNdir)/$$instname"* ;               \
+              rm -f "$(DESTDIR)$(manNdir)/$$instname"* ;               \
        done
 
 uninstall-xml:
        @dest=$(DESTDIR)$(HACK_CONF_DIR) ;                              \
         for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) ; do            \
-            echo rm -f $$dest/$$file.xml ;                             \
-                 rm -f $$dest/$$file.xml ;                             \
+            echo rm -f "$$dest/$$file.xml" ;                           \
+                 rm -f "$$dest/$$file.xml" ;                           \
        done
 
 clean::
-       -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) m6502.h testx11
+       -rm -f ./*.o a.out core $(EXES) $(RETIRED_EXES) m6502.h testx11
 
 distclean: clean
-       -rm -f Makefile TAGS *~ "#"*
+       -rm -f Makefile TAGS ./*~ "#"*
 
 # Adds all current dependencies to Makefile
 depend:
@@ -414,7 +415,7 @@ depend:
 # to include only dependencies on files which are themselves a part of this
 # package.
 distdepend:: m6502.h
-       @echo updating dependencies in `pwd`/Makefile.in... ;                             \
+       @echo "updating dependencies in `pwd`/Makefile.in..." ;                           \
        $(DEPEND) -w 0 -f -                                                               \
        -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) --               \
        $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) $(FFMPEG_CFLAGS) -- \
@@ -445,8 +446,8 @@ list_tarfiles:
 check_men:
        @badmen="" ;                                                    \
         for exe in $(EXES) $(SCRIPTS); do                              \
-          if ! [ -f $(srcdir)/$$exe.man                                \
-                 -o "$$exe" = webcollage-helper ]; then                \
+          if ! [ -f "$(srcdir)/$$exe.man" ] &&                         \
+             ! [ "$$exe" = webcollage-helper ]; then                   \
             badmen="$$badmen $$exe" ;                                  \
           fi ;                                                         \
         done ;                                                         \
index 58d721709c16afe31d61cb2e4e80a2c92d379de2..349b0847f6120e9d96b2e318e3bc05691b96149c 100755 (executable)
@@ -21,7 +21,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.49 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.51 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 my $debug_p = 0;
@@ -59,6 +59,27 @@ $analogtv_default_opts .= $thread_default_opts;
 
 
 
+sub shaders_for_saver($) {
+  my ($saver) = @_;
+
+  my @shaders = ();
+  my $ext = 'glsl';
+  my @dirs = ('glx/glsl', '../hacks/glx/glsl');
+
+  $saver = lc($saver);
+  for (my $i = 0; $i < 6; $i++) {
+    my $suf = ($i == 0 ? 'c' : $i-1);
+    my $f1 = ($i == 1 ? "$saver.$ext" : undef);
+    my $f2 = "$saver-$suf.$ext";
+    foreach my $d (@dirs) {
+      if ($f1 && -f "$d/$f1") { push @shaders, "$d/$f1"; last; }
+      elsif     (-f "$d/$f2") { push @shaders, "$d/$f2"; last; }
+    }
+  }
+  return @shaders;
+}
+
+
 # Returns two tables:
 # - A table of the default resource values.
 # - A table of "--switch" => "resource: value", or "--switch" => "resource: %"
@@ -74,12 +95,16 @@ sub parse_src($) {
   $file = 'polyhedra-gl.c' if ($file eq 'polyhedra.c');
   $file = 'companion.c' if ($file eq 'companioncube.c');
 
+  my @shaders = shaders_for_saver ($saver);
+  $file = 'xshadertoy.c' if (@shaders);
+
   my $ofile = $file;
   $file = "glx/$ofile"          unless (-f $file);
   $file = "../hacks/$ofile"     unless (-f $file);
   $file = "../hacks/glx/$ofile" unless (-f $file);
   my $body = '';
   open (my $in, '<:utf8', $file) || error ("$ofile: $!");
+  local $/ = undef;  # read entire file
   while (<$in>) { $body .= $_; }
   close $in;
   $file =~ s@^.*/@@;
@@ -223,6 +248,7 @@ sub parse_xml($$$) {
   $file = "../hacks/$ofile" unless (-f $file);
   my $body = '';
   open (my $in, '<:utf8', $file) || error ("$ofile: $!");
+  local $/ = undef;  # read entire file
   while (<$in>) { $body .= $_; }
   close $in;
   $file =~ s@^.*/@@;
@@ -448,6 +474,7 @@ sub check_config($$) {
   # kludge
   return 0 if ($saver =~ m/(-helper)$/);
   return 0 if ($saver =~ m/(xscreensaver-)/);
+  return 0 if ($saver =~ m/xshadertoy$/);
 
   my ($src_opts, $switchmap) = parse_src ($saver);
   my ($saver_title, $gl_p, $xml_opts, $widgets) =
@@ -589,33 +616,6 @@ sub write_file_if_changed($$;$) {
 }
 
 
-# Read the template file and splice in the @KEYWORDS@ in the hash.
-#
-sub read_template($$) {
-  my ($file, $subs) = @_;
-  my $body = '';
-  open (my $in, '<:utf8', $file) || error ("$file: $!");
-  while (<$in>) { $body .= $_; }
-  close $in;
-
-  $body =~ s@/\*.*?\*/@@gs;  # omit comments
-  $body =~ s@//.*$@@gm;
-
-  foreach my $key (keys %$subs) {
-    my $val = $subs->{$key};
-    $body =~ s/@\Q$key\E@/$val/gs;
-  }
-
-  if ($body =~ m/(@[-_A-Z\d]+@)/s) {
-    error ("$file: unmatched: $1 [$body]");
-  }
-
-  $body =~ s/[ \t]+$//gm;
-  $body =~ s/(\n\n)\n+/$1/gs;
-  return $body;
-}
-
-
 # This is duplicated in OSX/update-info-plist.pl
 #
 sub munge_blurb($$$$) {
@@ -711,6 +711,8 @@ sub build_android(@) {
   my $xml_dir     = "$project_dir/res/xml";
   my $values_dir  = "$project_dir/res/values";
   my $java_dir    = "$project_dir/src/org/jwz/xscreensaver/gen";
+  my $asset_dir   = "$project_dir/assets";
+  my $shader_dir  = "$asset_dir/glsl";
   my $gen_dir     = "gen";
 
   my $xml_header = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
@@ -731,6 +733,7 @@ sub build_android(@) {
     my $file = "../utils/version.h";
     my $body = '';
     open (my $in, '<:utf8', $file) || error ("$file: $!");
+    local $/ = undef;  # read entire file
     while (<$in>) { $body .= $_; }
     close $in;
     ($vers) = ($body =~ m@ (\d+\.[0-9a-z]+) @s);
@@ -741,7 +744,10 @@ sub build_android(@) {
   foreach my $saver (@savers) {
     next if ($saver =~ m/(-helper)$/);
 
-    my ($src_opts, $switchmap) = parse_src ($saver);
+    my @shaders = shaders_for_saver ($saver);
+    my $saver2 = @shaders ? 'xshadertoy' : $saver;
+
+    my ($src_opts, $switchmap) = parse_src ($saver2);
     my ($saver_title, $gl_p, $xml_opts, $widgets) =
       parse_xml ($saver, $switchmap, $src_opts);
 
@@ -766,6 +772,27 @@ sub build_android(@) {
       $saver_class =~ s/^(.)/\U$1/s;
     }
 
+    # Write all referenced shaders to "xscreensaver/assets/glsl/".
+    foreach my $file (@shaders) {
+      my $body = '';
+      open (my $in, '<:utf8', $file) || error ("$file: $!");
+      local $/ = undef;  # read entire file
+      while (<$in>) { $body .= $_; }
+      close $in;
+
+      # Omit comments in shaders.
+      $body =~ s@//[^\n]*@@gs;
+      $body =~ s@/\*.*?\*/@@gs;
+      $body =~ s/^[ \t]+|[ \t]+$//gm;
+      $body =~ s/\n\n+/\n/gs;
+      $body =~ s/^\s+|\s+$//gs;
+      $body .= "\n";
+
+      my $fn = $file;
+      $fn =~ s@^.*/@@gs;
+      $write_files{"$shader_dir/$fn"} = $body;
+    }
+
     my $settings = '';
 
     my $localize0 = sub($$) {
@@ -1038,8 +1065,8 @@ sub build_android(@) {
     $fntable_h2 .= ",\n  " if $fntable_h2 ne '';
     $fntable_h3 .= ",\n  " if $fntable_h3 ne '';
 
-    $fntable_h2 .= "${saver}_xscreensaver_function_table";
-    $fntable_h3 .= "{\"${saver}\", &${saver}_xscreensaver_function_table}";
+    $fntable_h2 .= "${saver2}_xscreensaver_function_table";
+    $fntable_h3 .= "{\"${saver}\", &${saver2}_xscreensaver_function_table}";
   }
 
   $arrays =~ s/^/  /gm;
@@ -1228,7 +1255,7 @@ sub build_android(@) {
   # if a hack is removed from $ANDROID_HACKS in android/Makefile but
   # the old XML files remain behind, the build blows up.
   #
-  foreach my $dd ($xml_dir, $gen_dir, $java_dir) {
+  foreach my $dd ($xml_dir, $gen_dir, $java_dir, $shader_dir) {
     opendir (my $dirp, $dd) || error ("$dd: $!");
     my @files = readdir ($dirp);
     closedir $dirp;
@@ -1237,7 +1264,8 @@ sub build_android(@) {
       $f = "$dd/$f";
       next if (defined ($write_files{$f}));
       if ($f =~ m/_(settings|wallpaper|dream)\.xml$/s ||
-          $f =~ m/(Settings|Daydream)\.java$/s) {
+          $f =~ m/(Settings|Daydream)\.java$/s ||
+          $f =~ m/\.glsl$/s) {
         print STDERR "$progname: rm $f\n";
         unlink ($f) unless ($debug_p);
       } else {
index b6591e9381c4536d9d7883f3a6a47a2801c5152f..906029c21cd4e785b991363d20e2c15f46250e8f 100644 (file)
@@ -4,8 +4,8 @@
             a screen saver and locker for the X window system
                             by Jamie Zawinski
 
-                              version 6.13
-                               02-Dec-2025
+                              version 6.14
+                               15-Jan-2026
 
                      https://www.jwz.org/xscreensaver/
 
diff --git a/hacks/config/alienbeacon.xml b/hacks/config/alienbeacon.xml
new file mode 100644 (file)
index 0000000..b899a0b
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="alienbeacon" _label="Alien Beacon" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=na3do17whcw"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Our investigation of the signal from the planet's surface brought us to what
+seems to be an alien beacon. Based on the rock formation around the beacon, it
+was probably left here millions of years ago.
+
+https://www.shadertoy.com/view/ld2SzK
+
+Written by Otavio Good; 2014.
+  </_description>
+</screensaver>
diff --git a/hacks/config/batteredplanet.xml b/hacks/config/batteredplanet.xml
new file mode 100644 (file)
index 0000000..3190bab
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="batteredplanet" _label="Battered Planet" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=FIj2oOuIXvw"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+An alien planet full of craters, with other celestial objects in the sky.
+
+https://www.shadertoy.com/view/wsjBD3
+
+Written by Otavio Good; 2020.
+  </_description>
+</screensaver>
diff --git a/hacks/config/elementalring.xml b/hacks/config/elementalring.xml
new file mode 100644 (file)
index 0000000..879fe67
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="elementalring" _label="Elemental Ring" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=gmgIuvYGf0Y"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+A rotating ring knots and un-knots itself.
+
+https://www.shadertoy.com/view/MsVXDt
+
+Written by Otavio Good; 2016.
+  </_description>
+</screensaver>
diff --git a/hacks/config/fluxcore.xml b/hacks/config/fluxcore.xml
new file mode 100644 (file)
index 0000000..397df6e
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="fluxcore" _label="Flux Core" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=LHsx3JGB2is"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Long range space-based energy transmission requires a flux core to amplify
+and concentrate energy.
+
+https://www.shadertoy.com/view/ltlSWf
+
+Written by Otavio Good; 2015.
+  </_description>
+</screensaver>
diff --git a/hacks/config/gimbalharmonics.xml b/hacks/config/gimbalharmonics.xml
new file mode 100644 (file)
index 0000000..01477aa
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="gimbalharmonics" _label="Gimbal Harmonics" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=wMl2XUMlcLk"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Disc-based visualization of different frequencies next to each other.
+
+https://www.shadertoy.com/view/llS3zd
+
+Written by Otavio Good; 2015.
+  </_description>
+</screensaver>
index b061b03184562ea407cececca0286108adc5d1c7..9e783d2971d66b5201134cc6bb4fb464fc5b4de4 100644 (file)
  
     <number id="duration" type="slider" arg="--duration %"
             _label="Time until loading a new image"
-            _low-label="10 seconds" _high-label="5 minutes"
-            low="10" high="300" default="30"/>
+            _low-label="1 second" _high-label="5 minutes"
+            low="1" high="300" default="30"/>
 
     <number id="pan" type="slider" arg="--transition %"
             _label="Image loading animation duration"
-            _low-label="1 second" _high-label="30 seconds"
-            low="1" high="30" default="3"/>
+            _low-label="None" _high-label="30 seconds"
+            low="0" high="30" default="3"/>
    </vgroup>
    <vgroup>
     <number id="zoom" type="slider" arg="--zoom %"
@@ -31,8 +31,8 @@
  
     <number id="pan" type="slider" arg="--pan %"
             _label="Pan / zoom duration"
-            _low-label="1 second" _high-label="30 seconds"
-            low="1" high="30" default="6"/>
+            _low-label="None" _high-label="30 seconds"
+            low="0" high="30" default="6"/>
  
     <number id="fade" type="slider" arg="--fade %"
             _label="Crossfade duration"
diff --git a/hacks/config/hexplasma.xml b/hacks/config/hexplasma.xml
new file mode 100644 (file)
index 0000000..7007f63
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="hexplasma" _label="Hex Plasma" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=KAYPUB3OXWM"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+A hexagon in a plasma field.
+
+https://www.shadertoy.com/view/WfS3Dd
+
+Written by Nemerix; 2025.
+  </_description>
+</screensaver>
diff --git a/hacks/config/logarithmiccircles.xml b/hacks/config/logarithmiccircles.xml
new file mode 100644 (file)
index 0000000..eaa9b42
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="logarithmiccircles" _label="Logarithmic Circles" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=8E1sgc_GISk"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Zooming black and white circles.
+
+https://www.shadertoy.com/view/mljcWR
+
+Written by mrange; 2023.
+  </_description>
+</screensaver>
diff --git a/hacks/config/neongravity.xml b/hacks/config/neongravity.xml
new file mode 100644 (file)
index 0000000..b23c282
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="neongravity" _label="Neon Gravity" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=YvK5pBph9UU"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+The stylish interior of a torus.
+
+https://www.shadertoy.com/view/43G3Wc
+
+Written by mrange; 2023.
+  </_description>
+</screensaver>
diff --git a/hacks/config/neontriangulator.xml b/hacks/config/neontriangulator.xml
new file mode 100644 (file)
index 0000000..94c01c2
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="neontriangulator" _label="Neon Triangulator" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=YJ1eYlQb5OA"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Neon triangles zoom.
+
+https://www.shadertoy.com/view/tXGGRD
+
+Written by mrange; 2021.
+  </_description>
+</screensaver>
diff --git a/hacks/config/protophore.xml b/hacks/config/protophore.xml
new file mode 100644 (file)
index 0000000..9dda77e
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="protophore" _label="Protophore" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=QKxrzPuyRsc"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+A reflective metal fractal.
+
+https://www.shadertoy.com/view/XljGDz
+
+Written by Otavio Good; 2015.
+  </_description>
+</screensaver>
diff --git a/hacks/config/selfreflect.xml b/hacks/config/selfreflect.xml
new file mode 100644 (file)
index 0000000..0f1c31f
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="selfreflect" _label="Self Reflect" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=ZVbtTLHJimQ"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Platonic solids with inner mirrors.
+
+https://www.shadertoy.com/view/XfyXRV
+
+Written by mrange; 2024.
+  </_description>
+</screensaver>
diff --git a/hacks/config/skyline.xml b/hacks/config/skyline.xml
new file mode 100644 (file)
index 0000000..e9201b3
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="skyline" _label="Skyline" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=sao3ZCm2vTY"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+A procedurally-generated cityscape.
+
+https://www.shadertoy.com/view/XtsSWs
+
+Written by Otavio Good; 2015.
+  </_description>
+</screensaver>
diff --git a/hacks/config/stardome.xml b/hacks/config/stardome.xml
new file mode 100644 (file)
index 0000000..3e8172b
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="stardome" _label="Star Dome" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=qPvuutuMQHo"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Stars and a galaxy under a dome on a moon.
+
+https://www.shadertoy.com/view/stBcW1
+
+Written by mrange; 2022.
+  </_description>
+</screensaver>
diff --git a/hacks/config/starnest.xml b/hacks/config/starnest.xml
new file mode 100644 (file)
index 0000000..4f378aa
--- /dev/null
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="starnest" _label="Star Nest" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=EcntiVDT6Fo"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+<!--
+  <hgroup>
+    <boolean id="automouse" _label="Auto-mouse"    arg-set="-\-automouse"/>
+    <number id="automousespeed" type="slider" arg="-\-automouse-speed %"
+            _label="Auto-mouse Speed" _low-label="Slow" _high-label="Fast"
+            low="0.01" high="10.0" default="1.0"
+            convert="ratio"/>
+  </hgroup>
+-->
+
+  <xscreensaver-updater />
+
+  <_description>
+A star field via 3D kaliset fractal and volumetric rendering.
+
+https://www.shadertoy.com/view/XlfGRj
+
+Written by Pablo Roman Andrioli; 2013.
+  </_description>
+</screensaver>
diff --git a/hacks/config/stripeytorus.xml b/hacks/config/stripeytorus.xml
new file mode 100644 (file)
index 0000000..9ef7607
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="stripeytorus" _label="Stripey Torus" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=rVFg7F_6478"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+The stylish interior of a torus.
+
+https://www.shadertoy.com/view/fd33zn
+
+Written by mrange; 2021.
+  </_description>
+</screensaver>
diff --git a/hacks/config/synthwavecity.xml b/hacks/config/synthwavecity.xml
new file mode 100644 (file)
index 0000000..e4da35a
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<screensaver name="synthwavecity" _label="Synthwave City" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=V0oWOW6pjgA"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Let the neon wash over you.
+
+https://www.shadertoy.com/view/7lKyDD
+
+Written by Jan Mróz and 3w36zj6; 2019.
+  </_description>
+</screensaver>
diff --git a/hacks/config/topologica.xml b/hacks/config/topologica.xml
new file mode 100644 (file)
index 0000000..5858391
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="topologica" _label="Topologica" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=wBJD2NZTzgI"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+Pulsing lines of light.
+
+https://www.shadertoy.com/view/4djXzz
+
+Written by Otavio Good; 2014.
+  </_description>
+</screensaver>
diff --git a/hacks/config/truchetzoom.xml b/hacks/config/truchetzoom.xml
new file mode 100644 (file)
index 0000000..fc173bd
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<screensaver name="truchetzoom" _label="Truchet Zoom" gl="yes">
+
+  <command arg="--root"/>
+
+  <video href="https://www.youtube.com/watch?v=ts6A_H7R64w"/>
+
+  <number id="delay" type="slider" arg="--delay %"
+          _label="Frame rate" _low-label="Low" _high-label="High"
+          low="0" high="100000" default="20000"
+          convert="invert"/>
+    
+  <number id="speed" type="slider" arg="--speed %"
+          _label="Speed" _low-label="Slow" _high-label="Fast"
+          low="0.01" high="10.0" default="1.0"
+          convert="ratio"/>
+    
+  <number id="scale" type="slider" arg="--scale %"
+          _label="Resolution" _low-label="Low" _high-label="Full"
+          low="0.1" high="1.0" default="1.0" />
+    
+  <boolean id="showfps" _label="Show frame rate" arg-set="--fps"/>
+
+  <xscreensaver-updater />
+
+  <_description>
+A looping, distorting truchet chain with scanlines.
+
+https://www.shadertoy.com/view/4cBcDy
+
+Written by mrange; 2024.
+  </_description>
+</screensaver>
index e79079b4537d9e6febeabe7e379497f135d381c6..d39f662cb20d8eb6b09497a4f1fb9b71cd54d2f2 100644 (file)
@@ -397,26 +397,6 @@ flame_draw (Display *dpy, Window window, void *closure)
   return this_delay;
 }
 
-
-#if defined(__hpux) && defined(PLOSS)
-/* I don't understand why this is necessary, but I'm told that this program
-   does nothing at all on HP-sUX without it.
-
-   I'm further told that HPUX 11.0 doesn't define PLOSS, and works ok without
-   this section.  Go figure.
- */
-#undef random
-#undef srandom
-#include <math.h>
-int matherr(x)
-   register struct exception *x;
-{
-  if (x->type == PLOSS) return 1;
-  else return 0;
-}
-#endif /* __hpux */
-
-
 \f
 static const char *flame_defaults [] = {
   ".background:        black",
index 2ba4b90f75308060e8126528dce5b184e9a0c302..593e4478f9a7b22d9a8f6229f3a13cfe6854d13d 100644 (file)
@@ -29,6 +29,9 @@ INSTALL_DIRS  = @INSTALL_DIRS@
 #
 # "Gallant" was the original Solaris 2.x console font.  It is used by BSOD.
 # BSD licensed: https://ftp.netbsd.org/pub/NetBSD/NetBSD-current/src/sys/dev/wsfont/gallant12x22.h
+# (See also https://github.com/Prince213/gallant and
+# https://github.com/Prince213/gallant/blob/push-zyzpprmmslrt/gallant.ttf
+# for a full Unicode recreation, also BSD licensed, but not included here.)
 #
 # "Luxi Mono" was the Red Hat console font; it is very similar to "Gallant".
 # Also used by BSOD.
@@ -55,7 +58,7 @@ default: all
 all:
 clean:
 distclean:: clean
-       -rm -f Makefile TAGS *~ "#"*
+       -rm -f Makefile TAGS ./*~ "#"*
 
 list_tarfiles:
        @find $(TARFILES) -type f -print | sort
@@ -71,8 +74,8 @@ install-fonts:
                  $(INSTALL_DIRS) "$$dest" ;                            \
           fi ;                                                         \
           for f in $(FONTS) ; do                                       \
-            echo $(INSTALL_DATA) $(srcdir)/$$f $$dest/$$f ;            \
-                 $(INSTALL_DATA) $(srcdir)/$$f $$dest/$$f ;            \
+            echo $(INSTALL_DATA) "$(srcdir)/$$f" "$$dest/$$f" ;        \
+                 $(INSTALL_DATA) "$(srcdir)/$$f" "$$dest/$$f" ;        \
           done ;                                                       \
         fi
 
@@ -81,10 +84,11 @@ uninstall-fonts:
        @if ! [ -z "$(FONT_DIR)" ]; then                                \
           dest="$(DESTDIR)$(FONT_DIR)" ;                               \
           for f in $(FONTS) ; do                                       \
-            echo $(RM) $$dest/$$f ;                                    \
-                 $(RM) $$dest/$$f ;                                    \
+            echo $(RM) "$$dest/$$f" ;                                  \
+                 $(RM) "$$dest/$$f" ;                                  \
           done ;                                                       \
-          rmdir "$(DESTDIR)$(FONT_DIR)" ;                              \
+          echo rmdir "$(DESTDIR)$(FONT_DIR)" ;                         \
+               rmdir "$(DESTDIR)$(FONT_DIR)" ;                         \
           exit 0 ;                                                     \
         fi
 
index 08e0f0711f860edbd5db6786a2befc50ba5de178..cfa76b560768fc281bd0760edd3ea448cfce29a0 100644 (file)
@@ -1,4 +1,4 @@
-# hacks/glx/Makefile.in --- xscreensaver, Copyright © 1999-2025 Jamie Zawinski.
+# hacks/glx/Makefile.in --- xscreensaver, Copyright © 1999-2026 Jamie Zawinski.
 # the `../../configure' script generates `hacks/glx/Makefile' from this file.
 
 @SET_MAKE@
@@ -88,7 +88,8 @@ UTILDIR_OBJS  = $(UTILS_BIN)/colors.o $(UTILS_BIN)/grabclient.o \
                  $(UTILS_BIN)/textclient.o $(UTILS_BIN)/async_netdb.o \
                  $(UTILS_BIN)/aligned_malloc.o $(UTILS_BIN)/thread_util.o \
                  $(UTILS_BIN)/spline.o $(UTILS_BIN)/pow2.o \
-                 $(UTILS_BIN)/font-retry.o $(UTILS_BIN)/easing.o
+                 $(UTILS_BIN)/font-retry.o $(UTILS_BIN)/easing.o \
+                 $(UTILS_BIN)/xftwrap.o
 JWXYZ_OBJS     = $(JWXYZ_BIN)/jwzgles.o
 HACKDIR_OBJS   = $(HACK_BIN)/screenhack.o $(HACK_BIN)/xlockmore.o \
                  $(HACK_BIN)/fps.o $(HACK_BIN)/ximage-loader.o \
@@ -150,7 +151,17 @@ SRCS               = xscreensaver-gl-visual.c normals.c erase-gl.c fps-gl.c \
                  skulloop.c kallisti.c kallisti_model.c highvoltage.c \
                  highvoltage_model.c hopffibration.c hopfanimations.c \
                  platonicfolding.c klondike.c klondike-game.c dumpsterfire.c \
-                 dumpster_model.c
+                 dumpster_model.c xshadertoy.c
+
+GLSL_SRCS      = glsl/alienbeacon.glsl glsl/batteredplanet.glsl \
+                 glsl/elementalring.glsl glsl/fluxcore.glsl \
+                 glsl/gimbalharmonics.glsl glsl/hexplasma.glsl \
+                 glsl/logarithmiccircles.glsl glsl/neongravity-0.glsl \
+                 glsl/neongravity-1.glsl glsl/neontriangulator.glsl \
+                 glsl/protophore.glsl glsl/selfreflect.glsl \
+                 glsl/skyline.glsl glsl/stardome.glsl glsl/starnest.glsl \
+                 glsl/stripeytorus.glsl glsl/synthwavecity.glsl \
+                 glsl/topologica.glsl glsl/truchetzoom.glsl
 
 SCRIPTS                = mapscroller.pl
 
@@ -208,7 +219,7 @@ OBJS                = xscreensaver-gl-visual.o normals.o erase-gl.o fps-gl.o \
                  teeth_model.o hextrail.o papercube.o cubocteversion.o \
                  skulloop.o kallisti.o kallisti_model.o highvoltage.o \
                  highvoltage_model.o platonicfolding.o klondike.o \
-                 klondike-game.o dumpsterfire.o 
+                 klondike-game.o dumpsterfire.o xshadertoy.o
 
 GL_EXES                = cage gears moebius pipes sproingies stairs superquadrics \
                  morph3d rubik atlantis lament bubble3d glplanet pulsar \
@@ -233,13 +244,17 @@ GL_EXES           = cage gears moebius pipes sproingies stairs superquadrics \
                  sphereeversion covid19 headroom beats mapscroller \
                  squirtorus nakagin chompytower hextrail papercube \
                  cubocteversion skulloop kallisti highvoltage hopffibration \
-                 platonicfolding klondike dumpsterfire
+                 platonicfolding klondike dumpsterfire xshadertoy
 GLE_EXES       = extrusion
+GLSL_EXES      = alienbeacon batteredplanet elementalring fluxcore \
+                 gimbalharmonics hexplasma logarithmiccircles neongravity \
+                 neontriangulator protophore selfreflect skyline stardome \
+                 starnest stripeytorus synthwavecity topologica truchetzoom
 SUID_EXES      = sonar
 SETCAP_EXES    = sonar
 GL_UTIL_EXES   = xscreensaver-gl-visual
 JWZGLES_OBJS   = @JWZGLES_OBJS@
-HACK_EXES_1    = @GL_EXES@ @GLE_EXES@
+HACK_EXES_1    = @GL_EXES@ @GLE_EXES@ $(GLSL_EXES)
 HACK_EXES      = $(HACK_EXES_1) @SUID_EXES@
 XSHM_OBJS      = $(UTILS_BIN)/xshm.o $(UTILS_BIN)/aligned_malloc.o
 DT             = $(UTILS_BIN)/doubletime.o
@@ -318,13 +333,21 @@ GL_MEN            = xscreensaver-gl-visual.man \
                  mapscroller.man squirtorus.man nakagin.man chompytower.man \
                  hextrail.man papercube.man cubocteversion.man skulloop.man \
                  kallisti.man highvoltage.man hopffibration.man \
-                 platonicfolding.man
+                 platonicfolding.man xshadertoy.man \
+                 alienbeacon.man batteredplanet.man elementalring.man \
+                 fluxcore.man gimbalharmonics.man hexplasma.man \
+                 logarithmiccircles.man neongravity.man neontriangulator.man \
+                 protophore.man selfreflect.man skyline.man stardome.man \
+                 starnest.man stripeytorus.man synthwavecity.man \
+                 topologica.man truchetzoom.man
 MEN            = @GL_MEN@
 RETIRED_MEN    = glforestfire.man
 EXTRAS         = README Makefile.in dxf2gl.pl vrml2gl.pl wfront2gl.pl \
-                 molecules.sh starwars.txt zalgo.txt *.dxf
+                 xshadertoy-download.pl xshadertoy-compile.pl \
+                 molecules.sh starwars.txt zalgo.txt *.dxf glsl/README
 
-TARFILES       = $(SRCS) $(HDRS) $(SCRIPTS) $(GL_MEN) $(RETIRED_MEN) $(EXTRAS)
+TARFILES       = $(SRCS) $(HDRS) $(SCRIPTS) $(GLSL_SRCS) $(GL_MEN) \
+                 $(RETIRED_MEN) $(EXTRAS)
 
 # Using $(MAKE) directly means the shell executes things even with "make -n"
 MAKE2 = $(MAKE)
@@ -343,13 +366,14 @@ install-strip:
 install-program:: $(EXES)
        @exes="$(HACK_EXES_1) @GL_UTIL_EXES@" ;                         \
         idir="$(DESTDIR)$(HACKDIR)" ;                                  \
-        if ( echo $$exes | grep -q . ); then                           \
-          if [ ! -d $$idir ]; then                                     \
-            $(INSTALL_DIRS) $$idir ;                                   \
+        if ( echo "$$exes" | grep -q . ); then                         \
+          if [ ! -d "$$idir" ]; then                                   \
+            echo $(INSTALL_DIRS) "$$idir" ;                            \
+                 $(INSTALL_DIRS) "$$idir" ;                            \
           fi ;                                                         \
           for program in $$exes; do                                    \
-            echo $(INSTALL_PROGRAM) $$program $$idir/$$program ;       \
-                 $(INSTALL_PROGRAM) $$program $$idir/$$program ;       \
+            echo $(INSTALL_PROGRAM) "$$program" "$$idir/$$program" ;   \
+                 $(INSTALL_PROGRAM) "$$program" "$$idir/$$program" ;   \
           done ;                                                       \
                                                                        \
           exes="$(SUID_EXES)" ;                                        \
@@ -359,12 +383,12 @@ install-program:: $(EXES)
             sinst="$(INSTALL_PROGRAM)" ;                               \
           fi ;                                                         \
           for program in $$exes; do                                    \
-            echo $$sinst $$program $$idir/$$program ;                  \
-            if   $$sinst $$program $$idir/$$program ; then             \
+            echo $$sinst "$$program" "$$idir/$$program" ;              \
+            if   $$sinst "$$program" "$$idir/$$program" ; then         \
                true ;                                                  \
-            elif [ @SETUID_HACKS@ = yes ]; then                        \
-              echo $(INSTALL_PROGRAM) $$program $$idir/$$program ;     \
-              if   $(INSTALL_PROGRAM) $$program $$idir/$$program ; then\
+            elif [ "@SETUID_HACKS@" = yes ]; then                      \
+              echo $(INSTALL_PROGRAM) "$$program" "$$idir/$$program" ; \
+              if   $(INSTALL_PROGRAM) "$$program" "$$idir/$$program" ; then\
                 echo "" ;                                              \
                 echo "WARNING: unable to install $$program setuid:"    \
                      "installed non-setuid instead." ;                 \
@@ -378,10 +402,10 @@ install-program:: $(EXES)
           done ;                                                       \
                                                                        \
           exes="$(SETCAP_EXES)" ;                                      \
-          if [ @SETCAP_HACKS@ = yes ]; then                            \
+          if [ "@SETCAP_HACKS@" = yes ]; then                          \
             for program in $$exes; do                                  \
-              echo $(PROG_SETCAP) $(SETCAP_FLAGS) $$idir/$$program ;   \
-              if   $(PROG_SETCAP) $(SETCAP_FLAGS) $$idir/$$program ; then \
+              echo $(PROG_SETCAP) $(SETCAP_FLAGS) "$$idir/$$program" ; \
+              if   $(PROG_SETCAP) $(SETCAP_FLAGS) "$$idir/$$program" ; then \
                 true ;                                                 \
               else                                                     \
                 echo "" ;                                              \
@@ -395,35 +419,35 @@ install-program:: $(EXES)
 
 install-scripts: $(SCRIPTS) munge-scripts
        @                                                               \
-       if ! ( echo $(HACK_EXES_1) | grep -q . ); then exit 0 ; fi ;    \
-       if [ ! -d $(DESTDIR)$(HACKDIR) ]; then                          \
-         $(INSTALL_DIRS) $(DESTDIR)$(HACKDIR) ;                        \
+       dir="$(DESTDIR)$(HACKDIR)" ;                                    \
+       if ! ( echo "$(HACK_EXES_1)" | grep -q . ); then exit 0 ; fi ;  \
+       if [ ! -d "$$dir" ]; then                                       \
+         echo $(INSTALL_DIRS) "$$dir" ;                                \
+              $(INSTALL_DIRS) "$$dir" ;                                \
         fi ;                                                           \
        for program in $(SCRIPTS); do                                   \
          if [ -r $$program ] ; then                                    \
-           p=$$program ;                                               \
+           p="$$program" ;                                             \
          else                                                          \
-           p=$(srcdir)/$$program ;                                     \
+           p="$(srcdir)/$$program" ;                                   \
          fi ;                                                          \
-         echo $(INSTALL_SCRIPT) $$p                                    \
-           $(DESTDIR)$(HACKDIR)/$$program ;                            \
-         $(INSTALL_SCRIPT) $$p                                         \
-           $(DESTDIR)$(HACKDIR)/$$program ;                            \
+         echo $(INSTALL_SCRIPT) "$$p" "$$dir/$$program" ;              \
+              $(INSTALL_SCRIPT) "$$p" "$$dir/$$program" ;              \
        done
 
 munge-scripts: $(SCRIPTS)
        @tmp=/tmp/mf.$$$$ ;                                             \
        perl="$(PERL)" ;                                                \
-       rm -f $$tmp ;                                                   \
+       rm -f "$$tmp" ;                                                 \
        for program in $(SCRIPTS); do                                   \
          sed "s@^\(#!\)\(/[^ ]*/perl[^ ]*\)\(.*\)\$$@\1$$perl\3@"      \
-             < $(srcdir)/$$program > $$tmp ;                           \
-         if ! cmp -s $(srcdir)/$$program $$tmp ; then                  \
+             < "$(srcdir)/$$program" > "$$tmp" ;                       \
+         if ! cmp -s "$(srcdir)/$$program" "$$tmp" ; then              \
            echo "$$program: setting interpreter to $$perl" >&2 ;       \
-           cat $$tmp > ./$$program ;                                   \
+           cat "$$tmp" > "./$$program" ;                               \
          fi ;                                                          \
        done ;                                                          \
-       rm -f $$tmp
+       rm -f "$$tmp"
 
 # When installing man pages, we install "foo.man" as "foo.N" and update
 # the .TH line in the installed file with one like
@@ -434,42 +458,43 @@ munge-scripts: $(SCRIPTS)
 #
 install-man: $(MEN)
        @men="$(MEN)" ;                                                 \
-       U=$(UTILS_SRC)/version.h ;                                      \
-       V=`sed -n 's/.*xscreensaver \([0-9]\.[^)]*)\).*/\1/p' < $$U` ;  \
-       T=/tmp/xs$$$$.$(mansuffix) ;                                    \
+       U="$(UTILS_SRC)/version.h" ;                                    \
+       V=`sed -n 's/.*xscreensaver \([0-9]\.[^)]*)\).*/\1/p' < $$U |   \
+           head -1`;                                                   \
+       T="/tmp/xs$$$$.$(mansuffix)" ;                                  \
        TH=".TH XScreenSaver $(mansuffix) \"$$V\" \"X Version 11\"" ;   \
+       dir="$(DESTDIR)$(manNdir)" ;                                    \
                                                                        \
-       if ! ( echo $(HACK_EXES_1) | grep -q . ); then exit 0 ; fi ;    \
+       if ! ( echo "$(HACK_EXES_1)" | grep -q . ); then exit 0 ; fi ;  \
        echo "installing man pages: $$TH" ;                             \
                                                                        \
-       if [ ! -d $(DESTDIR)$(manNdir) ]; then                          \
-         $(INSTALL_DIRS) $(DESTDIR)$(manNdir) ;                        \
+       if [ ! -d "$$dir" ]; then                                       \
+         echo $(INSTALL_DIRS) "$$dir" ;                                \
+              $(INSTALL_DIRS) "$$dir" ;                                \
         fi ;                                                           \
                                                                        \
        for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         manbase=`echo $$man | sed 's/\.man$$//'` ;    \
+         instname="`echo "$$man" | sed 's/\.man$$/\.$(mansuffix)/'`" ; \
+         manbase="`echo "$$man" | sed 's/\.man$$//'`" ;                \
          TH=".TH $$manbase $(mansuffix) \"$$V\" \"X Version 11\" \"XScreenSaver manual\"" ;   \
          sed -e "s/^\.TH.*/$$TH/"                                      \
              -e 's@(MANSUFFIX)@($(mansuffix))@g'                       \
-           < $(srcdir)/$$man > $$T ;                                   \
-         echo $(INSTALL_DATA) $(srcdir)/$$man                          \
-          $(DESTDIR)$(manNdir)/$$instname ;                            \
-         $(INSTALL_DATA) $$T                                           \
-           $(DESTDIR)$(manNdir)/$$instname ;                           \
+           < "$(srcdir)/$$man" > "$$T" ;                               \
+         echo $(INSTALL_DATA) "$(srcdir)/$$man" "$$dir/$$instname" ;   \
+              $(INSTALL_DATA) "$$T"             "$$dir/$$instname" ;   \
        done ;                                                          \
-       rm -f $$T
+       rm -f "$$T"
 
 install-xml:
-       @dest=$(DESTDIR)$(HACK_CONF_DIR) ;                              \
-        if [ ! -d $$dest ]; then                                       \
-          $(INSTALL_DIRS) $$dest ;                                     \
+       @dest="$(DESTDIR)$(HACK_CONF_DIR)" ;                            \
+        if [ ! -d "$$dest" ]; then                                     \
+          $(INSTALL_DIRS) "$$dest" ;                                   \
         fi ;                                                           \
-        src=$(srcdir)/../config ;                                      \
+        src="$(srcdir)/../config" ;                                    \
         for file in $(EXES) $(SCRIPTS) ; do                            \
-          if [ -f $$src/$$file.xml ]; then                             \
-            echo $(INSTALL_DATA) $$src/$$file.xml $$dest/$$file.xml ;  \
-                 $(INSTALL_DATA) $$src/$$file.xml $$dest/$$file.xml ;  \
+          if [ -f "$$src/$$file.xml" ]; then                           \
+            echo $(INSTALL_DATA) "$$src/$$file.xml" "$$dest/$$file.xml" ; \
+                 $(INSTALL_DATA) "$$src/$$file.xml" "$$dest/$$file.xml" ; \
           fi ;                                                         \
        done
 
@@ -478,34 +503,34 @@ uninstall-program::
        @exes="$(HACK_EXES) $(RETIRED_EXES) $(SCRIPTS) @GL_UTIL_EXES@" ;\
         idir="$(DESTDIR)$(HACKDIR)" ;                                  \
         for program in $$exes; do                                      \
-          echo rm -f $$idir/$$program ;                                \
-               rm -f $$idir/$$program ;                                \
+          echo rm -f "$$idir/$$program" ;                              \
+               rm -f "$$idir/$$program" ;                              \
         done
 
 # $HACKDIR/xscreensaver-gl-visual used to be $bindir/xscreensaver-gl-helper
 uninstall-program::
-       rm -f $(DESTDIR)$(bindir)/xscreensaver-gl-helper
+       rm -f "$(DESTDIR)$(bindir)/xscreensaver-gl-helper"
 
 uninstall-man:
        @men="$(MEN) $(RETIRED_MEN)" ;                                  \
        for man in $$men; do                                            \
-         instname=`echo $$man | sed 's/\.man$$/\.$(mansuffix)/'` ;     \
-         echo rm -f $(DESTDIR)$(manNdir)/$$instname* ;                 \
-              rm -f $(DESTDIR)$(manNdir)/$$instname* ;                 \
+         instname="`echo "$$man" | sed 's/\.man$$/\.$(mansuffix)/'`" ; \
+         echo rm -f "$(DESTDIR)$(manNdir)/$$instname"* ;               \
+              rm -f "$(DESTDIR)$(manNdir)/$$instname"* ;               \
        done
 
 uninstall-xml:
        @dest=$(DESTDIR)$(HACK_CONF_DIR) ;                              \
         for file in $(EXES) $(RETIRED_EXES) $(SCRIPTS) ; do            \
-            echo rm -f $$dest/$$file.xml ;                             \
-                 rm -f $$dest/$$file.xml ;                             \
+            echo rm -f "$$dest/$$file.xml" ;                           \
+                 rm -f "$$dest/$$file.xml" ;                           \
        done
 
 clean::
-       -rm -f *.o a.out core $(EXES) $(RETIRED_EXES) molecules.h
+       -rm -f ./*.o a.out core $(EXES) $(RETIRED_EXES) molecules.h
 
 distclean: clean
-       -rm -f Makefile TAGS *~ "#"*
+       -rm -f Makefile TAGS ./*~ "#"*
 
 # Adds all current dependencies to Makefile
 depend:
@@ -519,7 +544,7 @@ depend:
 # to include only dependencies on files which are themselves a part of this
 # package.
 distdepend:: molecules.h
-       @echo updating dependencies in `pwd`/Makefile.in... ;               \
+       @echo "updating dependencies in `pwd`/Makefile.in..." ;             \
        $(DEPEND) -w 0 -f -                                                 \
        -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \
        $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --    \
@@ -567,8 +592,9 @@ check_men:
           done ;                                                       \
         fi
 
+VX = @GL_UTIL_EXES@ @GL_EXES@ @GLE_EXES@ @SUID_EXES@ $(RETIRED_EXES)
 validate_xml:
-       @cd $(HACK_SRC) && $(PERL) check-configs.pl --force $(EXES) $(RETIRED_EXES)
+       @cd $(HACK_SRC) && $(PERL) check-configs.pl --force $(VX)
 
 distdepend:: check_men validate_xml
 
@@ -603,6 +629,7 @@ $(HACK_BIN)/screenhack.o:   $(HACK_SRC)/screenhack.c
 $(HACK_BIN)/xlockmore.o:       $(HACK_SRC)/xlockmore.c
 $(HACK_BIN)/fps.o:             $(HACK_SRC)/fps.c
 $(HACK_BIN)/ffmpeg-out.o:      $(HACK_SRC)/ffmpeg-out.c
+$(UTILS_BIN)/xftwrap.o:                $(UTILS_SRC)/xftwrap.c
 
 $(UTILDIR_OBJS):
        $(MAKE2CC) -C $(UTILS_BIN) $(@F)
@@ -702,8 +729,11 @@ LAMENTOBJS = gllist.o lament_model.o $(HACK_TRACK_OBJS) $(PNG) normals.o
 lament:                lament.o        $(LAMENTOBJS)
        $(CC_HACK) -o $@ $@.o   $(LAMENTOBJS) $(PNG_LIBS)
 
+
+DXF2GL = $(srcdir)/dxf2gl.pl
+
 lament_dxf::
-       ./dxf2gl.pl --smooth --layers lament.dxf lament_model.c
+       $(DXF2GL) --smooth --layers lament.dxf lament_model.c
 
 
 B3D_OBJS = b_sphere.o b_draw.o b_lockglue.o $(HACK_OBJS)
@@ -711,7 +741,7 @@ bubble3d:   bubble3d.o      $(B3D_OBJS)
        $(CC_HACK) -o $@ $@.o   $(B3D_OBJS) $(HACK_LIBS)
 
 timezones_dxf::
-       ./dxf2gl.pl --normalize --wireframe timezones.dxf timezones.c
+       $(DXF2GL) --normalize --wireframe timezones.dxf timezones.c
 
 PLANET_OBJS=sphere.o gllist.o timezones.o $(PNG) $(HACK_TRACK_OBJS)
 glplanet:      glplanet.o      $(PLANET_OBJS)
@@ -813,7 +843,7 @@ toaster_dxf::
          toast2.dxf \
        ; do \
          f2=`echo $$f | sed 's/dxf$$/c/'` ; \
-         ./dxf2gl.pl --normalize --smooth $$f $$f2 ; \
+         $(DXF2GL) --normalize --smooth $$f $$f2 ; \
        done ; \
 
 COW1=cow_face.o cow_hide.o cow_hoofs.o cow_horns.o cow_tail.o cow_udder.o
@@ -827,15 +857,15 @@ winduprobot:                      $(ROBO1) $(ROBO2)
        $(CC_HACK) -o $@        $(ROBO1) $(ROBO2) $(PNG_LIBS) $(TEXT_LIBS)
 
 winduprobot_dxf::
-       ./dxf2gl.pl --smooth --layers robot.dxf robot.c
-       ./dxf2gl.pl --wireframe robot-wireframe.dxf robot-wireframe.c
+       $(DXF2GL) --smooth --layers robot.dxf robot.c
+       $(DXF2GL) --wireframe robot-wireframe.dxf robot-wireframe.c
 
 CAM_OBJS=seccam.o gllist.o vigilance.o $(HACK_TRACK_OBJS)
 vigilance:                     $(CAM_OBJS)
        $(CC_HACK) -o $@        $(CAM_OBJS) $(HACK_LIBS)
 
 seccam_dxf::
-       ./dxf2gl.pl --smooth --layers seccam.dxf seccam.c
+       $(DXF2GL) --smooth --layers seccam.dxf seccam.c
 
 EASE = $(UTILS_BIN)/easing.o
 SLIDE_OBJS = $(HACK_GRAB_OBJS) $(EASE)
@@ -934,8 +964,10 @@ moebiusgears:      moebiusgears.o  $(GEARS_OBJS)
 boing:         boing.o         normals.o $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
-carousel:      carousel.o      $(EASE) $(HACK_TRACK_GRAB_OBJS)
-       $(CC_HACK) -o $@ $@.o   $(EASE) $(HACK_TRACK_GRAB_OBJS) $(HACK_LIBS)
+XFTWRAP = $(UTILS_BIN)/xftwrap.o
+CAROUSEL_OBJS = $(EASE) $(XFTWRAP) $(HACK_TRACK_GRAB_OBJS)
+carousel:      carousel.o      $(CAROUSEL_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(CAROUSEL_OBJS) $(HACK_LIBS)
 
 fliptext:      fliptext.o      $(TEXT) $(HACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(TEXT) $(HACK_OBJS) $(HACK_LIBS) $(TEXT_LIBS)
@@ -1000,7 +1032,7 @@ sonar-icmp.o: sonar-icmp.c
        $(CC) -c $(HACK_CFLAGS_BASE) $(THREAD_CFLAGS) $<
 sonar:         sonar.o         $(SONAR_OBJS)
        $(CC_HACK) -o $@ $@.o   $(THREAD_CFLAGS) $(SONAR_OBJS) $(LIBCAP_LIBS) $(THREAD_LIBS) $(HACK_LIBS)
-       @if [ "$$USER" = jwz ]; then \
+       @if [ "$$USER" = jwz -a -z "$$RPM_PACKAGE_NAME" ]; then \
          set -x ; sudo chown root $@ ; sudo chmod u+s $@ ; \
        fi
 
@@ -1008,7 +1040,7 @@ JIGSAW_OBJS=normals.o $(UTILS_BIN)/spline.o $(HACK_TRACK_GRAB_OBJS)
 jigsaw:                jigsaw.o        $(JIGSAW_OBJS)
        $(CC_HACK) -o $@ $@.o   $(JIGSAW_OBJS) $(HACK_LIBS)
 
-PHOTOPILE_OBJS=dropshadow.o  $(HACK_GRAB_OBJS)
+PHOTOPILE_OBJS=dropshadow.o $(XFTWRAP) $(HACK_GRAB_OBJS)
 photopile:     photopile.o     $(PHOTOPILE_OBJS)
        $(CC_HACK) -o $@ $@.o   $(PHOTOPILE_OBJS) $(HACK_LIBS)
 
@@ -1050,7 +1082,7 @@ cityflow: cityflow.o      $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
 splitflap_dxf::
-       ./dxf2gl.pl --normalize --smooth --layers splitflap.dxf splitflap_obj.c
+       $(DXF2GL) --normalize --smooth --layers splitflap.dxf splitflap_obj.c
 
 FLAP_OBJS=splitflap_obj.o gllist.o splitflap.o $(TEXT) $(HACK_TRACK_OBJS)
 splitflap:                     $(FLAP_OBJS)
@@ -1089,7 +1121,7 @@ esper:    esper.o                 $(HACK_GRAB_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_GRAB_OBJS) $(HACK_LIBS)
 
 ships_dxf::
-       ./dxf2gl.pl --normalize --layers ships.dxf ships.c
+       $(DXF2GL) --normalize --layers ships.dxf ships.c
 
 DAZ_OBJS=ships.o gllist.o $(HACK_TRACK_OBJS)
 razzledazzle:  razzledazzle.o  $(DAZ_OBJS)
@@ -1109,7 +1141,7 @@ handsy:   handsy.o                 $(HANDSY_OBJS)
        $(CC_HACK) -o $@ $@.o    $(HANDSY_OBJS) $(HACK_LIBS)
 
 handsy_dxf::
-       ./dxf2gl.pl --smooth 28 --layers handsy.dxf handsy_model.c
+       $(DXF2GL) --smooth 28 --layers handsy.dxf handsy_model.c
 
 gravitywell:   gravitywell.o   $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
@@ -1129,8 +1161,8 @@ headroom: headroom.o       $(HEADROOM_OBJS)
        $(CC_HACK) -o $@ $@.o    $(HEADROOM_OBJS) $(HACK_LIBS)
 
 headroom_dxf::
-       ./dxf2gl.pl --layers headroom.dxf headroom_model.c
-       ./dxf2gl.pl --layers skull.dxf skull_model.c
+       $(DXF2GL) --layers headroom.dxf headroom_model.c
+       $(DXF2GL) --layers skull.dxf skull_model.c
 
 beats:         beats.o         sphere.o $(HACK_OBJS)
        $(CC_HACK) -o $@ $@.o   sphere.o $(HACK_OBJS) $(HACK_LIBS)
@@ -1151,7 +1183,7 @@ chompytower:      chompytower.o   $(CHOBJS) $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o   $(CHOBJS) $(HACK_TRACK_OBJS) $(HACK_LIBS)
 
 teeth_dxf::
-       ./dxf2gl.pl --layers --smooth --normalize teeth.dxf teeth_model.c
+       $(DXF2GL) --layers --smooth --normalize teeth.dxf teeth_model.c
 
 hextrail:      hextrail.o       normals.o $(HACK_TRACK_OBJS)
        $(CC_HACK) -o $@ $@.o    normals.o $(HACK_TRACK_OBJS) $(HACK_LIBS)
@@ -1168,7 +1200,7 @@ skulloop: skulloop.o       $(SKULLOOP_OBJS)
        $(CC_HACK) -o $@ $@.o    $(SKULLOOP_OBJS) $(HACK_LIBS)
 
 kallisti_dxf::
-       ./dxf2gl.pl --smooth --normalize kallisti.dxf kallisti_model.c
+       $(DXF2GL) --smooth --normalize kallisti.dxf kallisti_model.c
 KALLISTI=kallisti.o kallisti_model.o gllist.o $(HACK_TRACK_OBJS)
 kallisti:                      $(KALLISTI)
        $(CC_HACK) -o $@        $(KALLISTI) $(HACK_LIBS)
@@ -1178,13 +1210,13 @@ kallisti:                       $(KALLISTI)
 # highvoltage3.dxf: export pole cables as lines
 # highvoltage4.dxf: export pole connections as lines
 highvoltage_dxf::
-       ./dxf2gl.pl --wireframe --layers highvoltage.dxf  highvoltage_model.c
+       $(DXF2GL) --wireframe --layers highvoltage.dxf  highvoltage_model.c
        mv highvoltage_model.c highvoltage_tmp1.c
-       ./dxf2gl.pl --smooth highvoltage2.dxf highvoltage_model_tower_j_body.c
+       $(DXF2GL) --smooth highvoltage2.dxf highvoltage_model_tower_j_body.c
        mv highvoltage_model_tower_j_body.c highvoltage_tmp2.c
-       ./dxf2gl.pl --wireframe --layers highvoltage3.dxf highvoltage_model.c
+       $(DXF2GL) --wireframe --layers highvoltage3.dxf highvoltage_model.c
        mv highvoltage_model.c highvoltage_tmp3.c
-       ./dxf2gl.pl --wireframe --layers highvoltage4.dxf highvoltage_model.c
+       $(DXF2GL) --wireframe --layers highvoltage4.dxf highvoltage_model.c
        mv highvoltage_model.c highvoltage_tmp4.c
        cat highvoltage_tmp[1234].c > highvoltage_model.c
        rm highvoltage_tmp[1234].c
@@ -1207,11 +1239,76 @@ klondike:       klondike.o $(KLONDIKE_OBJS)
        $(CC_HACK) -o $@ $@.o   $(KLONDIKE_OBJS) $(HACK_LIBS) $(PNG_LIBS)
 
 dumpster_dxf::
-       ./dxf2gl.pl --smooth --layers --normalize dumpster.dxf dumpster_model.c
+       $(DXF2GL) --smooth --layers --normalize dumpster.dxf dumpster_model.c
 DUMPSTERFIRE=dumpsterfire.o dumpster_model.o gllist.o $(EASE) $(HACK_TRACK_OBJS)
 dumpsterfire:                  $(DUMPSTERFIRE)
        $(CC_HACK) -o $@        $(DUMPSTERFIRE) $(HACK_LIBS)
 
+xshadertoy:    xshadertoy.o    $(HACK_TRACK_OBJS)
+       $(CC_HACK) -o $@ $@.o   $(HACK_TRACK_OBJS) $(HACK_LIBS)
+
+
+
+# Shadertoy-based savers:
+
+
+SHCC = $(srcdir)/xshadertoy-compile.pl
+CC_GLSL = $(SHCC) --quiet --name
+
+alienbeacon: glsl/alienbeacon.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+batteredplanet: glsl/batteredplanet.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+elementalring: glsl/elementalring.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+fluxcore: glsl/fluxcore.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+gimbalharmonics: glsl/gimbalharmonics.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+hexplasma: glsl/hexplasma.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+logarithmiccircles: glsl/logarithmiccircles.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+neongravity: glsl/neongravity-0.glsl glsl/neongravity-1.glsl $(SHCC)
+       $(CC_GLSL) $@ $< $(srcdir)/glsl/neongravity-1.glsl
+
+neontriangulator: glsl/neontriangulator.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+protophore: glsl/protophore.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+selfreflect: glsl/selfreflect.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+skyline: glsl/skyline.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+stardome: glsl/stardome.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+starnest: glsl/starnest.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+stripeytorus: glsl/stripeytorus.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+synthwavecity: glsl/synthwavecity.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+topologica: glsl/topologica.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
+truchetzoom: glsl/truchetzoom.glsl $(SHCC)
+       $(CC_GLSL) $@ $<
+
 
 ##############################################################################
 #
@@ -1536,6 +1633,7 @@ carousel.o: $(UTILS_SRC)/resources.h
 carousel.o: $(UTILS_SRC)/usleep.h
 carousel.o: $(UTILS_SRC)/visual.h
 carousel.o: $(UTILS_SRC)/xft.h
+carousel.o: $(UTILS_SRC)/xftwrap.h
 carousel.o: $(UTILS_SRC)/yarandom.h
 carousel.o: $(HACK_SRC)/xlockmoreI.h
 carousel.o: $(HACK_SRC)/xlockmore.h
@@ -3876,6 +3974,7 @@ photopile.o: $(UTILS_SRC)/resources.h
 photopile.o: $(UTILS_SRC)/usleep.h
 photopile.o: $(UTILS_SRC)/visual.h
 photopile.o: $(UTILS_SRC)/xft.h
+photopile.o: $(UTILS_SRC)/xftwrap.h
 photopile.o: $(UTILS_SRC)/yarandom.h
 photopile.o: $(HACK_SRC)/xlockmoreI.h
 photopile.o: $(HACK_SRC)/xlockmore.h
@@ -5434,4 +5533,23 @@ xlock-gl-utils.o: $(HACK_SRC)/xlockmoreI.h
 xscreensaver-gl-visual.o: ../../config.h
 xscreensaver-gl-visual.o: $(UTILS_SRC)/visual-gl.h
 xscreensaver-gl-visual.o: $(UTILS_SRC)/visual.h
+xshadertoy.o: ../../config.h
+xshadertoy.o: $(HACK_SRC)/fps.h
+xshadertoy.o: $(srcdir)/glsl-utils.h
+xshadertoy.o: $(HACK_SRC)/recanim.h
+xshadertoy.o: $(srcdir)/rotator.h
+xshadertoy.o: $(HACK_SRC)/screenhackI.h
+xshadertoy.o: $(UTILS_SRC)/colors.h
+xshadertoy.o: $(UTILS_SRC)/doubletime.h
+xshadertoy.o: $(UTILS_SRC)/erase.h
+xshadertoy.o: $(UTILS_SRC)/font-retry.h
+xshadertoy.o: $(UTILS_SRC)/grabclient.h
+xshadertoy.o: $(UTILS_SRC)/hsv.h
+xshadertoy.o: $(UTILS_SRC)/resources.h
+xshadertoy.o: $(UTILS_SRC)/usleep.h
+xshadertoy.o: $(UTILS_SRC)/visual.h
+xshadertoy.o: $(UTILS_SRC)/xft.h
+xshadertoy.o: $(UTILS_SRC)/yarandom.h
+xshadertoy.o: $(HACK_SRC)/xlockmoreI.h
+xshadertoy.o: $(HACK_SRC)/xlockmore.h
 
diff --git a/hacks/glx/alienbeacon.man b/hacks/glx/alienbeacon.man
new file mode 100644 (file)
index 0000000..dadb6e8
--- /dev/null
@@ -0,0 +1,67 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+alienbeacon \- screen saver.
+.SH SYNOPSIS
+.B alienbeacon
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Our investigation of the signal from the planet's surface brought us to
+what seems to be an alien beacon. Based on the rock formation around the
+beacon, it was probably left here millions of years ago. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/ld2SzK
+.SH COPYRIGHT
+Copyright \(co 2014 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
diff --git a/hacks/glx/batteredplanet.man b/hacks/glx/batteredplanet.man
new file mode 100644 (file)
index 0000000..120672c
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+batteredplanet \- screen saver.
+.SH SYNOPSIS
+.B batteredplanet
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+An alien planet full of craters, with other celestial objects in the sky. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/wsjBD3
+.SH COPYRIGHT
+Copyright \(co 2020 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
index 901cda2f1df25de623a9c5fc1e08f410ec29ed08..a82c39b50187bef431c64dcb6e5fd75b76608d1d 100644 (file)
@@ -30,7 +30,6 @@
 
 # define release_carousel 0
 # include "xlockmore.h"
-# include "easing.h"
 
 #ifdef USE_GL
 
@@ -46,6 +45,8 @@
 #include "gltrackball.h"
 #include "grab-ximage.h"
 #include "texfont.h"
+#include "xftwrap.h"
+#include "easing.h"
 
 # ifndef HAVE_JWXYZ
 #  include <X11/Intrinsic.h>     /* for XrmDatabase in -debug mode */
@@ -800,7 +801,10 @@ draw_frame (ModeInfo *mi, image_frame *frame, time_t now, Bool body_p)
       XCharStruct e;
       int sw, sh;
       GLfloat scale = 0.05;
-      char *title = frame->current.title ? frame->current.title : "(untitled)";
+      char *title = frame->current.title;
+      char *token, *line;
+      int lineno = 0;
+
       texture_string_metrics (ss->texfont, title, &e, 0, 0);
       sw = e.width;
       sh = e.ascent + e.descent;
@@ -809,26 +813,42 @@ draw_frame (ModeInfo *mi, image_frame *frame, time_t now, Bool body_p)
 
       scale /= sh;
       glScalef (scale, scale, scale);
-
-      glTranslatef (((1/scale) - sw) / 2, 0, 0);
       glColor3f (1, 1, 1);
 
-      if (!wire)
+      /* Wrap long lines */
+      title = xft_word_wrap (MI_DISPLAY(mi), texfont_xft (ss->texfont),
+                             title, 1 / scale);
+      token = title;
+
+      /* print_texture_string() does flushleft for newlines,
+         but we want the lines centered. */
+      while ((line = strtok (token, "\n")))
         {
-          glEnable (GL_TEXTURE_2D);
+          token = 0;
+          texture_string_metrics (ss->texfont, line, &e, 0, 0);
+          sw = e.width;
+          glPushMatrix();
+          glTranslatef (((1/scale) - sw) / 2, -sh * lineno, 0);
+          if (!wire)
+            {
 # ifndef HAVE_ANDROID   /* Doesn't work -- photo displays as static */
-          print_texture_string (ss->texfont, title);
+              print_texture_string (ss->texfont, line);
 # endif
+            }
+          else
+            {
+              glBegin (GL_LINE_LOOP);
+              glVertex3f (0,  0,  0);
+              glVertex3f (sw, 0,  0);
+              glVertex3f (sw, sh, 0);
+              glVertex3f (0,  sh, 0);
+              glEnd();
+            }
+          glPopMatrix();
+          lineno++;
         }
-      else
-        {
-          glBegin (GL_LINE_LOOP);
-          glVertex3f (0,  0,  0);
-          glVertex3f (sw, 0,  0);
-          glVertex3f (sw, sh, 0);
-          glVertex3f (0,  sh, 0);
-          glEnd();
-        }
+
+      free (title);
     }
 
   glPopMatrix();
index de4c1d10e500c0bfbdcfb5cbc1fc6c691de4ab92..adc5e9f070b8eb00d0df3b99f9416deca8626ed8 100644 (file)
@@ -7,7 +7,7 @@
 static const char sccsid[] = "@(#)cubocteversion.c  1.1 23/03/02 xlockmore";
 #endif
 
-/* Copyright (c) 2023-2025 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2023-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -24,6 +24,7 @@ static const char sccsid[] = "@(#)cubocteversion.c  1.1 23/03/02 xlockmore";
  *
  * REVISION HISTORY:
  * C. Steger - 23/03/06: Initial version
+ * C. Steger - 26/01/04: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -290,7 +291,7 @@ typedef struct {
   GLuint self_tri_strips;
   Bool use_shaders;
 #ifdef HAVE_GLSL
-  Bool use_mipmaps;
+  Bool use_mipmaps, use_vao;
   /* The precomputed texture coordinates of the cuboctahedron */
   GLfloat tex[3*3*NUM_FACE];
   /* The textures of earth by day (index 0), earth by night (index 1), and
@@ -369,6 +370,7 @@ typedef struct {
   GLint wa_finl_tex_samp_color, wa_finl_tex_samp_num;
   GLint wa_finl_tex_samp_opaque;
   GLuint quad_buffer;
+  GLuint vertex_array_object;
 #endif /* HAVE_GLSL */
 } cubocteversionstruct;
 
@@ -1261,863 +1263,776 @@ static float vert_denner[NUM_MODELS_DENNER][NUM_VERT][3] =
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n"
-  "precision highp sampler2D;\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *poly_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "attribute vec3 VertexNormal;\n"
-  "attribute vec4 VertexColorF;\n"
-  "attribute vec4 VertexColorB;\n"
-  "attribute vec3 VertexTexCoord;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec3 TexCoord;\n"
-  "\n";
-static const GLchar *poly_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "in vec3 VertexNormal;\n"
-  "in vec4 VertexColorF;\n"
-  "in vec4 VertexColorB;\n"
-  "in vec3 VertexTexCoord;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 ColorF;\n"
-  "out vec4 ColorB;\n"
-  "out vec3 TexCoord;\n"
-  "\n";
-static const GLchar *poly_vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  ColorF = VertexColorF;\n"
-  "  ColorB = VertexColorB;\n"
-  "  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexTexCoord;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *poly_fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec3 TexCoord;\n"
-  "\n";
-static const GLchar *poly_fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 ColorF;\n"
-  "in vec4 ColorB;\n"
-  "in vec3 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *poly_fragment_shader_main =
-  "const float M_PI_F  = 3.14159265359f;\n"
-  "const float M_2PI_F = 6.28318530718f;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSamplerFront;\n"
-  "uniform sampler2D TextureSamplerBack;\n"
-  "uniform sampler2D TextureSamplerWater;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec3 normalDirection;\n"
-  "  vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "  vec4 ambientLighting, diffuseReflection, specularReflection, color;\n"
-  "  vec3 normTexCoord\n;"
-  "  vec2 texCoor;\n"
-  "  float ndotl, ndoth, pf, lat, lon;\n"
-  "  \n"
-  "  if (gl_FrontFacing)\n"
-  "  {\n"
-  "    normalDirection = normalize(Normal);\n"
-  "    sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;\n"
-  "    ambientColor = ColorF*MatFrontAmbient;\n"
-  "    diffuseColor = ColorF*MatFrontDiffuse;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    normalDirection = -normalize(Normal);\n"
-  "    sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;\n"
-  "    ambientColor = ColorB*MatBackAmbient;\n"
-  "    diffuseColor = ColorB*MatBackDiffuse;\n"
-  "  }\n"
-  "  \n"
-  "  ndotl = max(0.0f,dot(normalDirection,LtDirection));\n"
-  "  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));\n"
-  "  if (ndotl == 0.0f)\n"
-  "    pf = 0.0f;\n"
-  "  else\n"
-  "    pf = pow(ndoth,MatShininess);\n"
-  "  ambientLighting = ambientColor*LtAmbient;\n"
-  "  diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "  specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "  color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *poly_fragment_shader_out_2_1 =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    normTexCoord = normalize(TexCoord);\n"
-  "    lat = asin(normTexCoord.z);\n"
-  "    lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture2D(TextureSamplerFront,texCoor);\n"
-  "      specularReflection *= texture2D(TextureSamplerWater,texCoor);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture2D(TextureSamplerBack,texCoor);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  gl_FragColor = clamp(color,0.0f,1.0f);\n"
-  "  gl_FragColor.a = diffuseColor.a;\n"
-  "}\n";
-static const GLchar *poly_fragment_shader_out_3_0 =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    normTexCoord = normalize(TexCoord);\n"
-  "    lat = asin(normTexCoord.z);\n"
-  "    lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerFront,texCoor);\n"
-  "      specularReflection *= texture(TextureSamplerWater,texCoor);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerBack,texCoor);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  FragColor = clamp(color,0.0f,1.0f);\n"
-  "  FragColor.a = diffuseColor.a;\n"
-  "}\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_init_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *dp_init_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *dp_init_vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_init_fragment_shader_attribs_2_1 =
-  "";
-static const GLchar *dp_init_fragment_shader_attribs_3_0 =
-  "out vec2 FragColor;\n"
-  "\n";
-static const GLchar *dp_init_fragment_shader_main =
-  "const float MAX_DEPTH = 1.0f;\n"
-  "uniform vec2 TexScale;\n"
-  "uniform sampler2D TexSamplerOpaqueDepth;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec2 texCoord = gl_FragCoord.xy*TexScale;\n";
-static const GLchar *dp_init_fragment_shader_out_2_1 =
-  "  float opaqueDepth = texture2D(TexSamplerOpaqueDepth,texCoord.st).x;\n"
-  "  if (opaqueDepth != 1.0f && gl_FragCoord.z > opaqueDepth)\n"
-  "    gl_FragColor.rg = vec2(-MAX_DEPTH,opaqueDepth);\n"
-  "  else\n"
-  "    gl_FragColor.rg = vec2(-gl_FragCoord.z,gl_FragCoord.z);\n"
-  "}\n";
-static const GLchar *dp_init_fragment_shader_out_3_0 =
-  "  float opaqueDepth = texture(TexSamplerOpaqueDepth,texCoord.st).x;\n"
-  "  if (opaqueDepth != 1.0f && gl_FragCoord.z > opaqueDepth)\n"
-  "    FragColor = vec2(-MAX_DEPTH,opaqueDepth);\n"
-  "  else\n"
-  "    FragColor = vec2(-gl_FragCoord.z,gl_FragCoord.z);\n"
-  "}\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *dp_peel_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "attribute vec3 VertexNormal;\n"
-  "attribute vec4 VertexColorF;\n"
-  "attribute vec4 VertexColorB;\n"
-  "attribute vec3 VertexTexCoord;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec3 TexCoord;\n"
-  "\n";
-static const GLchar *dp_peel_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "in vec3 VertexNormal;\n"
-  "in vec4 VertexColorF;\n"
-  "in vec4 VertexColorB;\n"
-  "in vec3 VertexTexCoord;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 ColorF;\n"
-  "out vec4 ColorB;\n"
-  "out vec3 TexCoord;\n"
-  "\n";
-static const GLchar *dp_peel_vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  ColorF = VertexColorF;\n"
-  "  ColorB = VertexColorB;\n"
-  "  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexTexCoord;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_peel_fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec3 TexCoord;\n"
-  "\n";
-static const GLchar *dp_peel_fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 ColorF;\n"
-  "in vec4 ColorB;\n"
-  "in vec3 TexCoord;\n"
-  "\n";
-static const GLchar *dp_peel_fragment_shader_attribs_3_0_es =
-  "in vec3 Normal;\n"
-  "in vec4 ColorF;\n"
-  "in vec4 ColorB;\n"
-  "in vec3 TexCoord;\n"
-  "\n"
-  "layout(location = 0) out vec4 FragData0;\n"
-  "layout(location = 1) out vec4 FragData1;\n"
-  "layout(location = 2) out vec4 FragData2;\n"
-  "\n";
-static const GLchar *dp_peel_fragment_shader_main =
-  "const float M_PI_F  = 3.14159265359f;\n"
-  "const float M_2PI_F = 6.28318530718f;\n"
-  "const float MAX_DEPTH = 1.0f;\n"
-  "const float EPS = 1.0e-7f;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform vec2 TexScale;\n"
-  "uniform sampler2D TexSamplerDepthBlender;\n"
-  "uniform sampler2D TexSamplerFrontBlender;\n"
-  "uniform sampler2D TexSamplerFront;\n"
-  "uniform sampler2D TexSamplerBack;\n"
-  "uniform sampler2D TexSamplerWater;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  float fragDepth, nearestDepth, farthestDepth, alphaMultiplier;\n"
-  "  vec2 depthBlender, peelTexCoord;\n"
-  "  vec4 forwardTemp;\n"
-  "  \n"
-  "  vec3 normalDirection;\n"
-  "  vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "  vec4 ambientLighting, diffuseReflection, specularReflection, color;\n"
-  "  vec3 normTexCoord\n;"
-  "  vec2 texCoor;\n"
-  "  float ndotl, ndoth, pf, lat, lon;\n"
-  "  \n";
-static const GLchar *dp_peel_fragment_shader_peel_2_1 =
-  "  peelTexCoord = gl_FragCoord.xy*TexScale;\n"
-  "  fragDepth = gl_FragCoord.z;\n"
-  "  depthBlender = texture2D(TexSamplerDepthBlender,peelTexCoord.st).xy;\n"
-  "  forwardTemp = texture2D(TexSamplerFrontBlender,peelTexCoord.st);\n"
-  "  gl_FragData[0].xy = depthBlender;\n"
-  "  gl_FragData[1] = forwardTemp;\n"
-  "  gl_FragData[2] = vec4(0.0f);\n"
-  "  nearestDepth = -depthBlender.x;\n"
-  "  farthestDepth = depthBlender.y;\n"
-  "  alphaMultiplier = 1.0f-forwardTemp.a;\n"
-  "  if (fragDepth < nearestDepth-EPS || fragDepth > farthestDepth+EPS)\n"
-  "  {\n"
-  "    gl_FragData[0].xy = vec2(-MAX_DEPTH);\n"
-  "  }\n"
-  "  else if (fragDepth > nearestDepth+EPS && fragDepth < farthestDepth-EPS)\n"
-  "  {\n"
-  "    gl_FragData[0].xy = vec2(-fragDepth,fragDepth);\n"
-  "  }\n"
-  "  else\n"
-  "  {\n";
-static const GLchar *dp_peel_fragment_shader_peel_3_0 =
-  "  peelTexCoord = gl_FragCoord.xy*TexScale;\n"
-  "  fragDepth = gl_FragCoord.z;\n"
-  "  depthBlender = texture(TexSamplerDepthBlender,peelTexCoord.st).xy;\n"
-  "  forwardTemp = texture(TexSamplerFrontBlender,peelTexCoord.st);\n"
-  "  gl_FragData[0].xy = depthBlender;\n"
-  "  gl_FragData[1] = forwardTemp;\n"
-  "  gl_FragData[2] = vec4(0.0f);\n"
-  "  nearestDepth = -depthBlender.x;\n"
-  "  farthestDepth = depthBlender.y;\n"
-  "  alphaMultiplier = 1.0f-forwardTemp.a;\n"
-  "  if (fragDepth < nearestDepth-EPS || fragDepth > farthestDepth+EPS)\n"
-  "  {\n"
-  "    gl_FragData[0].xy = vec2(-MAX_DEPTH);\n"
-  "  }\n"
-  "  else if (fragDepth > nearestDepth+EPS && fragDepth < farthestDepth-EPS)\n"
-  "  {\n"
-  "    gl_FragData[0].xy = vec2(-fragDepth,fragDepth);\n"
-  "  }\n"
-  "  else\n"
-  "  {\n";
-static const GLchar *dp_peel_fragment_shader_peel_3_0_es =
-  "  peelTexCoord = gl_FragCoord.xy*TexScale;\n"
-  "  fragDepth = gl_FragCoord.z;\n"
-  "  depthBlender = texture(TexSamplerDepthBlender,peelTexCoord.st).xy;\n"
-  "  forwardTemp = texture(TexSamplerFrontBlender,peelTexCoord.st);\n"
-  "  FragData0.xy = depthBlender;\n"
-  "  FragData1 = forwardTemp;\n"
-  "  FragData2 = vec4(0.0f);\n"
-  "  nearestDepth = -depthBlender.x;\n"
-  "  farthestDepth = depthBlender.y;\n"
-  "  alphaMultiplier = 1.0f-forwardTemp.a;\n"
-  "  if (fragDepth < nearestDepth-EPS || fragDepth > farthestDepth+EPS)\n"
-  "  {\n"
-  "    FragData0.xy = vec2(-MAX_DEPTH);\n"
-  "  }\n"
-  "  else if (fragDepth > nearestDepth+EPS && fragDepth < farthestDepth-EPS)\n"
-  "  {\n"
-  "    FragData0.xy = vec2(-fragDepth,fragDepth);\n"
-  "  }\n"
-  "  else\n"
-  "  {\n";
-static const GLchar *dp_peel_fragment_shader_col =
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;\n"
-  "      ambientColor = ColorF*MatFrontAmbient;\n"
-  "      diffuseColor = ColorF*MatFrontDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;\n"
-  "      ambientColor = ColorB*MatBackAmbient;\n"
-  "      diffuseColor = ColorB*MatBackDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0f,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0f,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0f)\n"
-  "      pf = 0.0f;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *dp_peel_fragment_shader_col_2_1 =
-  "    if (BoolTextures)\n"
-  "    {\n"
-  "      normTexCoord = normalize(TexCoord);\n"
-  "      lat = asin(normTexCoord.z);\n"
-  "      lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "      texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "      if (gl_FrontFacing)\n"
-  "      {\n"
-  "        color *= texture2D(TexSamplerFront,texCoor);\n"
-  "        specularReflection *= texture2D(TexSamplerWater,texCoor);\n"
-  "      }\n"
-  "      else\n"
-  "      {\n"
-  "        color *= texture2D(TexSamplerBack,texCoor);\n"
-  "        specularReflection *= 0.0f;\n"
-  "      }\n"
-  "    }\n"
-  "    color += specularReflection;\n"
-  "    color = clamp(color,0.0f,1.0f);\n"
-  "    color.a = diffuseColor.a;\n"
-  "    \n";
-static const GLchar *dp_peel_fragment_shader_col_3_0 =
-  "    if (BoolTextures)\n"
-  "    {\n"
-  "      normTexCoord = normalize(TexCoord);\n"
-  "      lat = asin(normTexCoord.z);\n"
-  "      lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "      texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "      if (gl_FrontFacing)\n"
-  "      {\n"
-  "        color *= texture(TexSamplerFront,texCoor);\n"
-  "        specularReflection *= texture(TexSamplerWater,texCoor);\n"
-  "      }\n"
-  "      else\n"
-  "      {\n"
-  "        color *= texture(TexSamplerBack,texCoor);\n"
-  "        specularReflection *= 0.0f;\n"
-  "      }\n"
-  "    }\n"
-  "    color += specularReflection;\n"
-  "    color = clamp(color,0.0f,1.0f);\n"
-  "    color.a = diffuseColor.a;\n"
-  "    \n";
-static const GLchar *dp_peel_fragment_shader_out_2_1 =
-  "    gl_FragData[0].xy = vec2(-MAX_DEPTH);\n"
-  "    if (fragDepth >= nearestDepth-EPS && fragDepth <= nearestDepth+EPS)\n"
-  "    {\n"
-  "      gl_FragData[1].rgb += color.rgb*color.a*alphaMultiplier;\n"
-  "      gl_FragData[1].a = 1.0f-alphaMultiplier*(1.0f-color.a);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      gl_FragData[2] += color;\n"
-  "    }\n"
-  "  }\n"
-  "}\n";
-static const GLchar *dp_peel_fragment_shader_out_3_0 =
-  "    gl_FragData[0].xy = vec2(-MAX_DEPTH);\n"
-  "    if (fragDepth >= nearestDepth-EPS && fragDepth <= nearestDepth+EPS)\n"
-  "    {\n"
-  "      gl_FragData[1].rgb += color.rgb*color.a*alphaMultiplier;\n"
-  "      gl_FragData[1].a = 1.0f-alphaMultiplier*(1.0f-color.a);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      gl_FragData[2] += color;\n"
-  "    }\n"
-  "  }\n"
-  "}\n";
-static const GLchar *dp_peel_fragment_shader_out_3_0_es =
-  "    FragData0.xy = vec2(-MAX_DEPTH);\n"
-  "    if (fragDepth >= nearestDepth-EPS && fragDepth <= nearestDepth+EPS)\n"
-  "    {\n"
-  "      FragData1.rgb += color.rgb*color.a*alphaMultiplier;\n"
-  "      FragData1.a = 1.0f-alphaMultiplier*(1.0f-color.a);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      FragData2 += color;\n"
-  "    }\n"
-  "  }\n"
-  "}\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_blnd_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *dp_blnd_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *dp_blnd_vertex_shader_main =
-  "void main (void)\n"
-  "{\n"
-  "  gl_Position = vec4(VertexPosition,1.0f);\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_blnd_fragment_shader_attribs_2_1 =
-  "";
-static const GLchar *dp_blnd_fragment_shader_attribs_3_0 =
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *dp_blnd_fragment_shader_main =
-  "uniform vec2 TexScale;\n"
-  "uniform sampler2D TexSamplerTemp;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec2 TexCoord = gl_FragCoord.xy*TexScale;\n";
-static const GLchar *dp_blnd_fragment_shader_out_2_1 =
-  "  gl_FragColor = texture2D(TexSamplerTemp,TexCoord.st);\n"
-  "  if (gl_FragColor.a == 0.0f)\n"
-  "    discard;\n"
-  "}\n";
-static const GLchar *dp_blnd_fragment_shader_out_3_0 =
-  "  FragColor = texture(TexSamplerTemp,TexCoord.st);\n"
-  "  if (FragColor.a == 0.0f)\n"
-  "    discard;\n"
-  "}\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_finl_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *dp_finl_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *dp_finl_vertex_shader_main =
-  "void main (void)\n"
-  "{\n"
-  "  gl_Position = vec4(VertexPosition,1.0f);\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *dp_finl_fragment_shader_attribs_2_1 =
-  "";
-static const GLchar *dp_finl_fragment_shader_attribs_3_0 =
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *dp_finl_fragment_shader_main =
-  "uniform vec2 TexScale;\n"
-  "uniform sampler2D TexSamplerFrontBlender;\n"
-  "uniform sampler2D TexSamplerBackBlender;\n"
-  "uniform sampler2D TexSamplerOpaqueBlender;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 transColor;\n"
-  "  vec2 TexCoord = gl_FragCoord.xy*TexScale;\n";
-static const GLchar *dp_finl_fragment_shader_out_2_1 =
-  "  vec4 frontColor = texture2D(TexSamplerFrontBlender,TexCoord.st);\n"
-  "  vec4 backColor = texture2D(TexSamplerBackBlender,TexCoord.st);\n"
-  "  vec4 opaqueColor = texture2D(TexSamplerOpaqueBlender,TexCoord.st);\n"
-  "  frontColor.a = 1.0f-frontColor.a;\n"
-  "  transColor.rgb = frontColor.rgb+backColor.rgb*frontColor.a;\n"
-  "  transColor.a = (1.0f-frontColor.a*(1.0f-backColor.a));\n"
-  "  gl_FragColor.rgb = transColor.rgb+opaqueColor.rgb*(1.0f-transColor.a);\n"
-  "  gl_FragColor.a = transColor.a+opaqueColor.a*(1.0f-transColor.a);\n"
-  "}\n";
-static const GLchar *dp_finl_fragment_shader_out_3_0 =
-  "  vec4 frontColor = texture(TexSamplerFrontBlender,TexCoord.st);\n"
-  "  vec4 backColor = texture(TexSamplerBackBlender,TexCoord.st);\n"
-  "  vec4 opaqueColor = texture(TexSamplerOpaqueBlender,TexCoord.st);\n"
-  "  frontColor.a = 1.0f-frontColor.a;\n"
-  "  transColor.rgb = frontColor.rgb+backColor.rgb*frontColor.a;\n"
-  "  transColor.a = (1.0f-frontColor.a*(1.0f-backColor.a));\n"
-  "  FragColor.rgb = transColor.rgb+opaqueColor.rgb*(1.0f-transColor.a);\n"
-  "  FragColor.a = transColor.a+opaqueColor.a*(1.0f-transColor.a);\n"
-  "}\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *wa_init_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "attribute vec3 VertexNormal;\n"
-  "attribute vec4 VertexColorF;\n"
-  "attribute vec4 VertexColorB;\n"
-  "attribute vec3 VertexTexCoord;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec3 TexCoord;\n"
-  "\n";
-static const GLchar *wa_init_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "in vec3 VertexNormal;\n"
-  "in vec4 VertexColorF;\n"
-  "in vec4 VertexColorB;\n"
-  "in vec3 VertexTexCoord;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 ColorF;\n"
-  "out vec4 ColorB;\n"
-  "out vec3 TexCoord;\n"
-  "\n";
-static const GLchar *wa_init_vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  ColorF = VertexColorF;\n"
-  "  ColorB = VertexColorB;\n"
-  "  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexTexCoord;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *wa_init_fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec3 TexCoord;\n"
-  "\n";
-static const GLchar *wa_init_fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 ColorF;\n"
-  "in vec4 ColorB;\n"
-  "in vec3 TexCoord;\n"
-  "\n";
-static const GLchar *wa_init_fragment_shader_attribs_3_0_es =
-  "in vec3 Normal;\n"
-  "in vec4 ColorF;\n"
-  "in vec4 ColorB;\n"
-  "in vec3 TexCoord;\n"
-  "\n"
-  "layout(location = 0) out vec4 FragData0;\n"
-  "layout(location = 1) out vec4 FragData1;\n"
-  "\n";
-static const GLchar *wa_init_fragment_shader_main =
-  "const float M_PI_F  = 3.14159265359f;\n"
-  "const float M_2PI_F = 6.28318530718f;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSamplerFront;\n"
-  "uniform sampler2D TextureSamplerBack;\n"
-  "uniform sampler2D TextureSamplerWater;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec3 normalDirection;\n"
-  "  vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "  vec4 ambientLighting, diffuseReflection, specularReflection, color;\n"
-  "  vec3 normTexCoord\n;"
-  "  vec2 texCoor;\n"
-  "  float ndotl, ndoth, pf, lat, lon;\n"
-  "  \n"
-  "  if (gl_FrontFacing)\n"
-  "  {\n"
-  "    normalDirection = normalize(Normal);\n"
-  "    sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;\n"
-  "    ambientColor = ColorF*MatFrontAmbient;\n"
-  "    diffuseColor = ColorF*MatFrontDiffuse;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    normalDirection = -normalize(Normal);\n"
-  "    sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;\n"
-  "    ambientColor = ColorB*MatBackAmbient;\n"
-  "    diffuseColor = ColorB*MatBackDiffuse;\n"
-  "  }\n"
-  "  \n"
-  "  ndotl = max(0.0f,dot(normalDirection,LtDirection));\n"
-  "  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));\n"
-  "  if (ndotl == 0.0f)\n"
-  "    pf = 0.0f;\n"
-  "  else\n"
-  "    pf = pow(ndoth,MatShininess);\n"
-  "  ambientLighting = ambientColor*LtAmbient;\n"
-  "  diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "  specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "  color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *wa_init_fragment_shader_out_2_1 =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    normTexCoord = normalize(TexCoord);\n"
-  "    lat = asin(normTexCoord.z);\n"
-  "    lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture2D(TextureSamplerFront,texCoor);\n"
-  "      specularReflection *= texture2D(TextureSamplerWater,texCoor);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture2D(TextureSamplerBack,texCoor);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  color = clamp(color,0.0f,1.0f);\n"
-  "  color.a = diffuseColor.a;\n"
-  "  gl_FragData[0] = vec4(color.rgb*color.a,color.a);\n"
-  "  gl_FragData[1] = vec4(1.0f);\n"
-  "}\n";
-static const GLchar *wa_init_fragment_shader_out_3_0 =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    normTexCoord = normalize(TexCoord);\n"
-  "    lat = asin(normTexCoord.z);\n"
-  "    lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerFront,texCoor);\n"
-  "      specularReflection *= texture(TextureSamplerWater,texCoor);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerBack,texCoor);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  color = clamp(color,0.0f,1.0f);\n"
-  "  color.a = diffuseColor.a;\n"
-  "  gl_FragData[0] = vec4(color.rgb*color.a,color.a);\n"
-  "  gl_FragData[1] = vec4(1.0f);\n"
-  "}\n";
-static const GLchar *wa_init_fragment_shader_out_3_0_es =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    normTexCoord = normalize(TexCoord);\n"
-  "    lat = asin(normTexCoord.z);\n"
-  "    lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerFront,texCoor);\n"
-  "      specularReflection *= texture(TextureSamplerWater,texCoor);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerBack,texCoor);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  color = clamp(color,0.0f,1.0f);\n"
-  "  color.a = diffuseColor.a;\n"
-  "  FragData0 = vec4(color.rgb*color.a,color.a);\n"
-  "  FragData1 = vec4(1.0f);\n"
-  "}\n";
-
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *wa_finl_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *wa_finl_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *wa_finl_vertex_shader_main =
-  "void main (void)\n"
-  "{\n"
-  "  gl_Position = vec4(VertexPosition,1.0f);\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *wa_finl_fragment_shader_attribs_2_1 =
-  "";
-static const GLchar *wa_finl_fragment_shader_attribs_3_0 =
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *wa_finl_fragment_shader_main =
-  "uniform vec2 TexScale;\n"
-  "uniform sampler2D TexSamplerColorBlender;\n"
-  "uniform sampler2D TexSamplerNumBlender;\n"
-  "uniform sampler2D TexSamplerOpaqueBlender;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec2 TexCoord = gl_FragCoord.xy*TexScale;\n";
-static const GLchar *wa_finl_fragment_shader_out_2_1 =
-  "  vec4 backColor = texture2D(TexSamplerOpaqueBlender,TexCoord.st);\n"
-  "  vec4 sumColor = texture2D(TexSamplerColorBlender,TexCoord.st);\n"
-  "  float n = texture2D(TexSamplerNumBlender,TexCoord.st).r;\n"
-  "  if (n == 0.0)\n"
-  "  {\n"
-  "    gl_FragColor = backColor;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 avgColor = sumColor.rgb/sumColor.a;\n"
-  "    float avgAlpha = sumColor.a/n;\n"
-  "    float t = pow(1.0f-avgAlpha,n);\n"
-  "    gl_FragColor.rgb = avgColor*(1.0f-t)+backColor.rgb*t;\n"
-  "    gl_FragColor.a = 1.0f-t;\n"
-  "  }\n"
-  "}\n";
-static const GLchar *wa_finl_fragment_shader_out_3_0 =
-  "  vec4 backColor = texture(TexSamplerOpaqueBlender,TexCoord.st);\n"
-  "  vec4 sumColor = texture(TexSamplerColorBlender,TexCoord.st);\n"
-  "  float n = texture(TexSamplerNumBlender,TexCoord.st).r;\n"
-  "  if (n == 0.0)\n"
-  "  {\n"
-  "    FragColor = backColor;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 avgColor = sumColor.rgb/sumColor.a;\n"
-  "    float avgAlpha = sumColor.a/n;\n"
-  "    float t = pow(1.0f-avgAlpha,n);\n"
-  "    FragColor.rgb = avgColor*(1.0f-t)+backColor.rgb*t;\n"
-  "    FragColor.a = 1.0f-t;\n"
-  "  }\n"
-  "}\n";
+/* The polygon vertex shader code. */
+static const GLchar *poly_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+attribute vec3 VertexNormal;                                             \n\
+attribute vec4 VertexColorF;                                             \n\
+attribute vec4 VertexColorB;                                             \n\
+attribute vec3 VertexTexCoord;                                           \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec3 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+in vec3 VertexNormal;                                                    \n\
+in vec4 VertexColorF;                                                    \n\
+in vec4 VertexColorB;                                                    \n\
+in vec3 VertexTexCoord;                                                  \n\
+out vec3 Normal;                                                         \n\
+out vec4 ColorF;                                                         \n\
+out vec4 ColorB;                                                         \n\
+out vec3 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  ColorF = VertexColorF;                                                 \n\
+  ColorB = VertexColorB;                                                 \n\
+  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;          \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexTexCoord;                                           \n\
+}                                                                        \n";
+
+/* The polygon fragment shader code. */
+static const GLchar *poly_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec3 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 ColorF;                                                          \n\
+in vec4 ColorB;                                                          \n\
+in vec3 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+const float M_PI_F  = 3.14159265359f;                                    \n\
+const float M_2PI_F = 6.28318530718f;                                    \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSamplerFront;                                   \n\
+uniform sampler2D TextureSamplerBack;                                    \n\
+uniform sampler2D TextureSamplerWater;                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec3 normalDirection;                                                  \n\
+  vec4 ambientColor, diffuseColor, sceneColor;                           \n\
+  vec4 ambientLighting, diffuseReflection, specularReflection, color;    \n\
+  vec3 normTexCoord;                                                     \n\
+  vec2 texCoor;                                                          \n\
+  float ndotl, ndoth, pf, lat, lon;                                      \n\
+                                                                         \n\
+  if (gl_FrontFacing)                                                    \n\
+  {                                                                      \n\
+    normalDirection = normalize(Normal);                                 \n\
+    sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;                   \n\
+    ambientColor = ColorF*MatFrontAmbient;                               \n\
+    diffuseColor = ColorF*MatFrontDiffuse;                               \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    normalDirection = -normalize(Normal);                                \n\
+    sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;                    \n\
+    ambientColor = ColorB*MatBackAmbient;                                \n\
+    diffuseColor = ColorB*MatBackDiffuse;                                \n\
+  }                                                                      \n\
+                                                                         \n\
+  ndotl = max(0.0f,dot(normalDirection,LtDirection));                    \n\
+  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));                   \n\
+  if (ndotl == 0.0f)                                                     \n\
+    pf = 0.0f;                                                           \n\
+  else                                                                   \n\
+    pf = pow(ndoth,MatShininess);                                        \n\
+  ambientLighting = ambientColor*LtAmbient;                              \n\
+  diffuseReflection = LtDiffuse*diffuseColor*ndotl;                      \n\
+  specularReflection = LtSpecular*MatSpecular*pf;                        \n\
+  color = sceneColor+ambientLighting+diffuseReflection;                  \n\
+  if (BoolTextures)                                                      \n\
+  {                                                                      \n\
+    normTexCoord = normalize(TexCoord);                                  \n\
+    lat = asin(normTexCoord.z);                                          \n\
+    lon = atan(normTexCoord.y,normTexCoord.x);                           \n\
+    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);                    \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSamplerFront,texCoor);                   \n\
+      specularReflection *= texture2D(TextureSamplerWater,texCoor);      \n\
+#else                                                                    \n\
+      color *= texture(TextureSamplerFront,texCoor);                     \n\
+      specularReflection *= texture(TextureSamplerWater,texCoor);        \n\
+#endif                                                                   \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSamplerBack,texCoor);                    \n\
+#else                                                                    \n\
+      color *= texture(TextureSamplerBack,texCoor);                      \n\
+#endif                                                                   \n\
+      specularReflection *= 0.0f;                                        \n\
+    }                                                                    \n\
+  }                                                                      \n\
+  color += specularReflection;                                           \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0f,1.0f);                                 \n\
+  gl_FragColor.a = diffuseColor.a;                                       \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0f,1.0f);                                    \n\
+  FragColor.a = diffuseColor.a;                                          \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+
+/* The vertex shader code for the initialization stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_init_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+}                                                                        \n";
+
+/* The fragment shader code for the initialization stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_init_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ >= 130                                                   \n\
+out vec2 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+const float MAX_DEPTH = 1.0f;                                            \n\
+uniform vec2 TexScale;                                                   \n\
+uniform sampler2D TexSamplerOpaqueDepth;                                 \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec2 texCoord = gl_FragCoord.xy*TexScale;                              \n\
+#if __VERSION__ <= 120                                                   \n\
+  float opaqueDepth = texture2D(TexSamplerOpaqueDepth,texCoord.st).x;    \n\
+  if (opaqueDepth != 1.0f && gl_FragCoord.z > opaqueDepth)               \n\
+    gl_FragColor.rg = vec2(-MAX_DEPTH,opaqueDepth);                      \n\
+  else                                                                   \n\
+    gl_FragColor.rg = vec2(-gl_FragCoord.z,gl_FragCoord.z);              \n\
+#else                                                                    \n\
+  float opaqueDepth = texture(TexSamplerOpaqueDepth,texCoord.st).x;      \n\
+  if (opaqueDepth != 1.0f && gl_FragCoord.z > opaqueDepth)               \n\
+    FragColor = vec2(-MAX_DEPTH,opaqueDepth);                            \n\
+  else                                                                   \n\
+    FragColor = vec2(-gl_FragCoord.z,gl_FragCoord.z);                    \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+
+/* The vertex shader code for the peeling stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_peel_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+attribute vec3 VertexNormal;                                             \n\
+attribute vec4 VertexColorF;                                             \n\
+attribute vec4 VertexColorB;                                             \n\
+attribute vec3 VertexTexCoord;                                           \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec3 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+in vec3 VertexNormal;                                                    \n\
+in vec4 VertexColorF;                                                    \n\
+in vec4 VertexColorB;                                                    \n\
+in vec3 VertexTexCoord;                                                  \n\
+out vec3 Normal;                                                         \n\
+out vec4 ColorF;                                                         \n\
+out vec4 ColorB;                                                         \n\
+out vec3 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  ColorF = VertexColorF;                                                 \n\
+  ColorB = VertexColorB;                                                 \n\
+  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;          \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexTexCoord;                                           \n\
+}                                                                        \n";
+
+/* The fragment shader code for the peeling stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_peel_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec3 TexCoord;                                                   \n\
+#define FragData0 gl_FragData[0]                                         \n\
+#define FragData1 gl_FragData[1]                                         \n\
+#define FragData2 gl_FragData[2]                                         \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 ColorF;                                                          \n\
+in vec4 ColorB;                                                          \n\
+in vec3 TexCoord;                                                        \n\
+#if defined(GL_ES)                                                       \n\
+layout(location = 0) out vec4 FragData0;                                 \n\
+layout(location = 1) out vec4 FragData1;                                 \n\
+layout(location = 2) out vec4 FragData2;                                 \n\
+#elif __VERSION__ >= 150 && !defined(GL_compatibility_profile)           \n\
+out vec4 FragData[3];                                                    \n\
+#define FragData0 FragData[0]                                            \n\
+#define FragData1 FragData[1]                                            \n\
+#define FragData2 FragData[2]                                            \n\
+#else                                                                    \n\
+#define FragData0 gl_FragData[0]                                         \n\
+#define FragData1 gl_FragData[1]                                         \n\
+#define FragData2 gl_FragData[2]                                         \n\
+#endif                                                                   \n\
+#endif                                                                   \n\
+                                                                         \n\
+const float M_PI_F  = 3.14159265359f;                                    \n\
+const float M_2PI_F = 6.28318530718f;                                    \n\
+const float MAX_DEPTH = 1.0f;                                            \n\
+const float EPS = 1.0e-7f;                                               \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform vec2 TexScale;                                                   \n\
+uniform sampler2D TexSamplerDepthBlender;                                \n\
+uniform sampler2D TexSamplerFrontBlender;                                \n\
+uniform sampler2D TexSamplerFront;                                       \n\
+uniform sampler2D TexSamplerBack;                                        \n\
+uniform sampler2D TexSamplerWater;                                       \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  float fragDepth, nearestDepth, farthestDepth, alphaMultiplier;         \n\
+  vec2 depthBlender, peelTexCoord;                                       \n\
+  vec4 forwardTemp;                                                      \n\
+                                                                         \n\
+  vec3 normalDirection;                                                  \n\
+  vec4 ambientColor, diffuseColor, sceneColor;                           \n\
+  vec4 ambientLighting, diffuseReflection, specularReflection, color;    \n\
+  vec3 normTexCoord;                                                     \n\
+  vec2 texCoor;                                                          \n\
+  float ndotl, ndoth, pf, lat, lon;                                      \n\
+                                                                         \n\
+  peelTexCoord = gl_FragCoord.xy*TexScale;                               \n\
+  fragDepth = gl_FragCoord.z;                                            \n\
+#if __VERSION__ <= 120                                                   \n\
+  depthBlender = texture2D(TexSamplerDepthBlender,peelTexCoord.st).xy;   \n\
+  forwardTemp = texture2D(TexSamplerFrontBlender,peelTexCoord.st);       \n\
+#else                                                                    \n\
+  depthBlender = texture(TexSamplerDepthBlender,peelTexCoord.st).xy;     \n\
+  forwardTemp = texture(TexSamplerFrontBlender,peelTexCoord.st);         \n\
+#endif                                                                   \n\
+  FragData0.xy = depthBlender;                                           \n\
+  FragData1 = forwardTemp;                                               \n\
+  FragData2 = vec4(0.0f);                                                \n\
+  nearestDepth = -depthBlender.x;                                        \n\
+  farthestDepth = depthBlender.y;                                        \n\
+  alphaMultiplier = 1.0f-forwardTemp.a;                                  \n\
+  if (fragDepth < nearestDepth-EPS || fragDepth > farthestDepth+EPS)     \n\
+  {                                                                      \n\
+    FragData0.xy = vec2(-MAX_DEPTH);                                     \n\
+  }                                                                      \n\
+  else if (fragDepth > nearestDepth+EPS && fragDepth < farthestDepth-EPS)\n\
+  {                                                                      \n\
+    FragData0.xy = vec2(-fragDepth,fragDepth);                           \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;                 \n\
+      ambientColor = ColorF*MatFrontAmbient;                             \n\
+      diffuseColor = ColorF*MatFrontDiffuse;                             \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;                  \n\
+      ambientColor = ColorB*MatBackAmbient;                              \n\
+      diffuseColor = ColorB*MatBackDiffuse;                              \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0f,dot(normalDirection,LtDirection));                  \n\
+    ndoth = max(0.0f,dot(normalDirection,LtHalfVector));                 \n\
+    if (ndotl == 0.0f)                                                   \n\
+      pf = 0.0f;                                                         \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = sceneColor+ambientLighting+diffuseReflection;                \n\
+    if (BoolTextures)                                                    \n\
+    {                                                                    \n\
+      normTexCoord = normalize(TexCoord);                                \n\
+      lat = asin(normTexCoord.z);                                        \n\
+      lon = atan(normTexCoord.y,normTexCoord.x);                         \n\
+      texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);                  \n\
+      if (gl_FrontFacing)                                                \n\
+      {                                                                  \n\
+#if __VERSION__ <= 120                                                   \n\
+        color *= texture2D(TexSamplerFront,texCoor);                     \n\
+        specularReflection *= texture2D(TexSamplerWater,texCoor);        \n\
+#else                                                                    \n\
+        color *= texture(TexSamplerFront,texCoor);                       \n\
+        specularReflection *= texture(TexSamplerWater,texCoor);          \n\
+#endif                                                                   \n\
+      }                                                                  \n\
+      else                                                               \n\
+      {                                                                  \n\
+#if __VERSION__ <= 120                                                   \n\
+        color *= texture2D(TexSamplerBack,texCoor);                      \n\
+#else                                                                    \n\
+        color *= texture(TexSamplerBack,texCoor);                        \n\
+#endif                                                                   \n\
+        specularReflection *= 0.0f;                                      \n\
+      }                                                                  \n\
+    }                                                                    \n\
+    color += specularReflection;                                         \n\
+    color = clamp(color,0.0f,1.0f);                                      \n\
+    color.a = diffuseColor.a;                                            \n\
+                                                                         \n\
+    FragData0.xy = vec2(-MAX_DEPTH);                                     \n\
+    if (fragDepth >= nearestDepth-EPS && fragDepth <= nearestDepth+EPS)  \n\
+    {                                                                    \n\
+      FragData1.rgb += color.rgb*color.a*alphaMultiplier;                \n\
+      FragData1.a = 1.0f-alphaMultiplier*(1.0f-color.a);                 \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      FragData2 += color;                                                \n\
+    }                                                                    \n\
+  }                                                                      \n\
+}                                                                        \n";
+
+
+/* The vertex shader code for the blending stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_blnd_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  gl_Position = vec4(VertexPosition,1.0f);                               \n\
+}                                                                        \n";
+
+/* The fragment shader code for the blending stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_blnd_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ >= 130                                                   \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform vec2 TexScale;                                                   \n\
+uniform sampler2D TexSamplerTemp;                                        \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec2 TexCoord = gl_FragCoord.xy*TexScale;                              \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = texture2D(TexSamplerTemp,TexCoord.st);                  \n\
+  if (gl_FragColor.a == 0.0f)                                            \n\
+    discard;                                                             \n\
+#else                                                                    \n\
+  FragColor = texture(TexSamplerTemp,TexCoord.st);                       \n\
+  if (FragColor.a == 0.0f)                                               \n\
+    discard;                                                             \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+
+/* The vertex shader code for the final stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_finl_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  gl_Position = vec4(VertexPosition,1.0f);                               \n\
+}                                                                        \n";
+
+/* The fragment shader code for the final stage of the dual depth
+   peeling algorithm. */
+static const GLchar *dp_finl_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ >= 130                                                   \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform vec2 TexScale;                                                   \n\
+uniform sampler2D TexSamplerFrontBlender;                                \n\
+uniform sampler2D TexSamplerBackBlender;                                 \n\
+uniform sampler2D TexSamplerOpaqueBlender;                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 transColor;                                                       \n\
+  vec2 TexCoord = gl_FragCoord.xy*TexScale;                              \n\
+#if __VERSION__ <= 120                                                   \n\
+  vec4 frontColor = texture2D(TexSamplerFrontBlender,TexCoord.st);       \n\
+  vec4 backColor = texture2D(TexSamplerBackBlender,TexCoord.st);         \n\
+  vec4 opaqueColor = texture2D(TexSamplerOpaqueBlender,TexCoord.st);     \n\
+#else                                                                    \n\
+  vec4 frontColor = texture(TexSamplerFrontBlender,TexCoord.st);         \n\
+  vec4 backColor = texture(TexSamplerBackBlender,TexCoord.st);           \n\
+  vec4 opaqueColor = texture(TexSamplerOpaqueBlender,TexCoord.st);       \n\
+#endif                                                                   \n\
+  frontColor.a = 1.0f-frontColor.a;                                      \n\
+  transColor.rgb = frontColor.rgb+backColor.rgb*frontColor.a;            \n\
+  transColor.a = (1.0f-frontColor.a*(1.0f-backColor.a));                 \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor.rgb = transColor.rgb+opaqueColor.rgb*(1.0f-transColor.a); \n\
+  gl_FragColor.a = transColor.a+opaqueColor.a*(1.0f-transColor.a);       \n\
+#else                                                                    \n\
+  FragColor.rgb = transColor.rgb+opaqueColor.rgb*(1.0f-transColor.a);    \n\
+  FragColor.a = transColor.a+opaqueColor.a*(1.0f-transColor.a);          \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+
+/* The vertex shader code for the initial stage of the weighted averaging
+   transparency algorithm. */
+static const GLchar *wa_init_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+attribute vec3 VertexNormal;                                             \n\
+attribute vec4 VertexColorF;                                             \n\
+attribute vec4 VertexColorB;                                             \n\
+attribute vec3 VertexTexCoord;                                           \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec3 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+in vec3 VertexNormal;                                                    \n\
+in vec4 VertexColorF;                                                    \n\
+in vec4 VertexColorB;                                                    \n\
+in vec3 VertexTexCoord;                                                  \n\
+out vec3 Normal;                                                         \n\
+out vec4 ColorF;                                                         \n\
+out vec4 ColorB;                                                         \n\
+out vec3 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  ColorF = VertexColorF;                                                 \n\
+  ColorB = VertexColorB;                                                 \n\
+  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;          \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexTexCoord;                                           \n\
+}                                                                        \n";
+
+/* The fragment shader code for the initial stage of the weighted averaging
+   transparency algorithm. */
+static const GLchar *wa_init_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec3 TexCoord;                                                   \n\
+#define FragData0 gl_FragData[0]                                         \n\
+#define FragData1 gl_FragData[1]                                         \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 ColorF;                                                          \n\
+in vec4 ColorB;                                                          \n\
+in vec3 TexCoord;                                                        \n\
+#if defined(GL_ES)                                                       \n\
+layout(location = 0) out vec4 FragData0;                                 \n\
+layout(location = 1) out vec4 FragData1;                                 \n\
+#elif __VERSION__ >= 150 && !defined(GL_compatibility_profile)           \n\
+out vec4 FragData[2];                                                    \n\
+#define FragData0 FragData[0]                                            \n\
+#define FragData1 FragData[1]                                            \n\
+#else                                                                    \n\
+#define FragData0 gl_FragData[0]                                         \n\
+#define FragData1 gl_FragData[1]                                         \n\
+#endif                                                                   \n\
+#endif                                                                   \n\
+                                                                         \n\
+const float M_PI_F  = 3.14159265359f;                                    \n\
+const float M_2PI_F = 6.28318530718f;                                    \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSamplerFront;                                   \n\
+uniform sampler2D TextureSamplerBack;                                    \n\
+uniform sampler2D TextureSamplerWater;                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec3 normalDirection;                                                  \n\
+  vec4 ambientColor, diffuseColor, sceneColor;                           \n\
+  vec4 ambientLighting, diffuseReflection, specularReflection, color;    \n\
+  vec3 normTexCoord;                                                     \n\
+  vec2 texCoor;                                                          \n\
+  float ndotl, ndoth, pf, lat, lon;                                      \n\
+                                                                         \n\
+  if (gl_FrontFacing)                                                    \n\
+  {                                                                      \n\
+    normalDirection = normalize(Normal);                                 \n\
+    sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;                   \n\
+    ambientColor = ColorF*MatFrontAmbient;                               \n\
+    diffuseColor = ColorF*MatFrontDiffuse;                               \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    normalDirection = -normalize(Normal);                                \n\
+    sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;                    \n\
+    ambientColor = ColorB*MatBackAmbient;                                \n\
+    diffuseColor = ColorB*MatBackDiffuse;                                \n\
+  }                                                                      \n\
+                                                                         \n\
+  ndotl = max(0.0f,dot(normalDirection,LtDirection));                    \n\
+  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));                   \n\
+  if (ndotl == 0.0f)                                                     \n\
+    pf = 0.0f;                                                           \n\
+  else                                                                   \n\
+    pf = pow(ndoth,MatShininess);                                        \n\
+  ambientLighting = ambientColor*LtAmbient;                              \n\
+  diffuseReflection = LtDiffuse*diffuseColor*ndotl;                      \n\
+  specularReflection = LtSpecular*MatSpecular*pf;                        \n\
+  color = sceneColor+ambientLighting+diffuseReflection;                  \n\
+  if (BoolTextures)                                                      \n\
+  {                                                                      \n\
+    normTexCoord = normalize(TexCoord);                                  \n\
+    lat = asin(normTexCoord.z);                                          \n\
+    lon = atan(normTexCoord.y,normTexCoord.x);                           \n\
+    texCoor = vec2(0.5f+lon/M_2PI_F,0.5f+lat/M_PI_F);                    \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSamplerFront,texCoor);                   \n\
+      specularReflection *= texture2D(TextureSamplerWater,texCoor);      \n\
+#else                                                                    \n\
+      color *= texture(TextureSamplerFront,texCoor);                     \n\
+      specularReflection *= texture(TextureSamplerWater,texCoor);        \n\
+#endif                                                                   \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSamplerBack,texCoor);                    \n\
+#else                                                                    \n\
+      color *= texture(TextureSamplerBack,texCoor);                      \n\
+#endif                                                                   \n\
+      specularReflection *= 0.0f;                                        \n\
+    }                                                                    \n\
+  }                                                                      \n\
+  color += specularReflection;                                           \n\
+  color = clamp(color,0.0f,1.0f);                                        \n\
+  color.a = diffuseColor.a;                                              \n\
+  FragData0 = vec4(color.rgb*color.a,color.a);                           \n\
+  FragData1 = vec4(1.0f);                                                \n\
+}                                                                        \n";
+
+
+/* The vertex shader code for the final stage of the weighted averaging
+   transparency algorithm. */
+static const GLchar *wa_finl_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  gl_Position = vec4(VertexPosition,1.0f);                               \n\
+}                                                                        \n";
+
+/* The fragment shader code for the final stage of the weighted averaging
+   transparency algorithm. */
+static const GLchar *wa_finl_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ >= 130                                                   \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform vec2 TexScale;                                                   \n\
+uniform sampler2D TexSamplerColorBlender;                                \n\
+uniform sampler2D TexSamplerNumBlender;                                  \n\
+uniform sampler2D TexSamplerOpaqueBlender;                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec2 TexCoord = gl_FragCoord.xy*TexScale;                              \n\
+#if __VERSION__ <= 120                                                   \n\
+  vec4 backColor = texture2D(TexSamplerOpaqueBlender,TexCoord.st);       \n\
+  vec4 sumColor = texture2D(TexSamplerColorBlender,TexCoord.st);         \n\
+  float n = texture2D(TexSamplerNumBlender,TexCoord.st).r;               \n\
+#else                                                                    \n\
+  vec4 backColor = texture(TexSamplerOpaqueBlender,TexCoord.st);         \n\
+  vec4 sumColor = texture(TexSamplerColorBlender,TexCoord.st);           \n\
+  float n = texture(TexSamplerNumBlender,TexCoord.st).r;                 \n\
+#endif                                                                   \n\
+  if (n == 0.0)                                                          \n\
+  {                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+    gl_FragColor = backColor;                                            \n\
+#else                                                                    \n\
+    FragColor = backColor;                                               \n\
+#endif                                                                   \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    vec3 avgColor = sumColor.rgb/sumColor.a;                             \n\
+    float avgAlpha = sumColor.a/n;                                       \n\
+    float t = pow(1.0f-avgAlpha,n);                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+    gl_FragColor.rgb = avgColor*(1.0f-t)+backColor.rgb*t;                \n\
+    gl_FragColor.a = 1.0f-t;                                             \n\
+#else                                                                    \n\
+    FragColor.rgb = avgColor*(1.0f-t)+backColor.rgb*t;                   \n\
+    FragColor.a = 1.0f-t;                                                \n\
+#endif                                                                   \n\
+  }                                                                      \n\
+}                                                                        \n";
 
 
 #endif /* HAVE_GLSL */
@@ -3459,6 +3374,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(ce->poly_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glUniformMatrix4fv(ce->poly_mv_index,1,GL_FALSE,mv_mat);
     glUniformMatrix4fv(ce->poly_proj_index,1,GL_FALSE,p_mat);
 
@@ -3658,6 +3576,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glBindBuffer(GL_ARRAY_BUFFER,0);
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     glDisable(GL_CULL_FACE);
@@ -3683,6 +3604,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(ce->poly_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glActiveTexture(GL_TEXTURE2);
     glBindTexture(GL_TEXTURE_2D,ce->tex_names[0]);
     glUniform1i(ce->poly_tex_samp_f_index,2);
@@ -3803,6 +3727,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     }
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     /* Initialize the dual depth peeling. */
@@ -3831,6 +3758,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(ce->dp_init_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D,ce->dp_opaque_depth_tex);
     glUniform1i(ce->dp_init_tex_samp_depth,0);
@@ -3849,6 +3779,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glDisableVertexAttribArray(ce->dp_init_pos_index);
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     /* Dual depth peeling and blending. */
@@ -3874,6 +3807,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
       glUseProgram(ce->dp_peel_shader_program);
 
+      if (ce->use_vao)
+        glBindVertexArray(ce->vertex_array_object);
+
       glActiveTexture(GL_TEXTURE0);
       glBindTexture(GL_TEXTURE_2D,ce->dp_depth_tex[prev]);
       glUniform1i(ce->dp_peel_tex_samp_depth_blend,0);
@@ -3971,6 +3907,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
       glBindBuffer(GL_ARRAY_BUFFER,0);
 
+      if (ce->use_vao)
+        glBindVertexArray(0);
+
       glUseProgram(0);
 
       glBindFramebuffer(GL_FRAMEBUFFER,ce->dp_back_blender_fbo);
@@ -3986,6 +3925,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
       glUseProgram(ce->dp_blnd_shader_program);
 
+      if (ce->use_vao)
+        glBindVertexArray(ce->vertex_array_object);
+
       glActiveTexture(GL_TEXTURE0);
       glBindTexture(GL_TEXTURE_2D,ce->dp_back_temp_tex[curr]);
       glUniform1i(ce->dp_blnd_tex_samp_temp,0);
@@ -4003,6 +3945,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
       glDisableVertexAttribArray(ce->dp_blnd_pos_index);
 
+      if (ce->use_vao)
+        glBindVertexArray(0);
+
       glUseProgram(0);
 
 #ifdef HAVE_JWZGLES
@@ -4029,6 +3974,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(ce->dp_finl_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glActiveTexture(GL_TEXTURE1);
     glBindTexture(GL_TEXTURE_2D,ce->dp_front_blender_tex[curr]);
     glUniform1i(ce->dp_finl_tex_samp_front,1);
@@ -4052,6 +4000,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glBindBuffer(GL_ARRAY_BUFFER,0);
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     glDisable(GL_CULL_FACE);
@@ -4077,6 +4028,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(ce->poly_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glActiveTexture(GL_TEXTURE2);
     glBindTexture(GL_TEXTURE_2D,ce->tex_names[0]);
     glUniform1i(ce->poly_tex_samp_f_index,2);
@@ -4197,6 +4151,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     }
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     /* Accumulate colors and depth complexity. */
@@ -4215,6 +4172,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(ce->wa_init_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glUniformMatrix4fv(ce->wa_init_proj_index,1,GL_FALSE,p_mat);
 
     glUniform4fv(ce->wa_init_front_ambient_index,1,mat_diff_white);
@@ -4295,6 +4255,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glBindBuffer(GL_ARRAY_BUFFER,0);
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     glDisable(GL_BLEND);
@@ -4310,6 +4273,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 #endif
     glUseProgram(ce->wa_finl_shader_program);
 
+    if (ce->use_vao)
+      glBindVertexArray(ce->vertex_array_object);
+
     glActiveTexture(GL_TEXTURE1);
     glBindTexture(GL_TEXTURE_2D,ce->wa_color_tex);
     glUniform1i(ce->wa_finl_tex_samp_color,1);
@@ -4335,6 +4301,9 @@ static int cuboctahedron_eversion_pf(ModeInfo *mi)
 
     glUseProgram(0);
 
+    if (ce->use_vao)
+      glBindVertexArray(0);
+
     glDisable(GL_CULL_FACE);
     glEnable(GL_DEPTH_TEST);
     glDepthFunc(GL_LESS);
@@ -4673,20 +4642,20 @@ static void init_glsl(ModeInfo *mi)
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
   const char *gl_ext;
-  const GLchar *poly_vertex_shader_source[3];
-  const GLchar *poly_fragment_shader_source[4];
-  const GLchar *dp_init_vertex_shader_source[3];
-  const GLchar *dp_init_fragment_shader_source[4];
-  const GLchar *dp_peel_vertex_shader_source[3];
-  const GLchar *dp_peel_fragment_shader_source[7];
-  const GLchar *dp_blnd_vertex_shader_source[3];
-  const GLchar *dp_blnd_fragment_shader_source[4];
-  const GLchar *dp_finl_vertex_shader_source[3];
-  const GLchar *dp_finl_fragment_shader_source[4];
-  const GLchar *wa_init_vertex_shader_source[3];
-  const GLchar *wa_init_fragment_shader_source[4];
-  const GLchar *wa_finl_vertex_shader_source[3];
-  const GLchar *wa_finl_fragment_shader_source[4];
+  const GLchar *poly_vertex_shader_source[2];
+  const GLchar *poly_fragment_shader_source[2];
+  const GLchar *dp_init_vertex_shader_source[2];
+  const GLchar *dp_init_fragment_shader_source[2];
+  const GLchar *dp_peel_vertex_shader_source[2];
+  const GLchar *dp_peel_fragment_shader_source[2];
+  const GLchar *dp_blnd_vertex_shader_source[2];
+  const GLchar *dp_blnd_fragment_shader_source[2];
+  const GLchar *dp_finl_vertex_shader_source[2];
+  const GLchar *dp_finl_fragment_shader_source[2];
+  const GLchar *wa_init_vertex_shader_source[2];
+  const GLchar *wa_init_fragment_shader_source[2];
+  const GLchar *wa_finl_vertex_shader_source[2];
+  const GLchar *wa_finl_fragment_shader_source[2];
   static const GLfloat quad_verts[] =
   {
     -1.0f, -1.0f,
@@ -4698,6 +4667,7 @@ static void init_glsl(ModeInfo *mi)
   /* Determine whether to use shaders to render the cuboctahedron eversion. */
   ce->use_shaders = False;
   ce->use_mipmaps = False;
+  ce->use_vao = False;
   ce->poly_shader_program = 0;
   ce->dp_init_shader_program = 0;
   ce->dp_peel_shader_program = 0;
@@ -4710,204 +4680,43 @@ static void init_glsl(ModeInfo *mi)
                                  &gl_gles3))
     return;
 
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      poly_vertex_shader_source[0] = shader_version_2_1;
-      poly_vertex_shader_source[1] = poly_vertex_shader_attribs_2_1;
-      poly_vertex_shader_source[2] = poly_vertex_shader_main;
-      poly_fragment_shader_source[0] = shader_version_2_1;
-      poly_fragment_shader_source[1] = poly_fragment_shader_attribs_2_1;
-      poly_fragment_shader_source[2] = poly_fragment_shader_main;
-      poly_fragment_shader_source[3] = poly_fragment_shader_out_2_1;
-
-      dp_init_vertex_shader_source[0] = shader_version_2_1;
-      dp_init_vertex_shader_source[1] = dp_init_vertex_shader_attribs_2_1;
-      dp_init_vertex_shader_source[2] = dp_init_vertex_shader_main;
-      dp_init_fragment_shader_source[0] = shader_version_2_1;
-      dp_init_fragment_shader_source[1] = dp_init_fragment_shader_attribs_2_1;
-      dp_init_fragment_shader_source[2] = dp_init_fragment_shader_main;
-      dp_init_fragment_shader_source[3] = dp_init_fragment_shader_out_2_1;
-
-      dp_peel_vertex_shader_source[0] = shader_version_2_1;
-      dp_peel_vertex_shader_source[1] = dp_peel_vertex_shader_attribs_2_1;
-      dp_peel_vertex_shader_source[2] = dp_peel_vertex_shader_main;
-      dp_peel_fragment_shader_source[0] = shader_version_2_1;
-      dp_peel_fragment_shader_source[1] = dp_peel_fragment_shader_attribs_2_1;
-      dp_peel_fragment_shader_source[2] = dp_peel_fragment_shader_main;
-      dp_peel_fragment_shader_source[3] = dp_peel_fragment_shader_peel_2_1;
-      dp_peel_fragment_shader_source[4] = dp_peel_fragment_shader_col;
-      dp_peel_fragment_shader_source[5] = dp_peel_fragment_shader_col_2_1;
-      dp_peel_fragment_shader_source[6] = dp_peel_fragment_shader_out_2_1;
-
-      dp_blnd_vertex_shader_source[0] = shader_version_2_1;
-      dp_blnd_vertex_shader_source[1] = dp_blnd_vertex_shader_attribs_2_1;
-      dp_blnd_vertex_shader_source[2] = dp_blnd_vertex_shader_main;
-      dp_blnd_fragment_shader_source[0] = shader_version_2_1;
-      dp_blnd_fragment_shader_source[1] = dp_blnd_fragment_shader_attribs_2_1;
-      dp_blnd_fragment_shader_source[2] = dp_blnd_fragment_shader_main;
-      dp_blnd_fragment_shader_source[3] = dp_blnd_fragment_shader_out_2_1;
-
-      dp_finl_vertex_shader_source[0] = shader_version_2_1;
-      dp_finl_vertex_shader_source[1] = dp_finl_vertex_shader_attribs_2_1;
-      dp_finl_vertex_shader_source[2] = dp_finl_vertex_shader_main;
-      dp_finl_fragment_shader_source[0] = shader_version_2_1;
-      dp_finl_fragment_shader_source[1] = dp_finl_fragment_shader_attribs_2_1;
-      dp_finl_fragment_shader_source[2] = dp_finl_fragment_shader_main;
-      dp_finl_fragment_shader_source[3] = dp_finl_fragment_shader_out_2_1;
-
-      wa_init_vertex_shader_source[0] = shader_version_2_1;
-      wa_init_vertex_shader_source[1] = wa_init_vertex_shader_attribs_2_1;
-      wa_init_vertex_shader_source[2] = wa_init_vertex_shader_main;
-      wa_init_fragment_shader_source[0] = shader_version_2_1;
-      wa_init_fragment_shader_source[1] = wa_init_fragment_shader_attribs_2_1;
-      wa_init_fragment_shader_source[2] = wa_init_fragment_shader_main;
-      wa_init_fragment_shader_source[3] = wa_init_fragment_shader_out_2_1;
-
-      wa_finl_vertex_shader_source[0] = shader_version_2_1;
-      wa_finl_vertex_shader_source[1] = wa_finl_vertex_shader_attribs_2_1;
-      wa_finl_vertex_shader_source[2] = wa_finl_vertex_shader_main;
-      wa_finl_fragment_shader_source[0] = shader_version_2_1;
-      wa_finl_fragment_shader_source[1] = wa_finl_fragment_shader_attribs_2_1;
-      wa_finl_fragment_shader_source[2] = wa_finl_fragment_shader_main;
-      wa_finl_fragment_shader_source[3] = wa_finl_fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      poly_vertex_shader_source[0] = shader_version_3_0;
-      poly_vertex_shader_source[1] = poly_vertex_shader_attribs_3_0;
-      poly_vertex_shader_source[2] = poly_vertex_shader_main;
-      poly_fragment_shader_source[0] = shader_version_3_0;
-      poly_fragment_shader_source[1] = poly_fragment_shader_attribs_3_0;
-      poly_fragment_shader_source[2] = poly_fragment_shader_main;
-      poly_fragment_shader_source[3] = poly_fragment_shader_out_3_0;
-
-      dp_init_vertex_shader_source[0] = shader_version_3_0;
-      dp_init_vertex_shader_source[1] = dp_init_vertex_shader_attribs_3_0;
-      dp_init_vertex_shader_source[2] = dp_init_vertex_shader_main;
-      dp_init_fragment_shader_source[0] = shader_version_3_0;
-      dp_init_fragment_shader_source[1] = dp_init_fragment_shader_attribs_3_0;
-      dp_init_fragment_shader_source[2] = dp_init_fragment_shader_main;
-      dp_init_fragment_shader_source[3] = dp_init_fragment_shader_out_3_0;
-
-      dp_peel_vertex_shader_source[0] = shader_version_3_0;
-      dp_peel_vertex_shader_source[1] = dp_peel_vertex_shader_attribs_3_0;
-      dp_peel_vertex_shader_source[2] = dp_peel_vertex_shader_main;
-      dp_peel_fragment_shader_source[0] = shader_version_3_0;
-      dp_peel_fragment_shader_source[1] = dp_peel_fragment_shader_attribs_3_0;
-      dp_peel_fragment_shader_source[2] = dp_peel_fragment_shader_main;
-      dp_peel_fragment_shader_source[3] = dp_peel_fragment_shader_peel_3_0;
-      dp_peel_fragment_shader_source[4] = dp_peel_fragment_shader_col;
-      dp_peel_fragment_shader_source[5] = dp_peel_fragment_shader_col_3_0;
-      dp_peel_fragment_shader_source[6] = dp_peel_fragment_shader_out_3_0;
-
-      dp_blnd_vertex_shader_source[0] = shader_version_3_0;
-      dp_blnd_vertex_shader_source[1] = dp_blnd_vertex_shader_attribs_3_0;
-      dp_blnd_vertex_shader_source[2] = dp_blnd_vertex_shader_main;
-      dp_blnd_fragment_shader_source[0] = shader_version_3_0;
-      dp_blnd_fragment_shader_source[1] = dp_blnd_fragment_shader_attribs_3_0;
-      dp_blnd_fragment_shader_source[2] = dp_blnd_fragment_shader_main;
-      dp_blnd_fragment_shader_source[3] = dp_blnd_fragment_shader_out_3_0;
-
-      dp_finl_vertex_shader_source[0] = shader_version_3_0;
-      dp_finl_vertex_shader_source[1] = dp_finl_vertex_shader_attribs_3_0;
-      dp_finl_vertex_shader_source[2] = dp_finl_vertex_shader_main;
-      dp_finl_fragment_shader_source[0] = shader_version_3_0;
-      dp_finl_fragment_shader_source[1] = dp_finl_fragment_shader_attribs_3_0;
-      dp_finl_fragment_shader_source[2] = dp_finl_fragment_shader_main;
-      dp_finl_fragment_shader_source[3] = dp_finl_fragment_shader_out_3_0;
-
-      wa_init_vertex_shader_source[0] = shader_version_3_0;
-      wa_init_vertex_shader_source[1] = wa_init_vertex_shader_attribs_3_0;
-      wa_init_vertex_shader_source[2] = wa_init_vertex_shader_main;
-      wa_init_fragment_shader_source[0] = shader_version_3_0;
-      wa_init_fragment_shader_source[1] = wa_init_fragment_shader_attribs_3_0;
-      wa_init_fragment_shader_source[2] = wa_init_fragment_shader_main;
-      wa_init_fragment_shader_source[3] = wa_init_fragment_shader_out_3_0;
-
-      wa_finl_vertex_shader_source[0] = shader_version_3_0;
-      wa_finl_vertex_shader_source[1] = wa_finl_vertex_shader_attribs_3_0;
-      wa_finl_vertex_shader_source[2] = wa_finl_vertex_shader_main;
-      wa_finl_fragment_shader_source[0] = shader_version_3_0;
-      wa_finl_fragment_shader_source[1] = wa_finl_fragment_shader_attribs_3_0;
-      wa_finl_fragment_shader_source[2] = wa_finl_fragment_shader_main;
-      wa_finl_fragment_shader_source[3] = wa_finl_fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    poly_vertex_shader_source[0] = shader_version_3_0_es;
-    poly_vertex_shader_source[1] = poly_vertex_shader_attribs_3_0;
-    poly_vertex_shader_source[2] = poly_vertex_shader_main;
-    poly_fragment_shader_source[0] = shader_version_3_0_es;
-    poly_fragment_shader_source[1] = poly_fragment_shader_attribs_3_0;
-    poly_fragment_shader_source[2] = poly_fragment_shader_main;
-    poly_fragment_shader_source[3] = poly_fragment_shader_out_3_0;
-
-    dp_init_vertex_shader_source[0] = shader_version_3_0_es;
-    dp_init_vertex_shader_source[1] = dp_init_vertex_shader_attribs_3_0;
-    dp_init_vertex_shader_source[2] = dp_init_vertex_shader_main;
-    dp_init_fragment_shader_source[0] = shader_version_3_0_es;
-    dp_init_fragment_shader_source[1] = dp_init_fragment_shader_attribs_3_0;
-    dp_init_fragment_shader_source[2] = dp_init_fragment_shader_main;
-    dp_init_fragment_shader_source[3] = dp_init_fragment_shader_out_3_0;
-
-    dp_peel_vertex_shader_source[0] = shader_version_3_0_es;
-    dp_peel_vertex_shader_source[1] = dp_peel_vertex_shader_attribs_3_0;
-    dp_peel_vertex_shader_source[2] = dp_peel_vertex_shader_main;
-    dp_peel_fragment_shader_source[0] = shader_version_3_0_es;
-    dp_peel_fragment_shader_source[1] = dp_peel_fragment_shader_attribs_3_0_es;
-    dp_peel_fragment_shader_source[2] = dp_peel_fragment_shader_main;
-    dp_peel_fragment_shader_source[3] = dp_peel_fragment_shader_peel_3_0_es;
-    dp_peel_fragment_shader_source[4] = dp_peel_fragment_shader_col;
-    dp_peel_fragment_shader_source[5] = dp_peel_fragment_shader_col_3_0;
-    dp_peel_fragment_shader_source[6] = dp_peel_fragment_shader_out_3_0_es;
-
-    dp_blnd_vertex_shader_source[0] = shader_version_3_0_es;
-    dp_blnd_vertex_shader_source[1] = dp_blnd_vertex_shader_attribs_3_0;
-    dp_blnd_vertex_shader_source[2] = dp_blnd_vertex_shader_main;
-    dp_blnd_fragment_shader_source[0] = shader_version_3_0_es;
-    dp_blnd_fragment_shader_source[1] = dp_blnd_fragment_shader_attribs_3_0;
-    dp_blnd_fragment_shader_source[2] = dp_blnd_fragment_shader_main;
-    dp_blnd_fragment_shader_source[3] = dp_blnd_fragment_shader_out_3_0;
-
-    dp_finl_vertex_shader_source[0] = shader_version_3_0_es;
-    dp_finl_vertex_shader_source[1] = dp_finl_vertex_shader_attribs_3_0;
-    dp_finl_vertex_shader_source[2] = dp_finl_vertex_shader_main;
-    dp_finl_fragment_shader_source[0] = shader_version_3_0_es;
-    dp_finl_fragment_shader_source[1] = dp_finl_fragment_shader_attribs_3_0;
-    dp_finl_fragment_shader_source[2] = dp_finl_fragment_shader_main;
-    dp_finl_fragment_shader_source[3] = dp_finl_fragment_shader_out_3_0;
-
-    wa_init_vertex_shader_source[0] = shader_version_3_0_es;
-    wa_init_vertex_shader_source[1] = wa_init_vertex_shader_attribs_3_0;
-    wa_init_vertex_shader_source[2] = wa_init_vertex_shader_main;
-    wa_init_fragment_shader_source[0] = shader_version_3_0_es;
-    wa_init_fragment_shader_source[1] = wa_init_fragment_shader_attribs_3_0_es;
-    wa_init_fragment_shader_source[2] = wa_init_fragment_shader_main;
-    wa_init_fragment_shader_source[3] = wa_init_fragment_shader_out_3_0_es;
-
-    wa_finl_vertex_shader_source[0] = shader_version_3_0_es;
-    wa_finl_vertex_shader_source[1] = wa_finl_vertex_shader_attribs_3_0;
-    wa_finl_vertex_shader_source[2] = wa_finl_vertex_shader_main;
-    wa_finl_fragment_shader_source[0] = shader_version_3_0_es;
-    wa_finl_fragment_shader_source[1] = wa_finl_fragment_shader_attribs_3_0;
-    wa_finl_fragment_shader_source[2] = wa_finl_fragment_shader_main;
-    wa_finl_fragment_shader_source[3] = wa_finl_fragment_shader_out_3_0;
-  }
-
-  if (!glsl_CompileAndLinkShaders(3,poly_vertex_shader_source,
-                                  4,poly_fragment_shader_source,
+  poly_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  poly_vertex_shader_source[1] = poly_vertex_shader;
+  poly_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  poly_fragment_shader_source[1] = poly_fragment_shader;
+
+  dp_init_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_init_vertex_shader_source[1] = dp_init_vertex_shader;
+  dp_init_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_init_fragment_shader_source[1] = dp_init_fragment_shader;
+
+  dp_peel_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_peel_vertex_shader_source[1] = dp_peel_vertex_shader;
+  dp_peel_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_peel_fragment_shader_source[1] = dp_peel_fragment_shader;
+
+  dp_blnd_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_blnd_vertex_shader_source[1] = dp_blnd_vertex_shader;
+  dp_blnd_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_blnd_fragment_shader_source[1] = dp_blnd_fragment_shader;
+
+  dp_finl_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_finl_vertex_shader_source[1] = dp_finl_vertex_shader;
+  dp_finl_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  dp_finl_fragment_shader_source[1] = dp_finl_fragment_shader;
+
+  wa_init_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  wa_init_vertex_shader_source[1] = wa_init_vertex_shader;
+  wa_init_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  wa_init_fragment_shader_source[1] = wa_init_fragment_shader;
+
+  wa_finl_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  wa_finl_vertex_shader_source[1] = wa_finl_vertex_shader;
+  wa_finl_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  wa_finl_fragment_shader_source[1] = wa_finl_fragment_shader;
+
+  if (!glsl_CompileAndLinkShaders(2,poly_vertex_shader_source,
+                                  2,poly_fragment_shader_source,
                                   &ce->poly_shader_program))
     return;
 
@@ -5001,8 +4810,8 @@ static void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&ce->self_index_buffer);
 
   /* Initialize dual depth peeling data. */
-  if (!glsl_CompileAndLinkShaders(3,dp_init_vertex_shader_source,
-                                  4,dp_init_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,dp_init_vertex_shader_source,
+                                  2,dp_init_fragment_shader_source,
                                   &ce->dp_init_shader_program))
   {
     glDeleteProgram(ce->poly_shader_program);
@@ -5030,8 +4839,8 @@ static void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!glsl_CompileAndLinkShaders(3,dp_peel_vertex_shader_source,
-                                  7,dp_peel_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,dp_peel_vertex_shader_source,
+                                  2,dp_peel_fragment_shader_source,
                                   &ce->dp_peel_shader_program))
   {
     glDeleteProgram(ce->poly_shader_program);
@@ -5123,8 +4932,8 @@ static void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!glsl_CompileAndLinkShaders(3,dp_blnd_vertex_shader_source,
-                                  4,dp_blnd_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,dp_blnd_vertex_shader_source,
+                                  2,dp_blnd_fragment_shader_source,
                                   &ce->dp_blnd_shader_program))
   {
     glDeleteProgram(ce->poly_shader_program);
@@ -5150,8 +4959,8 @@ static void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!glsl_CompileAndLinkShaders(3,dp_finl_vertex_shader_source,
-                                  4,dp_finl_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,dp_finl_vertex_shader_source,
+                                  2,dp_finl_fragment_shader_source,
                                   &ce->dp_finl_shader_program))
   {
     glDeleteProgram(ce->poly_shader_program);
@@ -5187,8 +4996,8 @@ static void init_glsl(ModeInfo *mi)
 
   glGenQueries(1,&ce->dp_query);
 
-  if (!glsl_CompileAndLinkShaders(3,wa_init_vertex_shader_source,
-                                  4,wa_init_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,wa_init_vertex_shader_source,
+                                  2,wa_init_fragment_shader_source,
                                   &ce->wa_init_shader_program))
     return;
 
@@ -5270,8 +5079,8 @@ static void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!glsl_CompileAndLinkShaders(3,wa_finl_vertex_shader_source,
-                                  4,wa_finl_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,wa_finl_vertex_shader_source,
+                                  2,wa_finl_fragment_shader_source,
                                   &ce->wa_finl_shader_program))
   {
     glDeleteProgram(ce->poly_shader_program);
@@ -5315,6 +5124,10 @@ static void init_glsl(ModeInfo *mi)
   glBufferData(GL_ARRAY_BUFFER,sizeof(quad_verts),quad_verts,GL_STATIC_DRAW);
   glBindBuffer(GL_ARRAY_BUFFER,0);
 
+  ce->use_vao = glsl_IsCoreProfile();
+  if (ce->use_vao)
+    glGenVertexArrays(1,&ce->vertex_array_object);
+
   ce->use_shaders = True;
   if (!gl_gles3 && gl_major < 3)
   {
@@ -5831,6 +5644,8 @@ ENTRYPOINT void free_cubocteversion(ModeInfo *mi)
     glDeleteBuffers(1,&ce->self_index_buffer);
     glDeleteBuffers(1,&ce->quad_buffer);
     glDeleteQueries(1,&ce->dp_query);
+    if (ce->use_vao)
+      glDeleteVertexArrays(1,&ce->vertex_array_object);
     delete_dual_peeling_render_targets(mi);
     delete_weighted_average_render_targets(mi);
   }
diff --git a/hacks/glx/elementalring.man b/hacks/glx/elementalring.man
new file mode 100644 (file)
index 0000000..0a737da
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+elementalring \- screen saver.
+.SH SYNOPSIS
+.B elementalring
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+A rotating ring knots and un-knots itself. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/MsVXDt
+.SH COPYRIGHT
+Copyright \(co 2016 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
index ec4ca8c0eabd47e614305d53d47d12f69c6412d9..cc4a3d09a2eb4bf09e3c836b45c781d8b4b74435 100644 (file)
@@ -7,7 +7,7 @@
 static const char sccsid[] = "@(#)etruscanvenus.c  1.1 05/01/20 xlockmore";
 #endif
 
-/* Copyright (c) 2019-2021 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2019-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -26,6 +26,7 @@ static const char sccsid[] = "@(#)etruscanvenus.c  1.1 05/01/20 xlockmore";
  * C. Steger - 05/01/20: Initial version
  * C. Steger - 20/12/20: Added per-fragment shading
  * C. Steger - 20/12/30: Make the shader code work under macOS and iOS
+ * C. Steger - 25/12/31: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -362,7 +363,7 @@ typedef struct {
 #ifdef HAVE_GLSL
   GLfloat *uv;
   GLuint *indices;
-  Bool use_shaders, buffers_initialized;
+  Bool use_shaders, buffers_initialized, use_vao;
   GLuint shader_program;
   GLint vertex_uv_index, vertex_t_index, color_index;
   GLint mat_mv_index, mat_p_index, db_index, dl_index;
@@ -376,6 +377,7 @@ typedef struct {
   GLint texture_sampler_index;
   GLuint vertex_uv_buffer, vertex_t_buffer;
   GLuint color_buffer, indices_buffer;
+  GLuint vertex_array_object;
   GLint ni, ne, nt;
 #endif /* HAVE_GLSL */
 } etruscanvenusstruct;
@@ -385,211 +387,208 @@ static etruscanvenusstruct *etruscanvenus = (etruscanvenusstruct *) NULL;
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexUV;\n"
-  "attribute vec4 VertexT;\n"
-  "attribute vec4 VertexColor;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec3 VertexUV;\n"
-  "in vec4 VertexT;\n"
-  "in vec4 VertexColor;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "out vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform float DB;\n"
-  "uniform float DL;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  const float EPSILON = 1.19e-6f;\n"
-  "  const float M_SQRT2 = 1.41421356237f;\n"
-  "  float u = VertexUV.x;\n"
-  "  float v = VertexUV.y;\n"
-  "  float bosqrt2 = DB/M_SQRT2;\n"
-  "  float b2osqrt2 = 2.0f*bosqrt2;\n"
-  "  float b3osqrt2 = 3.0f*bosqrt2;\n"
-  "  float cu = cos(u);\n"
-  "  float su = sin(u);\n"
-  "  float c2u = cos(2.0f*u);\n"
-  "  float s2u = sin(2.0f*u);\n"
-  "  float c3u = cos(3.0f*u);\n"
-  "  float s3u = sin(3.0f*u);\n"
-  "  float cv = cos(v);\n"
-  "  float sv = sin(v);\n"
-  "  float c2v = cos(2.0f*v);\n"
-  "  float s2v = sin(2.0f*v);\n"
-  "  float nom = (1.0f-DL+DL*cv);\n"
-  "  float den = (1.0f-bosqrt2*s3u*s2v);\n"
-  "  float f = nom/den;\n"
-  "  float fx = c2u*cv+cu*sv;\n"
-  "  float fy = s2u*cv-su*sv;\n"
-  "  float fz = M_SQRT2*cv;\n"
-  "  vec3 x = f*vec3(fx,fy,fz);\n"
-  "  float nomv = -DL*sv;\n"
-  "  float denu = -b3osqrt2*c3u*s2v;\n"
-  "  float denv = -b2osqrt2*s3u*c2v;\n"
-  "  float den2 = 1.0f/(den*den);\n"
-  "  float fu = -nom*denu*den2;\n"
-  "  float fv = (den*nomv-nom*denv)*den2;\n"
-  "  float fxu = -su*sv-2.0f*s2u*cv;\n"
-  "  float fxv = cu*cv-c2u*sv;\n"
-  "  float fyu = 2.0f*c2u*cv-cu*sv;\n"
-  "  float fyv = -s2u*sv-su*cv;\n"
-  "  float fzv = -M_SQRT2*sv;\n"
-  "  vec3 xu = vec3(fu*fx+f*fxu,fu*fy+f*fyu,fu*fz);\n"
-  "  vec3 xv = vec3(fv*fx+f*fxv,fv*fy+f*fyv,fv*fz+f*fzv);\n"
-  "  vec3 n = cross(xu,xv);\n"
-  "  float t = length(n);\n"
-  "  if (t < EPSILON)\n"
-  "  {\n"
-  "    u += 0.01f;\n"
-  "    v += 0.01f;\n"
-  "    cu = cos(u);\n"
-  "    su = sin(u);\n"
-  "    c2u = cos(2.0f*u);\n"
-  "    s2u = sin(2.0f*u);\n"
-  "    c3u = cos(3.0f*u);\n"
-  "    s3u = sin(3.0f*u);\n"
-  "    cv = cos(v);\n"
-  "    sv = sin(v);\n"
-  "    c2v = cos(2.0f*v);\n"
-  "    s2v = sin(2.0f*v);\n"
-  "    nom = (1.0f-DL+DL*cv);\n"
-  "    den = (1.0f-bosqrt2*s3u*s2v);\n"
-  "    f = nom/den;\n"
-  "    fx = c2u*cv+cu*sv;\n"
-  "    fy = s2u*cv-su*sv;\n"
-  "    fz = M_SQRT2*cv;\n"
-  "    nomv = -DL*sv;\n"
-  "    denu = -b3osqrt2*c3u*s2v;\n"
-  "    denv = -b2osqrt2*s3u*c2v;\n"
-  "    den2 = 1.0f/(den*den);\n"
-  "    fu = -nom*denu*den2;\n"
-  "    fv = (den*nomv-nom*denv)*den2;\n"
-  "    fxu = -su*sv-2.0f*s2u*cv;\n"
-  "    fxv = cu*cv-c2u*sv;\n"
-  "    fyu = 2.0f*c2u*cv-cu*sv;\n"
-  "    fyv = -s2u*sv-su*cv;\n"
-  "    fzv = -M_SQRT2*sv;\n"
-  "    xu = vec3(fu*fx+f*fxu,fu*fy+f*fyu,fu*fz);\n"
-  "    xv = vec3(fv*fx+f*fxv,fv*fy+f*fyv,fv*fz+f*fzv);\n"
-  "  }\n"
-  "  vec4 Position = MatModelView*vec4(x,1.0f);\n"
-  "  vec4 pu = MatModelView*vec4(xu,0.0f);\n"
-  "  vec4 pv = MatModelView*vec4(xv,0.0f);\n"
-  "  Normal = normalize(cross(pu.xyz,pv.xyz));\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  Color = VertexColor;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexT;\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexUV;                                                 \n\
+attribute vec4 VertexT;                                                  \n\
+attribute vec4 VertexColor;                                              \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 VertexUV;                                                        \n\
+in vec4 VertexT;                                                         \n\
+in vec4 VertexColor;                                                     \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+out vec4 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform float DB;                                                        \n\
+uniform float DL;                                                        \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  const float EPSILON = 1.19e-6f;                                        \n\
+  const float M_SQRT2 = 1.41421356237f;                                  \n\
+  float u = VertexUV.x;                                                  \n\
+  float v = VertexUV.y;                                                  \n\
+  float bosqrt2 = DB/M_SQRT2;                                            \n\
+  float b2osqrt2 = 2.0f*bosqrt2;                                         \n\
+  float b3osqrt2 = 3.0f*bosqrt2;                                         \n\
+  float cu = cos(u);                                                     \n\
+  float su = sin(u);                                                     \n\
+  float c2u = cos(2.0f*u);                                               \n\
+  float s2u = sin(2.0f*u);                                               \n\
+  float c3u = cos(3.0f*u);                                               \n\
+  float s3u = sin(3.0f*u);                                               \n\
+  float cv = cos(v);                                                     \n\
+  float sv = sin(v);                                                     \n\
+  float c2v = cos(2.0f*v);                                               \n\
+  float s2v = sin(2.0f*v);                                               \n\
+  float nom = (1.0f-DL+DL*cv);                                           \n\
+  float den = (1.0f-bosqrt2*s3u*s2v);                                    \n\
+  float f = nom/den;                                                     \n\
+  float fx = c2u*cv+cu*sv;                                               \n\
+  float fy = s2u*cv-su*sv;                                               \n\
+  float fz = M_SQRT2*cv;                                                 \n\
+  vec3 x = f*vec3(fx,fy,fz);                                             \n\
+  float nomv = -DL*sv;                                                   \n\
+  float denu = -b3osqrt2*c3u*s2v;                                        \n\
+  float denv = -b2osqrt2*s3u*c2v;                                        \n\
+  float den2 = 1.0f/(den*den);                                           \n\
+  float fu = -nom*denu*den2;                                             \n\
+  float fv = (den*nomv-nom*denv)*den2;                                   \n\
+  float fxu = -su*sv-2.0f*s2u*cv;                                        \n\
+  float fxv = cu*cv-c2u*sv;                                              \n\
+  float fyu = 2.0f*c2u*cv-cu*sv;                                         \n\
+  float fyv = -s2u*sv-su*cv;                                             \n\
+  float fzv = -M_SQRT2*sv;                                               \n\
+  vec3 xu = vec3(fu*fx+f*fxu,fu*fy+f*fyu,fu*fz);                         \n\
+  vec3 xv = vec3(fv*fx+f*fxv,fv*fy+f*fyv,fv*fz+f*fzv);                   \n\
+  vec3 n = cross(xu,xv);                                                 \n\
+  float t = length(n);                                                   \n\
+  if (t < EPSILON)                                                       \n\
+  {                                                                      \n\
+    u += 0.01f;                                                          \n\
+    v += 0.01f;                                                          \n\
+    cu = cos(u);                                                         \n\
+    su = sin(u);                                                         \n\
+    c2u = cos(2.0f*u);                                                   \n\
+    s2u = sin(2.0f*u);                                                   \n\
+    c3u = cos(3.0f*u);                                                   \n\
+    s3u = sin(3.0f*u);                                                   \n\
+    cv = cos(v);                                                         \n\
+    sv = sin(v);                                                         \n\
+    c2v = cos(2.0f*v);                                                   \n\
+    s2v = sin(2.0f*v);                                                   \n\
+    nom = (1.0f-DL+DL*cv);                                               \n\
+    den = (1.0f-bosqrt2*s3u*s2v);                                        \n\
+    f = nom/den;                                                         \n\
+    fx = c2u*cv+cu*sv;                                                   \n\
+    fy = s2u*cv-su*sv;                                                   \n\
+    fz = M_SQRT2*cv;                                                     \n\
+    nomv = -DL*sv;                                                       \n\
+    denu = -b3osqrt2*c3u*s2v;                                            \n\
+    denv = -b2osqrt2*s3u*c2v;                                            \n\
+    den2 = 1.0f/(den*den);                                               \n\
+    fu = -nom*denu*den2;                                                 \n\
+    fv = (den*nomv-nom*denv)*den2;                                       \n\
+    fxu = -su*sv-2.0f*s2u*cv;                                            \n\
+    fxv = cu*cv-c2u*sv;                                                  \n\
+    fyu = 2.0f*c2u*cv-cu*sv;                                             \n\
+    fyv = -s2u*sv-su*cv;                                                 \n\
+    fzv = -M_SQRT2*sv;                                                   \n\
+    xu = vec3(fu*fx+f*fxu,fu*fy+f*fyu,fu*fz);                            \n\
+    xv = vec3(fv*fx+f*fxv,fv*fy+f*fyv,fv*fz+f*fzv);                      \n\
+  }                                                                      \n\
+  vec4 Position = MatModelView*vec4(x,1.0f);                             \n\
+  vec4 pu = MatModelView*vec4(xu,0.0f);                                  \n\
+  vec4 pv = MatModelView*vec4(xv,0.0f);                                  \n\
+  Normal = normalize(cross(pu.xyz,pv.xyz));                              \n\
+  gl_Position = MatProj*Position;                                        \n\
+  Color = VertexColor;                                                   \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexT;                                                  \n\
+}                                                                        \n";
 
 /* The fragment shader code is composed of code fragments that depend on
    the OpenGL version and code fragments that are version-independent.
    They are concatenated by glsl_CompileAndLinkShaders in the function
    init_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "in vec4 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  "uniform bool DrawLines;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSampler;"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 color;\n"
-  "  if (DrawLines)\n"
-  "  {\n"
-  "    color = Color;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 normalDirection;\n"
-  "    vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "    vec4 ambientLighting, diffuseReflection, specularReflection;\n"
-  "    float ndotl, ndoth, pf;\n"
-  "    \n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatFrontAmbient;\n"
-  "      diffuseColor = Color*MatFrontDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = Color*MatBackAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatBackAmbient;\n"
-  "      diffuseColor = Color*MatBackDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0)\n"
-  "      pf = 0.0;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "    if (BoolTextures)\n"
-  "      color *= texture2D(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  gl_FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "    if (BoolTextures)\n"
-  "      color *= texture(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+in vec4 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform bool DrawLines;                                                  \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSampler;                                        \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 color;                                                            \n\
+  if (DrawLines)                                                         \n\
+  {                                                                      \n\
+    color = Color;                                                       \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    vec3 normalDirection;                                                \n\
+    vec4 ambientColor, diffuseColor, sceneColor;                         \n\
+    vec4 ambientLighting, diffuseReflection, specularReflection;         \n\
+    float ndotl, ndoth, pf;                                              \n\
+                                                                         \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;                  \n\
+      ambientColor = Color*MatFrontAmbient;                              \n\
+      diffuseColor = Color*MatFrontDiffuse;                              \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = Color*MatBackAmbient*LtGlblAmbient;                   \n\
+      ambientColor = Color*MatBackAmbient;                               \n\
+      diffuseColor = Color*MatBackDiffuse;                               \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0,dot(normalDirection,LtDirection));                   \n\
+    ndoth = max(0.0,dot(normalDirection,LtHalfVector));                  \n\
+    if (ndotl == 0.0)                                                    \n\
+      pf = 0.0;                                                          \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = sceneColor+ambientLighting+diffuseReflection;                \n\
+    if (BoolTextures)                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSampler,TexCoord.st).rrra;               \n\
+#else                                                                    \n\
+      color *= texture(TextureSampler,TexCoord.st).rrra;                 \n\
+#endif                                                                   \n\
+    color += specularReflection;                                         \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0,1.0);                                   \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0,1.0);                                      \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -1127,6 +1126,7 @@ static int etruscan_venus_ff(ModeInfo *mi, double umin, double umax,
   if (ev->marks)
   {
     glEnable(GL_TEXTURE_2D);
+    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 #ifndef HAVE_JWZGLES
     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
 #endif
@@ -2090,6 +2090,9 @@ static int etruscan_venus_pf(ModeInfo *mi, double umin, double umax,
     }
   }
 
+  if (ev->use_vao)
+    glBindVertexArray(ev->vertex_array_object);
+
   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D,ev->tex_name);
   glUniform1i(ev->texture_sampler_index,0);
@@ -2140,6 +2143,9 @@ static int etruscan_venus_pf(ModeInfo *mi, double umin, double umax,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (ev->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   if (ev->appearance == APPEARANCE_DISTANCE_BANDS)
@@ -2171,9 +2177,14 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
-               GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
+#ifdef HAVE_GLSL
+  if (ev->use_shaders)
+    glTexImage2D(GL_TEXTURE_2D,0,GL_R8,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_RED,GL_UNSIGNED_BYTE,texture);
+  else
+#endif /* HAVE_GLSL */
+    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
 
@@ -2184,8 +2195,8 @@ static void init_glsl(ModeInfo *mi)
   etruscanvenusstruct *ev = &etruscanvenus[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   ev->uv = calloc(2*(NUMU+1)*(NUMV+1),sizeof(float));
   ev->indices = calloc(4*(NUMU+1)*(NUMV+1),sizeof(float));
@@ -2197,54 +2208,18 @@ static void init_glsl(ModeInfo *mi)
   ev->ni = 0;
   ev->ne = 0;
   ev->nt = 0;
+  ev->use_vao = False;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &ev->shader_program))
     return;
   ev->vertex_uv_index = glGetAttribLocation(ev->shader_program,"VertexUV");
@@ -2314,6 +2289,10 @@ static void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&ev->color_buffer);
   glGenBuffers(1,&ev->indices_buffer);
 
+  ev->use_vao = glsl_IsCoreProfile();
+  if (ev->use_vao)
+    glGenVertexArrays(1,&ev->vertex_array_object);
+
   ev->use_shaders = True;
 }
 
@@ -2369,13 +2348,13 @@ static void init(ModeInfo *mi)
   ev->col = calloc(4*(NUMU+1)*(NUMV+1),sizeof(float));
   ev->tex = calloc(2*(NUMU+1)*(NUMV+1),sizeof(float));
 
-  gen_texture(mi);
-  setup_etruscan_venus_color_texture(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,NUMU,NUMV);
-
 #ifdef HAVE_GLSL
   init_glsl(mi);
 #endif /* HAVE_GLSL */
 
+  gen_texture(mi);
+  setup_etruscan_venus_color_texture(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,NUMU,NUMV);
+
 #ifdef HAVE_ANDROID
   /* glPolygonMode(...,GL_LINE) is not supported for an OpenGL ES 1.1
      context. */
@@ -2763,6 +2742,8 @@ ENTRYPOINT void free_etruscanvenus(ModeInfo *mi)
     glDeleteBuffers(1,&ev->vertex_t_buffer);
     glDeleteBuffers(1,&ev->color_buffer);
     glDeleteBuffers(1,&ev->indices_buffer);
+    if (ev->use_vao)
+      glDeleteVertexArrays(1,&ev->vertex_array_object);
     if (ev->shader_program != 0)
     {
       glUseProgram(0);
index f1b7e368f83692f16a267e95ec892cace28507fa..17389a6668d5c43f32dc60d1d522a12e218a673a 100644 (file)
@@ -45,8 +45,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "flurry.h"
 
-#include <GL/gl.h>
-#include <GL/glu.h>
+/* #include <GL/gl.h> */
+/* #include <GL/glu.h> */
 
 #include <stdlib.h>
 #include <math.h>
diff --git a/hacks/glx/fluxcore.man b/hacks/glx/fluxcore.man
new file mode 100644 (file)
index 0000000..d9163c4
--- /dev/null
@@ -0,0 +1,66 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+fluxcore \- screen saver.
+.SH SYNOPSIS
+.B fluxcore
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Long range space-based energy transmission requires a flux core to amplify
+and concentrate energy. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/ltlSWf
+.SH COPYRIGHT
+Copyright \(co 2015 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
diff --git a/hacks/glx/gimbalharmonics.man b/hacks/glx/gimbalharmonics.man
new file mode 100644 (file)
index 0000000..7192f8b
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+gimbalharmonics \- screen saver.
+.SH SYNOPSIS
+.B gimbalharmonics
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Disc-based visualization of different frequencies next to each other. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/llS3zd
+.SH COPYRIGHT
+Copyright \(co 2015 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
index 415723ae33ea7f736e3c4a3376718192b3bb0e07..371a9e074106b9b2ec9f479e3d09f8e56de3b4d3 100644 (file)
@@ -14,9 +14,6 @@
 
 #include <assert.h>
 
-#include "rotator.h"
-#include "doubletime.h"
-
 #define DEF_LIGHT     "True"
 #define DEF_FOG       "False"
 #define DEF_TEXTURE   "True"
@@ -63,6 +60,8 @@ enum {
 
 #include <math.h>
 #include "xlockmore.h"
+#include "rotator.h"
+#include "doubletime.h"
 
 #ifdef USE_GL                                  /* whole file */
 
index 3cf31c8d2a0e1855a5190f7460d089c3b4d6f27b..7db22a2dfdc0ec78208373356cf2405ff19d65b9 100644 (file)
@@ -1,5 +1,5 @@
 /* glsl-utils.c --- support functions for GLSL in OpenGL hacks.
- * Copyright (c) 2020-2021 Carsten Steger <carsten@mirsanmir.org>
+ * Copyright (c) 2020-2026 Carsten Steger <carsten@mirsanmir.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -316,21 +316,108 @@ GLboolean glsl_GetGlAndGlslVersions(GLint *gl_major, GLint *gl_minor,
 
  DONE:
 
-#if 0/*# ifndef __OPTIMIZE__*/
-  if (err)
-    fprintf (stderr, "%s: GLSL: %s\n", progname, err);
-  else
-    fprintf (stderr, "%s: GLSL available: GL=%d.%d, GLSL=%d.%d GLES3=%d\n",
-             progname,
-             *gl_major, *gl_minor, 
-             *glsl_major, *glsl_minor,
-             *gl_gles3 ? 1 : 0);
+# ifndef __OPTIMIZE__
+  {
+    static Bool printed_p = False;
+    if (printed_p)
+      ;
+    else if (err)
+      fprintf (stderr, "%s: GLSL: %s\n", progname, err);
+    else
+      fprintf (stderr, "%s: OpenGL %d.%d, GLSL %d.%d GLES3 = %s\n",
+               progname,
+               *gl_major, *gl_minor, 
+               *glsl_major, *glsl_minor,
+               *gl_gles3 ? "yes" : "no");
+    printed_p = True;
+  }
 # endif
 
   return (err ? GL_FALSE : GL_TRUE);
 }
 
 
+/* Return the #version string for a shader program depending on the GLSL
+   version that is being used. */
+const GLchar *glsl_GetGLSLVersionString(void)
+{
+  /* The GLSL version strings that correspond to different supported
+   versions of OpenGL. */
+  static const GLchar *shader_version_2_1 =      "#version 120\n";
+  static const GLchar *shader_version_3_0 =      "#version 130\n";
+  static const GLchar *shader_version_3_0_es =   "#version 300 es\n";
+#ifndef HAVE_JWZGLES
+  static const GLchar *shader_version_3_2_core = "#version 150\n";
+#endif
+  GLint gl_major, gl_minor, glsl_major, glsl_minor;
+  GLboolean gl_gles3;
+#ifndef HAVE_JWZGLES
+  GLint gl_profile;
+#endif
+
+  if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
+                                 &gl_gles3))
+    return NULL;
+  
+  if (gl_gles3 && gl_major == 3)
+    return shader_version_3_0_es;
+  
+  if (gl_major == 2 && gl_minor == 1)
+    return shader_version_2_1;
+  
+  if (gl_major == 3 && gl_minor < 2)
+    return shader_version_3_0;
+  
+  if (gl_major >= 4 || (gl_major == 3 && gl_minor >= 2))
+  {
+#ifndef HAVE_JWZGLES
+    glGetIntegerv(GL_CONTEXT_PROFILE_MASK,&gl_profile);
+    if ((gl_profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+      return shader_version_3_2_core;
+    else
+#endif
+      return shader_version_3_0;
+  }
+  
+  fprintf (stderr,
+           "%s: Unsupported OpenGL version: GL=%d.%d, GLSL=%d.%d GLES3=%d\n",
+           progname,
+           gl_major, gl_minor,
+           glsl_major, glsl_minor,
+           gl_gles3 ? 1 : 0);
+  return NULL;
+}
+
+
+/* Determine whether the OpenGL context is a core profile. */
+extern GLboolean glsl_IsCoreProfile(void)
+{
+  GLint gl_major, gl_minor, glsl_major, glsl_minor;
+  GLboolean gl_gles3;
+#ifndef HAVE_JWZGLES
+  GLint gl_profile;
+#endif
+
+  if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
+                                 &gl_gles3))
+    return GL_FALSE;
+  
+  if (gl_major < 3)
+    return GL_FALSE;
+  
+#ifndef HAVE_JWZGLES
+  if (gl_major >= 4 || (gl_major == 3 && gl_minor >= 2))
+  {
+    glGetIntegerv(GL_CONTEXT_PROFILE_MASK,&gl_profile);
+      if ((gl_profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
+        return GL_TRUE;
+  }
+#endif
+
+  return GL_FALSE;
+}
+
+
 #define PRINT_ERRORS
 /* #undef PRINT_ERRORS */
 
index 9ed6f7983b2de98faafb69057679d431c69bdb27..cea8c66e10956d47bf1216a88d363e40cd905f64 100644 (file)
@@ -1,5 +1,5 @@
 /* glsl-utils.h --- support functions for GLSL in OpenGL hacks.
- * Copyright (c) 2020-2021 Carsten Steger <carsten@mirsanmir.org>
+ * Copyright (c) 2020-2026 Carsten Steger <carsten@mirsanmir.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -68,6 +68,13 @@ extern GLboolean glsl_GetGlAndGlslVersions(GLint *gl_major,
                                            GLint *glsl_minor,
                                            GLboolean *gl_gles3);
 
+/* Return the #version string for a shader program depending on the GLSL
+   version that is being used. */
+const GLchar *glsl_GetGLSLVersionString(void);
+
+/* Determine whether the OpenGL context is a core profile. */
+extern GLboolean glsl_IsCoreProfile(void);
+
 /* Compile and link a vertex and a Fragment shader into a GLSL program. */
 extern GLboolean glsl_CompileAndLinkShaders(GLsizei vertex_shader_count,
                                         const GLchar **vertex_shader_source,
diff --git a/hacks/glx/glsl/README b/hacks/glx/glsl/README
new file mode 100644 (file)
index 0000000..2099543
--- /dev/null
@@ -0,0 +1,4 @@
+
+This directory contains the graphics hacks following the Shadertoy API,
+as implemented by ../xshadertoy.c.
+
diff --git a/hacks/glx/glsl/alienbeacon.glsl b/hacks/glx/glsl/alienbeacon.glsl
new file mode 100644 (file)
index 0000000..9adac9c
--- /dev/null
@@ -0,0 +1,424 @@
+// Title:  Alien Beacon
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/ld2SzK
+// Date:   26-Oct-2014
+// Desc:   Our investigation of the signal from the planet's surface brought us to what seems to be an alien beacon. Based on the rock formation around the beacon, it was probably left here millions of years ago.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+-Otavio Good
+*/
+
+// The noise function in this was inspired by IQ's "Terrain Tubes" shader. I never really figured out
+// his function completely, so I'm not sure of the exact similarities. It's nice though because it
+// works the same on all computers (I think). It's not based on a hash that changes from computer to 
+// computer. That means I can finally rely on the terrain being the same and make a camera path. :)
+// It's also a much faster noise function, although it can look a bit repetitive.
+
+#define MOTION_BLUR
+#define MOVING_SUN
+
+float Hash2d(vec2 uv)
+{
+    float f = uv.x + uv.y * 47.0;
+    return fract(cos(f*3.333)*100003.9);
+}
+float Hash3d(vec3 uv)
+{
+    float f = uv.x + uv.y * 37.0 + uv.z * 521.0;
+    return fract(cos(f*3.333)*100003.9);
+}
+
+float PI=3.14159265;
+
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+
+vec3 RotateX(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  //if (RIGHT_HANDED_COORD)
+  return vec3(v.x, cos * v.y + sin * v.z, -sin * v.y + cos * v.z);
+  //else return new float3(x, cos * y - sin * z, sin * y + cos * z);
+}
+vec3 RotateY(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  //if (RIGHT_HANDED_COORD)
+  return vec3(cos * v.x - sin * v.z, v.y, sin * v.x + cos * v.z);
+  //else return new float3(cos * x + sin * z, y, -sin * x + cos * z);
+}
+vec3 RotateZ(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  //if (RIGHT_HANDED_COORD)
+  return vec3(cos * v.x + sin * v.y, -sin * v.x + cos * v.y, v.z);
+}
+
+
+// This function basically is a procedural environment map that makes the sun
+vec3 sunCol = vec3(258.0, 208.0, 100.0) / 4255.0;//unfortunately, i seem to have 2 different sun colors. :(
+vec3 GetSunColorReflection(vec3 rayDir, vec3 sunDir)
+{
+       vec3 localRay = normalize(rayDir);
+       float dist = 1.0 - (dot(localRay, sunDir) * 0.5 + 0.5);
+       float sunIntensity = 0.015 / dist;
+       sunIntensity = pow(sunIntensity, 0.3)*100.0;
+
+    sunIntensity += exp(-dist*12.0)*300.0;
+       sunIntensity = min(sunIntensity, 40000.0);
+       return sunCol * sunIntensity*0.0425;
+}
+vec3 GetSunColorSmall(vec3 rayDir, vec3 sunDir)
+{
+       vec3 localRay = normalize(rayDir);
+       float dist = 1.0 - (dot(localRay, sunDir) * 0.5 + 0.5);
+       float sunIntensity = 0.05 / dist;
+    sunIntensity += exp(-dist*12.0)*300.0;
+       sunIntensity = min(sunIntensity, 40000.0);
+       return sunCol * sunIntensity*0.025;
+}
+
+// This is a spline used for the camera path
+vec4 CatmullRom(vec4 p0, vec4 p1, vec4 p2, vec4 p3, float t)
+{
+    float t2 = t*t;
+    float t3 = t*t*t;
+    return 0.5 *((2.0 * p1) +
+                 (-p0 + p2) * t +
+                        (2.0 * p0 - 5.0 * p1 + 4.0 * p2 - p3) * t2 +
+                        (-p0 + 3.0 * p1- 3.0 * p2 + p3) * t3);
+}
+
+// This spiral noise works by successively adding and rotating sin waves while increasing frequency.
+// It should work the same on all computers since it's not based on a hash function like some other noises.
+// It can be much faster than other noise functions if you're ok with some repetition.
+const float nudge = 0.739513;  // size of perpendicular vector
+float normalizer = 1.0 / sqrt(1.0 + nudge*nudge);      // pythagorean theorem on that perpendicular to maintain scale
+float SpiralNoiseC(vec3 p)
+{
+    float n = 0.0;     // noise amount
+    float iter = 1.0;
+    for (int i = 0; i < 8; i++)
+    {
+        // add sin and cos scaled inverse with the frequency
+        n += -abs(sin(p.y*iter) + cos(p.x*iter)) / iter;       // abs for a ridged look
+        // rotate by adding perpendicular and scaling down
+        p.xy += vec2(p.y, -p.x) * nudge;
+        p.xy *= normalizer;
+        // rotate on other axis
+        p.xz += vec2(p.z, -p.x) * nudge;
+        p.xz *= normalizer;
+        // increase the frequency
+        iter *= 1.733733;
+    }
+    return n;
+}
+float SpiralNoiseD(vec3 p)
+{
+    float n = 0.0;
+    float iter = 1.0;
+    for (int i = 0; i < 6; i++)
+    {
+        n += abs(sin(p.y*iter) + cos(p.x*iter)) / iter;        // abs for a ridged look
+        p.xy += vec2(p.y, -p.x) * nudge;
+        p.xy *= normalizer;
+        p.xz += vec2(p.z, -p.x) * nudge;
+        p.xz *= normalizer;
+        iter *= 1.733733;
+    }
+    return n;
+}
+float SpiralNoise3D(vec3 p)
+{
+    float n = 0.0;
+    float iter = 1.0;
+    for (int i = 0; i < 5; i++)
+    {
+        n += (sin(p.y*iter) + cos(p.x*iter)) / iter;
+        //p.xy += vec2(p.y, -p.x) * nudge;
+        //p.xy *= normalizer;
+        p.xz += vec2(p.z, -p.x) * nudge;
+        p.xz *= normalizer;
+        iter *= 1.33733;
+    }
+    return n;
+}
+
+// These are the xyz camera positions and a left/right facing angle relative to the path line
+// I think webgl glsl can only access arrays using a constant, so I'm writing all these out.
+// Someone please tell me if I'm wrong.
+vec4 c00 = vec4(3.5, 2.0, 13.1, 0.0);  // start point
+vec4 c01 = vec4(12.5, 2.2, 17.0, 0.0); // run up to canyon 2 before hole in large rock face
+vec4 c02 = vec4(21.5, 4.0, 8.1, 0.0);  // canyon 2 before hole in large rock face
+vec4 c03 = vec4(21.0, 5.0, 1.1, -0.5); // before hole in large rock face
+vec4 c04 = vec4(17.8, 5.4, -0.2, 0.0); // hole in large rock face
+vec4 c05 = vec4(14.7, 2.5, 1.4, 0.0);  // after hole in large rock face
+vec4 c06 = vec4(7.9, 2.3, -2.1, 0.0);
+vec4 c07 = vec4(0.5, -0.7, -3.5, 1.0);
+vec4 c08 = vec4(-3.0, -1.0, -3.5, 1.3);
+vec4 c09 = vec4(-3.5, -1.0, 4.0, 1.3);
+vec4 c10 = vec4(3.0, -0.7, 3.3, 0.8);
+vec4 c11 = vec4(3.5, -1.0, -4.75, 0.0);
+vec4 c12 = vec4(-6.0, -0.2, 1.0, 3.14);
+vec4 c13 = vec4(-6.0, -1.0, 5.5, 0.0);
+
+vec4 cXX = vec4(0.0, 3.0, 0.0, 0.0);
+
+float camPathOffset = 0.0;     // where to start on the camera path - parametric t var for catmull-rom spline
+vec3 camPos = vec3(0.0), camFacing;
+vec3 camLookat=vec3(0,0.0,0);
+float waterLevel = 1.5;
+// from a time t, this finds where in the camera path you are.
+// It uses Catmull-Rom splines
+vec4 CamPos(float t)
+{
+    t = mod(t, 14.0);  // repeat after 14 time units
+    float bigTime = floor(t);
+    float smallTime = fract(t);
+    // Can't do arrays right, so write this all out.
+    if (bigTime == 0.0) return CatmullRom(c00, c01, c02, c03, smallTime);
+    if (bigTime == 1.0) return CatmullRom(c01, c02, c03, c04, smallTime);
+    if (bigTime == 2.0) return CatmullRom(c02, c03, c04, c05, smallTime);
+    if (bigTime == 3.0) return CatmullRom(c03, c04, c05, c06, smallTime);
+    if (bigTime == 4.0) return CatmullRom(c04, c05, c06, c07, smallTime);
+    if (bigTime == 5.0) return CatmullRom(c05, c06, c07, c08, smallTime);
+    if (bigTime == 6.0) return CatmullRom(c06, c07, c08, c09, smallTime);
+
+    if (bigTime == 7.0) return CatmullRom(c07, c08, c09, c10, smallTime);
+    if (bigTime == 8.0) return CatmullRom(c08, c09, c10, c11, smallTime);
+    if (bigTime == 9.0) return CatmullRom(c09, c10, c11, c12, smallTime);
+    if (bigTime == 10.0) return CatmullRom(c10, c11, c12, c13, smallTime);
+    if (bigTime == 11.0) return CatmullRom(c11, c12, c13, c00, smallTime);
+    if (bigTime == 12.0) return CatmullRom(c12, c13, c00, c01, smallTime);
+    if (bigTime == 13.0) return CatmullRom(c13, c00, c01, c02, smallTime);
+    return vec4(0.0);
+}
+
+float DistanceToObject(vec3 p)
+{
+       float final = p.y + 4.5;
+    final -= SpiralNoiseC(p.xyz);      // mid-range noise
+    final += SpiralNoiseC(p.zxy*0.123+100.0)*3.0;      // large scale terrain features
+    final -= SpiralNoise3D(p); // more large scale features, but 3d, so not just a height map.
+    final -= SpiralNoise3D(p*49.0)*0.0625*0.125;       // small scale noise for variation
+       final = min(final, length(p) - 1.99);   // sphere in center
+    final = min(final, p.y + waterLevel);      // water
+       //final = min(final, length(p-camLookat) - 0.3);
+    return final;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+       // ---------------- First, set up the camera rays for ray marching ----------------
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+
+       // Camera up vector.
+       vec3 camUp=vec3(0,1,0); // vuv
+
+       // Camera lookat.
+       camLookat=vec3(0,0.0,0);        // vrp
+
+/*    if (iTime == 0.0)        // for debugging with manual camera
+    {
+        camPos = cXX.xyz;
+        camLookat = vec3(0.0)*cXX.xyz;
+    }*/
+
+    // debugging camera
+    float mx=iMouse.x/iResolution.x*PI*2.0;// + iTime * 0.1;
+       float my=-iMouse.y/iResolution.y*10.0;// + sin(iTime * 0.3)*0.2+0.2;//*PI/2.01;
+       camPos += vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*(5.2);  // prp
+
+    // set time for moving camera along path
+    float timeLine = iTime*0.2 + camPathOffset;
+    camFacing = camLookat + camPos;
+    // without this if condition, the mac doesn't work. mysterious. :(
+    if (iTime != -1.0)
+    {
+        vec4 catmullA = CamPos(timeLine);
+        // get a smoother derivative even though the spline is not C2 continuous.
+        // Also look ahead a bit so the camera leads the motion
+        vec4 catmullB = CamPos(timeLine + 0.3);
+#ifdef MOTION_BLUR
+        vec4 catmullC = CamPos(timeLine + 0.004);      // adjust for camera motion blur
+        vec4 catmullBlur = mix(catmullA, catmullC, Hash2d(uv));        // motion blur along camera path
+        camPos = catmullBlur.xyz;
+        // face camera along derivate of motion path
+        camFacing = normalize(catmullB.xyz - catmullA.xyz);
+        // rotate camera based on w component of camera path vectors
+        camFacing = RotateY(camFacing, -catmullBlur.w);
+#else
+        camPos = catmullA.xyz;
+        // face camera along derivate of motion path
+        camFacing = normalize(catmullB.xyz - catmullA.xyz);
+        // rotate camera based on w component of camera path vectors
+        camFacing = RotateY(camFacing, -catmullA.w);
+#endif
+        camFacing = RotateY(camFacing, -mx);
+       camLookat = camPos + camFacing;
+    }
+
+
+    // add randomness to camera for depth-of-field look close up.
+    //camPos += vec3(Hash2d(uv)*0.91, Hash2d(uv+37.0), Hash2d(uv+47.0))*0.01;
+
+       // Camera setup.
+       vec3 camVec=normalize(camLookat - camPos);//vpn
+       vec3 sideNorm=normalize(cross(camUp, camVec));  // u
+       vec3 upNorm=cross(camVec, sideNorm);//v
+       vec3 worldFacing=(camPos + camVec);//vcv
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;//scrCoord
+       vec3 relVec = normalize(worldPix - camPos);//scp
+
+       // --------------------------------------------------------------------------------
+       float dist = 0.05;
+       float t = 0.0;
+       float inc = 0.02;
+       float maxDepth = 110.0;
+       vec3 pos = vec3(0,0,0);
+       // ray marching time
+    for (int i = 0; i < 200; i++)      // This is the count of the max times the ray actually marches.
+    {
+        if ((t > maxDepth) || (abs(dist) < 0.0075)) break;
+        pos = camPos + relVec * t;
+        // *******************************************************
+        // This is _the_ function that defines the "distance field".
+        // It's really what makes the scene geometry.
+        // *******************************************************
+        dist = DistanceToObject(pos);
+        t += dist * 0.25;      // because deformations mess up distance function.
+    }
+
+       // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this geometry.
+
+#ifdef MOVING_SUN
+       vec3 sunDir = normalize(vec3(sin(iTime*0.047-1.5), cos(iTime*0.047-1.5), -0.5));
+#else
+       vec3 sunDir = normalize(vec3(0.93, 1.0, -1.5));
+#endif
+    // This makes the sky fade at sunset
+    float skyMultiplier = saturate(sunDir.y+0.7);
+       vec3 finalColor = vec3(0.0);
+
+       // If a ray actually hit the object, let's light it.
+       if (abs(dist) < 0.75)
+    //if (t <= maxDepth)
+       {
+        // calculate the normal from the distance field. The distance field is a volume, so if you
+        // sample the current point and neighboring points, you can use the difference to get
+        // the normal.
+        vec3 smallVec = vec3(0.005, 0, 0);
+        vec3 normal = vec3(dist - DistanceToObject(pos - smallVec.xyy),
+                           dist - DistanceToObject(pos - smallVec.yxy),
+                           dist - DistanceToObject(pos - smallVec.yyx));
+
+        /*if (pos.y <= waterLevel-2.995)       // water waves?
+        {
+            normal += SpiralNoise3D(pos*32.0+vec3(iTime*8.0,0.0,0.0))*0.0001;
+            normal += SpiralNoise3D(pos*27.0+vec3(0.0,0.0, iTime* 10.333))*0.0001;
+            normal += SpiralNoiseD(pos*37.0+vec3(0.0,iTime* 14.333,0.0))*0.0002;
+        }*/
+        normal = normalize(normal);
+
+        // calculate 2 ambient occlusion values. One for global stuff and one
+        // for local stuff - so the green sphere light source can also have ambient.
+        float ambientS = 1.0;
+        //ambient *= saturate(DistanceToObject(pos + normal * 0.1)*10.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.2)*5.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.4)*2.5);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.8)*1.25);
+        float ambient = ambientS * saturate(DistanceToObject(pos + normal * 1.6)*1.25*0.5);
+        ambient *= saturate(DistanceToObject(pos + normal * 3.2)*1.25*0.25);
+        ambient *= saturate(DistanceToObject(pos + normal * 6.4)*1.25*0.125);
+        //ambient = max(0.05, pow(ambient, 0.3));      // tone down ambient with a pow and min clamp it.
+        ambient = saturate(ambient);
+
+        // Trace a ray toward the sun for sun shadows
+        float sunShadow = 1.0;
+        float iter = 0.2;
+               for (int i = 0; i < 10; i++)
+        {
+            float tempDist = DistanceToObject(pos + sunDir * iter);
+               sunShadow *= saturate(tempDist*10.0);
+            if (tempDist <= 0.0) break;
+            iter *= 1.5;       // constant is more reliable than distance-based
+            //iter += max(0.2, tempDist)*1.2;
+        }
+        float sunSet = saturate(sunDir.y*4.0); // sunset dims the sun
+        sunShadow = saturate(sunShadow) * sunSet;
+
+        // calculate the reflection vector for highlights
+        vec3 ref = reflect(relVec, normal);
+
+        // pulse the ball light source
+        vec3 ballGlow = vec3(0.1, 0.97, 0.1) * abs(SpiralNoise3D(vec3(iTime*1.3)));
+
+        // ------ Calculate texture color of the rock ------
+        // basic orange and white blended together with noise
+        vec3 texColor = mix(vec3(0.95, 1.0, 1.0),  vec3(0.9, 0.7, 0.5), pow(abs(SpiralNoise3D(pos*1.0)-1.0), 0.6) );
+        // make the undersides darker greenish
+        texColor = mix(vec3(0.2, 0.2, 0.1), texColor, saturate(normal.y));
+        // fade to reddish/orange closer to the water level
+        texColor = mix(texColor, vec3(0.64, 0.2, 0.1) , saturate(-0.4-pos.y));
+        // some more variation to the color vertically
+        texColor = mix(texColor, vec3(0.2, 0.13, 0.02) , pow(saturate(pos.y*0.125+0.5), 2.0));
+        // give the rock a stratified, layered look
+        float rockLayers = abs(cos(pos.y*1.5+ SpiralNoiseD(pos*vec3(1.0, 2.0, 1.0)*4.0)*0.2 ));
+        texColor += vec3(0.7, 0.4, 0.3)*(1.0-pow(rockLayers, 0.3));
+
+        // make the water orange. I'm trying for that "nickel tailings" look.
+        texColor = mix(texColor, vec3(1.4, 0.15, 0.05) + SpiralNoise3D(pos)*0.025, saturate((-pos.y-1.45)*17.0));
+        // make the sphere white
+        if (length(pos) <= 2.01) texColor = vec3(1.0);
+        // don't let it get too saturated or dark
+        texColor = max(texColor, 0.05);
+
+        // ------ Calculate lighting color ------
+        // Start with sun color, standard lighting equation, and shadow
+        vec3 lightColor = vec3(1.0, 0.75, 0.75) * saturate(dot(sunDir, normal)) * sunShadow*1.5;
+        // sky color, hemisphere light equation approximation, anbient occlusion, sunset multiplier
+        lightColor += vec3(1.0,0.3,0.6) * ( dot(sunDir, normal) * 0.5 + 0.5 ) * ambient * 0.25 * skyMultiplier;
+        // Make the ball cast light. Distance to the 4th light falloff looked best. Use local ambient occlusion.
+        float lp = length(pos) - 1.0;
+        lightColor += ambientS*(ballGlow*1.2 * saturate(dot(normal, -pos)*0.5+0.5) / (lp*lp*lp*lp));
+
+        // finally, apply the light to the texture.
+        finalColor = texColor * lightColor;
+
+        // Make the water reflect the sun (leaving out sky reflection for no good reason)
+        vec3 refColor = GetSunColorReflection(ref, sunDir)*0.68;
+        finalColor += refColor * sunShadow * saturate(normal.y*normal.y) * saturate(-(pos.y+1.35)*16.0);
+
+        // make the ball itself glow
+        finalColor += pow(saturate(1.0 - length(pos)*0.4925), 0.65) * ballGlow*6.1;
+        // fog that fades to reddish plus the sun color so that fog is brightest towards sun
+        finalColor = mix(vec3(1.0, 0.41, 0.41)*skyMultiplier + min(vec3(0.25),GetSunColorSmall(relVec, sunDir))*2.0*sunSet, finalColor, exp(-t*0.03));
+       }
+    else
+    {
+        // Our ray trace hit nothing, so draw sky.
+        // fade the sky color, multiply sunset dimming
+        finalColor = mix(vec3(1.0, 0.5, 0.5), vec3(0.40, 0.25, 0.91), saturate(relVec.y))*skyMultiplier;
+        // add the sun
+        finalColor += GetSunColorSmall(relVec, sunDir);// + vec3(0.1, 0.1, 0.1);
+    }
+
+    //finalColor = vec3(Hash2d(uv)*0.91,  Hash2d(uv+47.0)*0.91, 0.0);
+    // vignette?
+    finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
+    finalColor *= 1.3;
+
+       // output the final color with sqrt for "gamma correction"
+       fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
+
+
diff --git a/hacks/glx/glsl/batteredplanet.glsl b/hacks/glx/glsl/batteredplanet.glsl
new file mode 100644 (file)
index 0000000..a3f5674
--- /dev/null
@@ -0,0 +1,355 @@
+// Title:  A battered alien planet
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/wsjBD3
+// Date:   01-Jun-2020
+// Desc:   License CC0: A battered alien planet
+// Been experimenting with space inspired shaders
+
+// License CC0: A battered alien planet
+//  Been experimenting with space inspired shaders
+
+#define PI  3.141592654
+#define TAU (2.0*PI)
+
+#define TOLERANCE       0.00001
+#define MAX_ITER        65
+#define MIN_DISTANCE    0.01
+#define MAX_DISTANCE    9.0
+
+const vec3  skyCol1       = vec3(0.35, 0.45, 0.6);
+const vec3  skyCol2       = vec3(0.4, 0.7, 1.0);
+const vec3  skyCol3       = pow(skyCol1, vec3(0.25));
+const vec3  sunCol1       = vec3(1.0,0.6,0.4);
+const vec3  sunCol2       = vec3(1.0,0.9,0.7);
+const vec3  smallSunCol1  = vec3(1.0,0.5,0.25)*0.5;
+const vec3  smallSunCol2  = vec3(1.0,0.5,0.25)*0.5;
+const vec3  mountainColor = 1.0*sqrt(vec3(0.95, 0.65, 0.45));
+const float cellWidth     = 1.0;
+const vec4  planet        = vec4(80.0, -20.0, 100.0, 50.0)*1000.0;
+
+void rot(inout vec2 p, float a) {
+  float c = cos(a);
+  float s = sin(a);
+  p = vec2(p.x*c + p.y*s, -p.x*s + p.y*c);
+}
+
+vec2 mod2(inout vec2 p, vec2 size) {
+  vec2 c = floor((p + size*0.5)/size);
+  p = mod(p + size*0.5,size) - size*0.5;
+  return c;
+}
+
+float circle(vec2 p, float r) {
+  return length(p) - r;
+}
+
+float egg(vec2 p, float ra, float rb) {
+  const float k = sqrt(3.0);
+  p.x = abs(p.x);
+  float r = ra - rb;
+  return ((p.y<0.0)       ? length(vec2(p.x,  p.y    )) - r :
+          (k*(p.x+r)<p.y) ? length(vec2(p.x,  p.y-k*r)) :
+                              length(vec2(p.x+r,p.y    )) - 2.0*r) - rb;
+}
+
+vec2 hash(vec2 p) {
+  p = vec2(dot (p, vec2 (127.1, 311.7)), dot (p, vec2 (269.5, 183.3)));
+  return -1. + 2.*fract (sin (p)*43758.5453123);
+}
+
+vec2 raySphere(vec3 ro, vec3 rd, vec4 sphere) {
+  vec3 center = sphere.xyz;
+  float radius = sphere.w;
+  vec3 m = ro - center.xyz;
+  float b = dot(m, rd);
+  float c = dot(m, m) - radius*radius;
+  if(c > 0.0 && b > 0.0) return vec2(-1.0, -1.0);
+  float discr = b * b - c;
+  if(discr < 0.0) return vec2(-1.0);
+  float normalMultiplier = 1.0;
+  float s = sqrt(discr);
+  float t0 = -b - s;
+  float t1 = -b + s;;
+  return vec2(t0, t1);
+}
+
+float noise1(vec2 p) {
+  vec2 n = mod2(p, vec2(cellWidth));
+  vec2 hh = hash(sqrt(2.0)*(n+1000.0));
+  hh.x *= hh.y;
+  
+  float r = 0.225*cellWidth;
+ 
+  float d = circle(p, 2.0*r);
+  
+  float h = hh.x*smoothstep(0.0, r, -d);
+
+  return h*0.25;
+}
+
+float noise2(vec2 p) {
+  vec2 n = mod2(p, vec2(cellWidth));
+  vec2 hh = hash(sqrt(2.0)*(n+1000.0));
+  hh.x *= hh.y;
+
+  rot(p, TAU*hh.y);
+  float r = 0.45*cellWidth;
+ 
+//  float d = circle(p, 1.0*r);
+  float d = egg(p, 0.75*r, 0.5*r*abs(hh.y));
+  
+  float h = (hh.x)*smoothstep(0.0, r, -2.0*d);
+
+  return h*0.275;
+}
+
+
+float height(vec2 p, float dd, int mx) {
+  const float aa   = 0.45;
+  const float ff   = 2.03;
+  const float tt   = 1.2;
+  const float oo   = 3.93;
+  const float near = 0.25;
+  const float far  = 0.65;
+  
+  float a = 1.0;
+  float o = 0.2;
+  float s = 0.0;
+  float d = 0.0;
+  
+  int i = 0;
+  
+  for (; i < 4;++i) {
+    float nn = a*noise2(p);
+    s += nn;
+    d += abs(a);
+    p += o;
+    a *= aa;
+    p *= ff;
+    o *= oo;
+    rot(p, tt);
+  }
+
+  float lod = s/d;
+
+  float rdd = dd/MAX_DISTANCE;
+  mx = int(mix(float(4), float(mx), step(rdd, far)));
+  
+  for (; i < mx; ++i) {
+    float nn = a*noise1(p);
+    s += nn;
+    d += abs(a);
+    p += o;
+    a *= aa;
+    p *= ff;
+    o *= oo;
+    rot(p, tt);
+  }
+  
+  float hid = (s/d);
+  
+  return mix(hid, lod, smoothstep(near, far, rdd));
+}
+
+float loheight(vec2 p, float d) {
+  return height(p, d, 0);
+}
+
+float height(vec2 p, float d) {
+  return height(p, d, 6);
+}
+
+float hiheight(vec2 p, float d) {
+  return height(p, d, 8);
+}
+  
+vec3 normal(vec2 p, float d) {
+  vec2 eps = vec2(0.00125, 0.0);
+  
+  vec3 n;
+  
+  n.x = (hiheight(p - eps.xy, d) - hiheight(p + eps.xy, d));
+  n.y = 2.0*eps.x;
+  n.z = (hiheight(p - eps.yx, d) - hiheight(p + eps.yx, d));
+  
+  return normalize(n);
+}
+
+const float stepLength[] = float[](0.9, 0.25);
+
+
+float march(vec3 ro, vec3 rd, out int max_iter) {
+  float dt = 0.1;
+  float d = MIN_DISTANCE;
+  int currentStep = 0;
+  float lastd = d;
+  for (int i = 0; i < MAX_ITER; ++i)
+  {
+    vec3 p = ro + d*rd;
+    float h = height(p.xz, d);
+    
+    if (d > MAX_DISTANCE) {
+      max_iter = i;
+      return MAX_DISTANCE;
+    }
+
+    float hd = p.y - h;
+
+    if (hd < TOLERANCE) {
+      ++currentStep;
+      if (currentStep >= stepLength.length()) {
+        max_iter = i;
+        return d;
+      }
+      
+      d = lastd;
+      continue;
+    }
+
+    float sl = stepLength[currentStep];
+
+    dt = max(hd, TOLERANCE)*sl + 0.0025*d;
+    lastd = d;
+    d += dt;
+  }
+  
+  max_iter = MAX_ITER;
+  return MAX_DISTANCE;
+}
+
+vec3 sunDirection() {
+  return normalize(vec3(-0.5, 0.085, 1.0));
+}
+
+vec3 smallSunDirection() {
+  return normalize(vec3(-0.2, -0.05, 1.0));
+}
+
+float psin(float f) {
+  return 0.5 + 0.5*sin(f);
+}
+
+vec3 skyColor(vec3 ro, vec3 rd) {
+  vec3 sunDir = sunDirection();
+  vec3 smallSunDir = smallSunDirection();
+
+  float sunDot = max(dot(rd, sunDir), 0.0);
+  float smallSunDot = max(dot(rd, smallSunDir), 0.0);
+  
+  float angle = atan(rd.y, length(rd.xz))*2.0/PI;
+
+  vec3 skyCol = mix(mix(skyCol1, skyCol2, max(0.0, angle)), skyCol3, clamp(-angle*2.0, 0.0, 1.0));
+  
+  vec3 sunCol = 0.5*sunCol1*pow(sunDot, 20.0) + 8.0*sunCol2*pow(sunDot, 2000.0);
+  vec3 smallSunCol = 0.5*smallSunCol1*pow(smallSunDot, 200.0) + 8.0*smallSunCol2*pow(smallSunDot, 20000.0);
+
+  vec3 dust = pow(sunCol2*mountainColor, vec3(1.75))*smoothstep(0.05, -0.1, rd.y)*0.5;
+
+  vec2 si = raySphere(ro, rd, planet);
+  
+  vec3 planetSurface = ro + si.x*rd;
+  vec3 planetNormal = normalize(planetSurface - planet.xyz);
+  float planetDiff = max(dot(planetNormal, sunDir), 0.0);
+  float planetBorder = max(dot(planetNormal, -rd), 0.0);
+  float planetLat = (planetSurface.x+planetSurface.y)*0.0005;
+  vec3 planetCol = mix(1.3*vec3(0.9, 0.8, 0.7), 0.3*vec3(0.9, 0.8, 0.7), pow(psin(planetLat+1.0)*psin(sqrt(2.0)*planetLat+2.0)*psin(sqrt(3.5)*planetLat+3.0), 0.5));
+
+  vec3 final = vec3(0.0);
+  
+ final += step(0.0, si.x)*pow(planetDiff, 0.75)*planetCol*smoothstep(-0.075, 0.0, rd.y)*smoothstep(0.0, 0.1, planetBorder);
+
+ final += skyCol + sunCol + smallSunCol + dust;
+
+
+  return final;
+}
+
+vec3 getColor(vec3 ro, vec3 rd) {
+  int max_iter = 0;
+  vec3 skyCol = skyColor(ro, rd);
+  vec3 col = vec3(0);
+  
+  float d = march(ro, rd, max_iter);
+
+  if (d < MAX_DISTANCE)   {
+    vec3 sunDir = sunDirection();
+    vec3 osunDir = sunDir*vec3(-1.0, .0, -1.0);
+    vec3 p = ro + d*rd;
+
+    vec3 normal = normal(p.xz, d);
+    
+    float amb = 0.2;
+
+    float dif1 = max(0.0, dot(sunDir, normal));
+    vec3 shd1 = sunCol2*mix(amb, 1.0, pow(dif1, 0.75));
+
+    float dif2 = max(0.0, dot(osunDir, normal));
+    vec3 shd2 = sunCol1*mix(amb, 1.0, pow(dif2, 0.75));
+
+    vec3 ref = reflect(rd, normal);
+    vec3 rcol = skyColor(p, ref);
+
+    col = mountainColor*amb*skyCol3;
+    col += mix(shd1, shd2, -0.5)*mountainColor;   
+    float fre = max(dot(normal, -rd), 0.0);
+    fre = pow(1.0 - fre, 5.0);
+    col += rcol*fre*0.5;
+    col += (1.0*p.y);
+    col = tanh(col);
+    col = mix(col, skyCol, smoothstep(0.5*MAX_DISTANCE, 1.0*MAX_DISTANCE, d));
+  
+  } else {
+    col = skyCol;
+  }
+  
+//  col += vec3(1.1, 0.0, 0.0)* smoothstep(0.25, 1.0,(float(max_iter)/float(MAX_ITER)));
+  return col;
+}
+
+vec3 getSample1(vec2 p, float time) {
+  float off = 0.5*iTime;
+
+  vec3 ro  = vec3(0.5, 1.0-0.25, -2.0 + off);
+  vec3 la  = ro + vec3(0.0, -0.30,  2.0);
+
+  vec3 ww = normalize(la - ro);
+  vec3 uu = normalize(cross(vec3(0.0,1.0,0.0), ww));
+  vec3 vv = normalize(cross(ww, uu));
+  vec3 rd = normalize(p.x*uu + p.y*vv + 2.0*ww);
+
+  vec3 col = getColor(ro, rd)  ;
+ 
+  return col;
+  
+}
+
+vec3 getSample2(vec2 p, float time) {
+  p.y-=time*0.25;
+  float h = height(p, 0.0);
+  vec3 n = normal(p, 0.0);
+  
+  vec3 lp = vec3(10.0, -1.2, 0.0);
+  
+  vec3 ld = normalize(vec3(p.x, h, p.y)- lp);
+  
+  float d = max(dot(ld, n), 0.0);
+  
+  vec3 col = vec3(0.0);
+
+  col = vec3(1.0)*(h+0.1);
+  col += vec3(1.5)*pow(d, 0.75);
+ 
+  return col;
+  
+}
+
+void mainImage(out vec4 fragColor, vec2 fragCoord) {
+  vec2 q = fragCoord.xy/iResolution.xy;
+  vec2 p = -1.0 + 2.0*q;
+  p.x *= iResolution.x/iResolution.y;
+  
+  vec3 col = getSample1(p, iTime);
+  
+  fragColor = vec4(col, 1.0);
+}
+
diff --git a/hacks/glx/glsl/elementalring.glsl b/hacks/glx/glsl/elementalring.glsl
new file mode 100644 (file)
index 0000000..8f3ca8a
--- /dev/null
@@ -0,0 +1,345 @@
+// Title:  Elemental Ring
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/MsVXDt
+// Date:   19-Jul-2016
+// Desc:   This shader was inspired by https://www.shadertoy.com/view/MtBSWR. I wanted to do a 3d version.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+^ This means do ANYTHING YOU WANT with this code. Because we are programmers, not lawyers.
+-Otavio Good
+*/
+
+// ---------------- Config ----------------
+// This is an option that lets you render high quality frames for screenshots. It enables
+// stochastic antialiasing and motion blur automatically for any shader.
+//#define NON_REALTIME_HQ_RENDER
+const float frameToRenderHQ = 11.0; // Time in seconds of frame to render
+const float antialiasingSamples = 16.0; // 16x antialiasing - too much might make the shader compiler angry.
+
+//#define MANUAL_CAMERA
+
+
+// --------------------------------------------------------
+// These variables are for the non-realtime block renderer.
+float localTime = 0.0;
+float seed = 1.0;
+
+// ---- noise functions ----
+float v31(vec3 a)
+{
+    return a.x + a.y * 37.0 + a.z * 521.0;
+}
+float v21(vec2 a)
+{
+    return a.x + a.y * 37.0;
+}
+float Hash11(float a)
+{
+    return fract(sin(a)*10403.9);
+}
+float Hash21(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(sin(f)*104003.9);
+}
+vec2 Hash22(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(cos(f)*vec2(10003.579, 37049.7));
+}
+vec2 Hash12(float f)
+{
+    return fract(cos(f)*vec2(10003.579, 37049.7));
+}
+float Hash1d(float u)
+{
+    return fract(sin(u)*143.9);        // scale this down to kill the jitters
+}
+float Hash2d(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(sin(f)*104003.9);
+}
+float Hash3d(vec3 uv)
+{
+    float f = uv.x + uv.y * 37.0 + uv.z * 521.0;
+    return fract(sin(f)*110003.9);
+}
+
+const float PI=3.14159265;
+
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+
+// polynomial smooth min (k = 0.1);
+float smin( float a, float b, float k )
+{
+    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
+    return mix( b, a, h ) - k*h*(1.0-h);
+}
+
+vec2 matMin(vec2 a, vec2 b)
+{
+       if (a.x < b.x) return a;
+       else return b;
+}
+
+// ---- shapes defined by distance fields ----
+// See this site for a reference to more distance functions...
+// https://iquilezles.org/articles/distfunctions
+// box distance field
+float sdBox(vec3 p, vec3 radius)
+{
+  vec3 dist = abs(p) - radius;
+  return min(max(dist.x, max(dist.y, dist.z)), 0.0) + length(max(dist, 0.0));
+}
+
+// simple cylinder distance field
+float cyl(vec2 p, float r)
+{
+    return length(p) - r;
+}
+
+const float TAU = 2.0 * PI;
+
+float glow = 0.0;
+// This is the function that makes the geometry.
+// The input is a position in space.
+// The output is the distance to the nearest surface and a material number
+vec2 DistanceToObject(vec3 p)
+{
+    float time = localTime*2.0;
+    float cylRadBig = 1.0;
+    float cylRadSmall = 0.05;
+    float freq = 4.0;
+    float braidRad = 0.15;
+    float angle = atan(p.z, p.x);
+    float cylDist = length(p.xz) - cylRadBig;
+    vec3 cylWarp = vec3(cylDist, p.y, angle);
+    float amp = sin(angle + time) * 0.5 + 0.5;
+
+    float theta = angle*freq;
+    vec2 wave1 = vec2(sin(theta), cos(theta)) * braidRad;
+    wave1 *= amp;
+    //float d = length(cylWarp.xy + wave1) - cylRadSmall;
+    float d = sdBox(vec3(cylWarp.xy + wave1, 0.0), vec3(cylRadSmall));
+    float final = d;
+
+    theta = angle*freq + TAU / 3.0;
+    vec2 wave2 = vec2(sin(theta), cos(theta)) * braidRad;
+    wave2 *= amp;
+    //d = length(cylWarp.xy + wave2) - cylRadSmall;
+    d = sdBox(vec3(cylWarp.xy + wave2, 0.0), vec3(cylRadSmall));
+    final = smin(final, d, 0.1);
+
+    theta = angle*freq - TAU / 3.0;
+    vec2 wave3 = vec2(sin(theta), cos(theta)) * braidRad;
+    wave3 *= amp;
+    //d = length(cylWarp.xy + wave3) - cylRadSmall;
+    d = sdBox(vec3(cylWarp.xy + wave3, 0.0), vec3(cylRadSmall));
+    final = smin(final, d, 0.1);
+
+    vec2 matd = vec2(final, fract((angle+time) / TAU+0.5));
+    float sliver = cyl(cylWarp.xy, 0.03);
+    glow += 1.0 / (sliver * sliver * sliver * sliver + 1.0);
+    //sliver = max(sliver, abs(fract(cylWarp.z*freq-2.0*localTime)-0.5)-0.3);
+    matd = matMin(matd, vec2(sliver, -1.0));
+    return matd;
+}
+
+// Input is UV coordinate of pixel to render.
+// Output is RGB color.
+vec3 RayTrace(in vec2 fragCoord )
+{
+    glow = 0.0;
+       // -------------------------------- animate ---------------------------------------
+       vec3 camPos, camUp, camLookat;
+       // ------------------- Set up the camera rays for ray marching --------------------
+    // Map uv to [-1.0..1.0]
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+    float zoom = 2.2;
+    uv /= zoom;
+
+    // Camera up vector.
+       camUp=vec3(0,1,0);
+
+       // Camera lookat.
+       camLookat=vec3(0);
+
+    // debugging camera
+    float mx=iMouse.x/iResolution.x*PI*2.0;
+       float my=-iMouse.y/iResolution.y*10.0;
+#ifndef MANUAL_CAMERA
+    camPos = vec3(0.0);
+    camPos.y = sin(localTime*0.125)*3.0;
+    camPos.z = cos(localTime*0.125)*3.0;
+    camUp.y = camPos.z;
+    camUp.z = -camPos.y;
+    camUp = normalize(camUp);
+#else
+       camPos = vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*3.0;
+#endif
+
+       // Camera setup.
+       vec3 camVec=normalize(camLookat - camPos);
+       vec3 sideNorm=normalize(cross(camUp, camVec));
+       vec3 upNorm=cross(camVec, sideNorm);
+       vec3 worldFacing=(camPos + camVec);
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;
+       vec3 rayVec = normalize(worldPix - camPos);
+
+       // ----------------------------- Ray march the scene ------------------------------
+       vec2 distMat = vec2(1.0, 0.0);
+       float t = 0.0 + Hash2d(uv)*1.6; // random dither glow by moving march count start position
+       const float maxDepth = 6.0; // farthest distance rays will travel
+       vec3 pos = vec3(0,0,0);
+    const float smallVal = 0.000625;
+    float marchCount = 0.0;
+       // ray marching time
+    for (int i = 0; i < 80; i++)       // This is the count of the max times the ray actually marches.
+    {
+        // Step along the ray.
+        pos = camPos + rayVec * t;
+        // This is _the_ function that defines the "distance field".
+        // It's really what makes the scene geometry. The idea is that the
+        // distance field returns the distance to the closest object, and then
+        // we know we are safe to "march" along the ray by that much distance
+        // without hitting anything. We repeat this until we get really close
+        // and then break because we have effectively hit the object.
+        distMat = DistanceToObject(pos);
+
+        // Move along the ray.
+        // Leave room for error by multiplying in case distance function isn't exact.
+        t += distMat.x * 0.8;
+        // If we are very close to the object, let's call it a hit and exit this loop.
+        if ((t > maxDepth) || (abs(distMat.x) < smallVal)) break;
+
+        // Glow if we're close to the part of the ring with the braid.
+        float cyc = (-sin(distMat.y * TAU))*0.5+0.7;
+        // This function is similar to a gaussian fall-off of glow when you're close
+        // to an object.
+        // http://thetamath.com/app/y=(1)/((x*x+1))
+        marchCount += cyc / (distMat.x * distMat.x + 1.0);
+    }
+
+       // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this geometry.
+
+    // Save off ray-march glows so they don't get messed up when we call the distance
+    // function again to get the normal
+       float glowSave = glow;
+    float marchSave = marchCount;
+    marchCount = 0.0;
+    glow = 0.0;
+
+    // default to blueish background color.
+       vec3 finalColor = vec3(0.09, 0.15, 0.35);
+
+       // If a ray actually hit the object, let's light it.
+    if (t <= maxDepth)
+       {
+        // calculate the normal from the distance field. The distance field is a volume, so if you
+        // sample the current point and neighboring points, you can use the difference to get
+        // the normal.
+        vec3 smallVec = vec3(smallVal, 0, 0);
+        vec3 normalU = vec3(distMat.x - DistanceToObject(pos - smallVec.xyy).x,
+                           distMat.x - DistanceToObject(pos - smallVec.yxy).x,
+                           distMat.x - DistanceToObject(pos - smallVec.yyx).x);
+
+        vec3 texColor = vec3(0.0, 0.0, 0.1);
+        if (distMat.y < 0.0) texColor = vec3(0.6, 0.3, 0.1)*110.0;
+
+        finalColor = texColor;
+        // visualize length of gradient of distance field to check distance field correctness
+        //finalColor = vec3(0.5) * (length(normalU) / smallVec.x);
+       }
+    // add the ray marching glows
+    finalColor += vec3(0.3, 0.5, 0.9) * glowSave*0.00625;
+    finalColor += vec3(1.0, 0.5, 0.3) * marchSave*0.05;
+
+    // vignette
+    finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
+
+       // output the final color without gamma correction - will do gamma later.
+       return vec3(saturate(finalColor));
+}
+
+#ifdef NON_REALTIME_HQ_RENDER
+// This function breaks the image down into blocks and scans
+// through them, rendering 1 block at a time. It's for non-
+// realtime things that take a long time to render.
+
+// This is the frame rate to render at. Too fast and you will
+// miss some blocks.
+const float blockRate = 20.0;
+void BlockRender(in vec2 fragCoord)
+{
+    // blockSize is how much it will try to render in 1 frame.
+    // adjust this smaller for more complex scenes, bigger for
+    // faster render times.
+    const float blockSize = 64.0;
+    // Make the block repeatedly scan across the image based on time.
+    float frame = floor(iTime * blockRate);
+    vec2 blockRes = floor(iResolution.xy / blockSize) + vec2(1.0);
+    // ugly bug with mod.
+    //float blockX = mod(frame, blockRes.x);
+    float blockX = fract(frame / blockRes.x) * blockRes.x;
+    //float blockY = mod(floor(frame / blockRes.x), blockRes.y);
+    float blockY = fract(floor(frame / blockRes.x) / blockRes.y) * blockRes.y;
+    // Don't draw anything outside the current block.
+    if ((fragCoord.x - blockX * blockSize >= blockSize) ||
+       (fragCoord.x - (blockX - 1.0) * blockSize < blockSize) ||
+       (fragCoord.y - blockY * blockSize >= blockSize) ||
+       (fragCoord.y - (blockY - 1.0) * blockSize < blockSize))
+    {
+        discard;
+    }
+}
+#endif
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+#ifdef NON_REALTIME_HQ_RENDER
+    // Optionally render a non-realtime scene with high quality
+    BlockRender(fragCoord);
+#endif
+
+    // Do a multi-pass render
+    vec3 finalColor = vec3(0.0);
+#ifdef NON_REALTIME_HQ_RENDER
+    for (float i = 0.0; i < antialiasingSamples; i++)
+    {
+        const float motionBlurLengthInSeconds = 1.0 / 60.0;
+        // Set this to the time in seconds of the frame to render.
+           localTime = frameToRenderHQ;
+        // This line will motion-blur the renders
+        localTime += Hash11(v21(fragCoord + seed)) * motionBlurLengthInSeconds;
+        // Jitter the pixel position so we get antialiasing when we do multiple passes.
+        vec2 jittered = fragCoord.xy + vec2(
+            Hash21(fragCoord + seed),
+            Hash21(fragCoord*7.234567 + seed)
+            );
+        // don't antialias if only 1 sample.
+        if (antialiasingSamples == 1.0) jittered = fragCoord;
+        // Accumulate one pass of raytracing into our pixel value
+           finalColor += RayTrace(jittered);
+        // Change the random seed for each pass.
+           seed *= 1.01234567;
+    }
+    // Average all accumulated pixel intensities
+    finalColor /= antialiasingSamples;
+#else
+    // Regular real-time rendering
+    localTime = iTime;
+    finalColor = RayTrace(fragCoord);
+#endif
+
+    fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
+
+
diff --git a/hacks/glx/glsl/fluxcore.glsl b/hacks/glx/glsl/fluxcore.glsl
new file mode 100644 (file)
index 0000000..b7aea57
--- /dev/null
@@ -0,0 +1,681 @@
+// Title:  Flux Core
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/ltlSWf
+// Date:   24-Aug-2015
+// Desc:   Long range space-based energy transmission requires a flux core to amplify and concentrate energy.
+// *** Try out the high quality non-realtime renderer. Feel free to use it for your shaders if you want to render screenshots.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+^ This means do ANYTHING YOU WANT with this code. Because we are programmers, not lawyers.
+-Otavio Good
+*/
+
+// ---------------- Config ----------------
+// This is an option that lets you render high quality frames for screenshots. It enables
+// stochastic antialiasing and motion blur automatically for any shader.
+//#define NON_REALTIME_HQ_RENDER
+const float frameToRenderHQ = 20.0; // Time in seconds of frame to render
+const float antialiasingSamples = 16.0; // 16x antialiasing - too much might make the shader compiler angry.
+
+//#define MANUAL_CAMERA
+
+
+#define ZERO_TRICK max(0, -iFrame)
+// --------------------------------------------------------
+// These variables are for the non-realtime block renderer.
+float localTime = 0.0;
+float seed = 1.0;
+
+// Animation variables
+float animStructure = 1.0;
+float fade = 1.0;
+
+// ---- noise functions ----
+float v31(vec3 a)
+{
+    return a.x + a.y * 37.0 + a.z * 521.0;
+}
+float v21(vec2 a)
+{
+    return a.x + a.y * 37.0;
+}
+float Hash11(float a)
+{
+    return fract(sin(a)*10403.9);
+}
+float Hash21(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(sin(f)*104003.9);
+}
+vec2 Hash22(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(cos(f)*vec2(10003.579, 37049.7));
+}
+vec2 Hash12(float f)
+{
+    return fract(cos(f)*vec2(10003.579, 37049.7));
+}
+float Hash1d(float u)
+{
+    return fract(sin(u)*143.9);        // scale this down to kill the jitters
+}
+float Hash2d(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(sin(f)*104003.9);
+}
+float Hash3d(vec3 uv)
+{
+    float f = uv.x + uv.y * 37.0 + uv.z * 521.0;
+    return fract(sin(f)*110003.9);
+}
+float mixP(float f0, float f1, float a)
+{
+    return mix(f0, f1, a*a*(3.0-2.0*a));
+}
+const vec2 zeroOne = vec2(0.0, 1.0);
+float noise2d(vec2 uv)
+{
+    vec2 fr = fract(uv.xy);
+    vec2 fl = floor(uv.xy);
+    float h00 = Hash2d(fl);
+    float h10 = Hash2d(fl + zeroOne.yx);
+    float h01 = Hash2d(fl + zeroOne);
+    float h11 = Hash2d(fl + zeroOne.yy);
+    return mixP(mixP(h00, h10, fr.x), mixP(h01, h11, fr.x), fr.y);
+}
+float noise(vec3 uv)
+{
+    vec3 fr = fract(uv.xyz);
+    vec3 fl = floor(uv.xyz);
+    float h000 = Hash3d(fl);
+    float h100 = Hash3d(fl + zeroOne.yxx);
+    float h010 = Hash3d(fl + zeroOne.xyx);
+    float h110 = Hash3d(fl + zeroOne.yyx);
+    float h001 = Hash3d(fl + zeroOne.xxy);
+    float h101 = Hash3d(fl + zeroOne.yxy);
+    float h011 = Hash3d(fl + zeroOne.xyy);
+    float h111 = Hash3d(fl + zeroOne.yyy);
+    return mixP(
+        mixP(mixP(h000, h100, fr.x),
+             mixP(h010, h110, fr.x), fr.y),
+        mixP(mixP(h001, h101, fr.x),
+             mixP(h011, h111, fr.x), fr.y)
+        , fr.z);
+}
+
+const float PI=3.14159265;
+
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+
+vec3 RotateX(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(v.x, cos * v.y + sin * v.z, -sin * v.y + cos * v.z);
+}
+vec3 RotateY(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(cos * v.x - sin * v.z, v.y, sin * v.x + cos * v.z);
+}
+vec3 RotateZ(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(cos * v.x + sin * v.y, -sin * v.x + cos * v.y, v.z);
+}
+
+// This spiral noise works by successively adding and rotating sin waves while increasing frequency.
+// It should work the same on all computers since it's not based on a hash function like some other noises.
+// It can be much faster than other noise functions if you're ok with some repetition.
+const float nudge = 0.71;      // size of perpendicular vector
+float normalizer = 1.0 / sqrt(1.0 + nudge*nudge);      // pythagorean theorem on that perpendicular to maintain scale
+// Total hack of the spiral noise function to get a rust look
+float RustNoise3D(vec3 p)
+{
+    float n = 0.0;
+    float iter = 1.0;
+    float pn = noise(p*0.125);
+    pn += noise(p*0.25)*0.5;
+    pn += noise(p*0.5)*0.25;
+    pn += noise(p*1.0)*0.125;
+    for (int i = ZERO_TRICK; i < 7; i++)
+    {
+        //n += (sin(p.y*iter) + cos(p.x*iter)) / iter;
+        float wave = saturate(cos(p.y*0.25 + pn) - 0.998);
+        wave *= noise(p * 0.125)*1016.0;
+        n += wave;
+        p.xy += vec2(p.y, -p.x) * nudge;
+        p.xy *= normalizer;
+        p.xz += vec2(p.z, -p.x) * nudge;
+        p.xz *= normalizer;
+        iter *= 1.4733;
+    }
+    return n;
+}
+
+// ---- functions to remap / warp space ----
+float repsDouble(float a)
+{
+    return abs(a * 2.0 - 1.0);
+}
+vec2 repsDouble(vec2 a)
+{
+    return abs(a * 2.0 - 1.0);
+}
+
+vec2 mapSpiralMirror(vec2 uv)
+{
+    float len = length(uv);
+    float at = atan(uv.x, uv.y);
+    at = at / PI;
+    float dist = (fract(log(len)+at*0.5)-0.5) * 2.0;
+    at = repsDouble(at);
+    at = repsDouble(at);
+    return vec2(abs(dist), abs(at));
+}
+
+vec2 mapSpiral(vec2 uv)
+{
+    float len = length(uv);
+    float at = atan(uv.x, uv.y);
+    at = at / PI;
+    float dist = (fract(log(len)+at*0.5)-0.5) * 2.0;
+    //dist += sin(at*32.0)*0.05;
+    // at is [-1..1]
+    // dist is [-1..1]
+    at = repsDouble(at);
+    at = repsDouble(at);
+    return vec2(dist, at);
+}
+
+vec2 mapCircleInvert(vec2 uv)
+{
+    float len = length(uv);
+    float at = atan(uv.x, uv.y);
+    //at = at / PI;
+    //return uv;
+    len = 1.0 / len;
+    return vec2(sin(at)*len, cos(at)*len);
+}
+
+vec3 mapSphereInvert(vec3 uv)
+{
+    float len = length(uv);
+    vec3 dir = normalize(uv);
+    len = 1.0 / len;
+    return dir * len;
+}
+
+// ---- shapes defined by distance fields ----
+// See this site for a reference to more distance functions...
+// https://iquilezles.org/articles/distfunctions
+float length8(vec2 v)
+{
+       return pow(pow(abs(v.x),8.0) + pow(abs(v.y), 8.0), 1.0/8.0);
+}
+
+// box distance field
+float sdBox(vec3 p, vec3 radius)
+{
+  vec3 dist = abs(p) - radius;
+  return min(max(dist.x, max(dist.y, dist.z)), 0.0) + length(max(dist, 0.0));
+}
+
+// Makes a warped torus that rotates around
+float sdTorusWobble( vec3 p, vec2 t, float offset)
+{
+       float a = atan(p.x, p.z);
+    float subs = 2.0;
+       a = sin(a*subs+localTime*4.0+offset*3.234567);
+       vec2 q = vec2(length(p.xz)-t.x-a*0.1,p.y);
+       return length8(q)-t.y;
+}
+
+// simple cylinder distance field
+float cyl(vec2 p, float r)
+{
+    return length(p) - r;
+}
+
+float glow = 0.0, glow2 = 0.0, glow3 = 0.0;
+float pulse;
+// This is the big money function that makes the crazy fractally shape
+// The input is a position in space.
+// The output is the distance to the nearest surface.
+float DistanceToObject(vec3 p)
+{
+    vec3 orig = p;
+    // Magically remap space to be in a spiral
+    p.yz = mapSpiralMirror(p.yz);
+    // Mix between spiral space and unwarped space. This changes the scene
+    // from the tunnel to the spiral.
+    p = mix(orig, p, animStructure);
+//    p = mix(p, orig, cos(localTime)*0.5+0.5);
+
+    // Cut out stuff outside of outer radius
+       const float outerRad = 3.5;
+    float lenXY = length(p.xy);
+    float final = lenXY - outerRad;
+    // Carve out inner radius
+    final = max(final, -(lenXY - (outerRad-0.65)));
+
+    // Slice the object in a 3d grid
+    float slice = 0.04;
+    vec3 grid = -abs(fract(p)-0.5) + slice;
+    //final = max(final, grid.x);
+    //final = max(final, grid.y);
+    final = max(final, grid.z);
+
+    // Carve out cylinders from the object on all 3 axis, scaled 3 times
+    // This gives it the fractal look.
+    vec3 rep = fract(p)-0.5;
+    float scale = 1.0;
+    float mult = 0.32;
+    for (int i = ZERO_TRICK; i < 3; i++)
+    {
+        float uglyDivider = max(1.0, float(i));        // wtf is this? My math sucks :(
+        // carve out 3 cylinders
+        float dist = cyl(rep.xz/scale, mult/scale)/uglyDivider;
+        final = max(final, -dist);
+        dist = cyl(rep.xy/scale, mult/scale)/uglyDivider;
+        final = max(final, -dist);
+        dist = cyl(rep.yz/scale, mult/scale)/uglyDivider;
+        final = max(final, -dist);
+        // Scale and repeat.
+        scale *= 1.14+1.0;// + sin(localTime)*0.995;
+        rep = fract(rep*scale) - 0.5;
+    }
+
+    // Make radial struts that poke into the center of the spiral
+    vec3 sp = p;
+    sp.x = abs(sp.x)-5.4;
+    sp.z = fract(sp.z) - 0.5;
+    // Bad distance field on these makes them sometimes disappear. Math. :(
+    float struts = sdBox(sp+vec3(2.95, 0.1-sin(sp.x*2.0)*1.1, 0.0), vec3(1.5, 0.05, 0.02))*0.5;
+    //glow3 += (0.00005)/max(0.01, struts);
+    final = min(final, struts);
+
+    // Make spiral glows that rotate and pulse energy to the center
+    rep.yz = (fract(p.yz)-0.5);
+    rep.x = p.x;
+    scale = 1.14+1.0;
+    float jolt = max(0.0, sin(length(orig.yz) + localTime*20.0))*0.94;
+    jolt *= saturate(0.3-pulse);
+    float spiral = sdBox(RotateX(rep+vec3(-0.05,0.0,0.0), pulse), vec3(0.01+jolt,1.06, mult*0.01)/scale );
+    glow3 += (0.0018)/max(0.0025,spiral);
+    final = min(final, spiral + (1.0-animStructure) * 100.0);
+
+    // Make a warped torus that rotates around and glows orange
+    vec3 rp = p.xzy;
+    rp.x = -abs(rp.x);
+    rp.y = fract(rp.y) - 0.5;
+    float torus = sdTorusWobble(rp + vec3(3.0, 0.0, 0.0), vec2(0.2, 0.0003), p.z);
+    glow2 += 0.0015 / max(0.03, torus);
+    final = min(final, torus);
+
+    // Make the glowing tower in the center.
+    // This also gives a bit of a glow to everything.
+    glow += (0.02+abs(sin(orig.x-localTime*3.0)*0.15)*jolt )/length(orig.yz);
+
+    return final;
+}
+
+// Input is UV coordinate of pixel to render.
+// Output is RGB color.
+vec3 RayTrace(in vec2 fragCoord )
+{
+    glow = 0.0;
+    glow2 = 0.0;
+    glow3 = 0.0;
+       // -------------------------------- animate ---------------------------------------
+    // Default to spiral shape
+    animStructure = 1.0;
+
+    // Make a cycling, clamped sin wave to animate the glow-spiral rotation.
+    float slt = sin(localTime);
+    float stepLike = pow(abs(slt), 0.75)*sign(slt);
+    stepLike = max(-1.0, min(1.0, stepLike*1.5));
+    pulse = stepLike*PI/4.0 + PI/4.0;
+
+       vec3 camPos, camUp, camLookat;
+       // ------------------- Set up the camera rays for ray marching --------------------
+    // Map uv to [-1.0..1.0]
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+
+#ifdef MANUAL_CAMERA
+    // Camera up vector.
+       camUp=vec3(0,1,0);
+
+       // Camera lookat.
+       camLookat=vec3(0,0.0,0);
+
+    // debugging camera
+    float mx=iMouse.x/iResolution.x*PI*2.0;// + localTime * 0.166;
+       float my=-iMouse.y/iResolution.y*10.0;// + sin(localTime * 0.3)*0.8+0.1;//*PI/2.01;
+       camPos = vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*8.35;
+#else
+    // Do the camera fly-by animation and different scenes.
+    // Time variables for start and end of each scene
+    const float t0 = 0.0;
+    const float t1 = 9.0;
+    const float t2 = 16.0;
+    const float t3 = 24.0;
+    const float t4 = 40.0;
+    const float t5 = 48.0;
+    const float t6 = 70.0;
+    // Repeat the animation after time t6
+    localTime = fract(localTime / t6) * t6;
+    /*const float t0 = 0.0;
+    const float t1 = 0.0;
+    const float t2 = 0.0;
+    const float t3 = 0.0;
+    const float t4 = 0.0;
+    const float t5 = 0.0;
+    const float t6 = 18.0;*/
+    if (localTime < t1)
+    {
+           animStructure = 0.0;
+        float time = localTime - t0;
+        float alpha = time / (t1 - t0);
+        fade = saturate(time);
+        fade *= saturate(t1 - localTime);
+        camPos = vec3(56.0, -2.5, 1.5);
+        camPos.x -= alpha * 6.8;
+        camUp=vec3(0,1,0);
+        camLookat=vec3(50,0.0,0);
+    } else if (localTime < t2)
+    {
+       animStructure = 0.0;
+        float time = localTime - t1;
+        float alpha = time / (t2 - t1);
+        fade = saturate(time);
+        fade *= saturate(t2 - localTime);
+        camPos = vec3(12.0, 3.3, -0.5);
+        camPos.x -= smoothstep(0.0, 1.0, alpha) * 4.8;
+        camUp=vec3(0,1,0);
+        camLookat=vec3(0,5.5,-0.5);
+    } else if (localTime < t3)
+    {
+        animStructure = 1.0;
+        float time = localTime - t2;
+        float alpha = time / (t3 - t2);
+        fade = saturate(time);
+        fade *= saturate(t3 - localTime);
+        camPos = vec3(12.0, 6.3, -0.5);
+        camPos.y -= alpha * 1.8;
+        camPos.x = cos(alpha*1.0) * 6.3;
+        camPos.z = sin(alpha*1.0) * 6.3;
+        camUp=normalize(vec3(0,1,-0.3 - alpha * 0.5));
+        camLookat=vec3(0,0.0,-0.5);
+    } else if (localTime < t4)
+    {
+        animStructure = 1.0;
+        float time = localTime - t3;
+        float alpha = time / (t4 - t3);
+        fade = saturate(time);
+        fade *= saturate(t4 - localTime);
+        camPos = vec3(12.0, 3.0, -2.6);
+        camPos.y -= alpha * 1.8;
+        camPos.x = cos(alpha*1.0) * 6.5-alpha*0.25;
+        camPos.z += sin(alpha*1.0) * 6.5-alpha*0.25;
+        camUp=normalize(vec3(0,1,0.0));
+        camLookat=vec3(0,0.0,-0.0);
+    } else if (localTime < t5)
+    {
+        animStructure = 1.0;
+        float time = localTime - t4;
+        float alpha = time / (t5 - t4);
+        fade = saturate(time);
+        fade *= saturate(t5 - localTime);
+        camPos = vec3(0.0, -7.0, -0.9);
+        camPos.y -= alpha * 1.8;
+        camPos.x = cos(alpha*1.0) * 1.5-alpha*1.5;
+        camPos.z += sin(alpha*1.0) * 1.5-alpha*1.5;
+        camUp=normalize(vec3(0,1,0.0));
+        camLookat=vec3(0,-3.0,-0.0);
+    } else if (localTime < t6)
+    {
+        float time = localTime - t5;
+        float alpha = time / (t6 - t5);
+        float smoothv = smoothstep(0.0, 1.0, saturate(alpha*1.8-0.1));
+        animStructure = 1.0-smoothv;
+        fade = saturate(time);
+        fade *= saturate(t6 - localTime);
+        camPos = vec3(10.0, -0.95+smoothv*1.0, 0.0);
+        camPos.x -= alpha * 6.8;
+        camUp=normalize(vec3(0,1.0-smoothv,0.0+smoothv));
+        camLookat=vec3(0,-0.0,-0.0);
+    }
+#endif
+
+       // Camera setup.
+       vec3 camVec=normalize(camLookat - camPos);
+       vec3 sideNorm=normalize(cross(camUp, camVec));
+       vec3 upNorm=cross(camVec, sideNorm);
+       vec3 worldFacing=(camPos + camVec);
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;
+       vec3 rayVec = normalize(worldPix - camPos);
+
+       // ----------------------------- Ray march the scene ------------------------------
+       float dist = 1.0;
+       float t = 0.1 + Hash2d(uv)*0.1; // random dither-fade things close to the camera
+       const float maxDepth = 45.0; // farthest distance rays will travel
+       vec3 pos = vec3(0,0,0);
+    const float smallVal = 0.000625;
+       // ray marching time
+    for (int i = ZERO_TRICK; i < 210; i++)     // This is the count of the max times the ray actually marches.
+    {
+        // Step along the ray. Switch x, y, and z because I messed up the orientation.
+        pos = (camPos + rayVec * t).yzx;
+        // This is _the_ function that defines the "distance field".
+        // It's really what makes the scene geometry. The idea is that the
+        // distance field returns the distance to the closest object, and then
+        // we know we are safe to "march" along the ray by that much distance
+        // without hitting anything. We repeat this until we get really close
+        // and then break because we have effectively hit the object.
+        dist = DistanceToObject(pos);
+        // This makes the ray trace more precisely in the center so it will not miss the
+        // vertical glowy beam.
+        dist = min(dist, length(pos.yz));
+
+        t += dist;
+        // If we are very close to the object, let's call it a hit and exit this loop.
+        if ((t > maxDepth) || (abs(dist) < smallVal)) break;
+    }
+
+       // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this geometry.
+       float glowSave = glow;
+       float glow2Save = glow2;
+       float glow3Save = glow3;
+
+       vec3 sunDir = normalize(vec3(0.93, 1.0, -1.5));
+       vec3 finalColor = vec3(0.0);
+
+       // If a ray actually hit the object, let's light it.
+    if (t <= maxDepth)
+       {
+        // calculate the normal from the distance field. The distance field is a volume, so if you
+        // sample the current point and neighboring points, you can use the difference to get
+        // the normal.
+        vec3 smallVec = vec3(smallVal, 0, 0);
+        vec3 normalU = vec3(dist - DistanceToObject(pos - smallVec.xyy),
+                           dist - DistanceToObject(pos - smallVec.yxy),
+                           dist - DistanceToObject(pos - smallVec.yyx));
+        vec3 normal = normalize(normalU);
+
+        // calculate 2 ambient occlusion values. One for global stuff and one
+        // for local stuff
+        float ambientS = 1.0;
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.05)*20.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.1)*10.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.2)*5.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.4)*2.5);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.8)*1.25);
+        float ambient = ambientS * saturate(DistanceToObject(pos + normal * 1.6)*1.25*0.5);
+        //ambient *= saturate(DistanceToObject(pos + normal * 3.2)*1.25*0.25);
+        //ambient *= saturate(DistanceToObject(pos + normal * 6.4)*1.25*0.125);
+        //ambient = max(0.05, pow(ambient, 0.3));      // tone down ambient with a pow and min clamp it.
+        ambient = saturate(ambient);
+
+        // calculate the reflection vector for highlights
+        //vec3 ref = reflect(rayVec, normal);
+
+        // Trace a ray toward the sun for sun shadows
+        float sunShadow = 1.0;
+        float iter = 0.01;
+        vec3 nudgePos = pos + normal*0.002;    // don't start tracing too close or inside the object
+               for (int i = ZERO_TRICK; i < 30; i++)
+        {
+            float tempDist = DistanceToObject(nudgePos + sunDir * iter);
+               sunShadow *= saturate(tempDist*150.0);  // Shadow hardness
+            if (tempDist <= 0.0) break;
+            //iter *= 1.5;     // constant is more reliable than distance-based
+            iter += max(0.01, tempDist)*1.0;
+            if (iter > 4.2) break;
+        }
+        sunShadow = saturate(sunShadow);
+
+        // make a few frequencies of noise to give it some texture
+        float n =0.0;
+        n += noise(pos*32.0);
+        n += noise(pos*64.0);
+        n += noise(pos*128.0);
+        n += noise(pos*256.0);
+        n += noise(pos*512.0);
+        n *= 0.8;
+        normal = normalize(normal + (n-2.0)*0.1);
+
+        // ------ Calculate texture color  ------
+        vec3 texColor = vec3(0.95, 1.0, 1.0);
+        vec3 rust = vec3(0.65, 0.25, 0.1) - noise(pos*128.0);
+        // Call the function that makes rust stripes on the texture
+        texColor *= smoothstep(texColor, rust, vec3(saturate(RustNoise3D(pos*8.0))-0.2));
+
+        // apply noise
+        texColor *= vec3(1.0)*n*0.05;
+        texColor *= 0.7;
+        texColor = saturate(texColor);
+
+        // ------ Calculate lighting color ------
+        // Start with sun color, standard lighting equation, and shadow
+        vec3 lightColor = vec3(3.6) * saturate(dot(sunDir, normal)) * sunShadow;
+        // weighted average the near ambient occlusion with the far for just the right look
+        float ambientAvg = (ambient*3.0 + ambientS) * 0.25;
+        // a red and blue light coming from different directions
+        lightColor += (vec3(1.0, 0.2, 0.4) * saturate(-normal.z *0.5+0.5))*pow(ambientAvg, 0.35);
+        lightColor += (vec3(0.1, 0.5, 0.99) * saturate(normal.y *0.5+0.5))*pow(ambientAvg, 0.35);
+        // blue glow light coming from the glow in the middle
+        lightColor += vec3(0.3, 0.5, 0.9) * saturate(dot(-pos, normal))*pow(ambientS, 0.3);
+        lightColor *= 4.0;
+
+        // finally, apply the light to the texture.
+        finalColor = texColor * lightColor;
+        // sun reflection to make it look metal
+        //finalColor += vec3(1.0)*pow(n,4.0)* GetSunColorSmall(ref, sunDir) * sunShadow;// * ambientS;
+        // visualize length of gradient of distance field to check distance field correctness
+        //finalColor = vec3(0.5) * (length(normalU) / smallVec.x);
+       }
+    else
+    {
+        // Our ray trace hit nothing, so draw sky.
+    }
+    // add the ray marching glows
+    float center = length(pos.yz);
+    finalColor += vec3(0.3, 0.5, 0.9) * glowSave*1.2;
+    finalColor += vec3(0.9, 0.5, 0.3) * glow2*1.2;
+    finalColor += vec3(0.25, 0.29, 0.93) * glow3Save*2.0;
+
+    // vignette?
+    finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
+    finalColor *= 1.0;// 1.3;
+
+       // output the final color without gamma correction - will do gamma later.
+       return vec3(clamp(finalColor, 0.0, 1.0)*saturate(fade+0.25));
+}
+
+#ifdef NON_REALTIME_HQ_RENDER
+// This function breaks the image down into blocks and scans
+// through them, rendering 1 block at a time. It's for non-
+// realtime things that take a long time to render.
+
+// This is the frame rate to render at. Too fast and you will
+// miss some blocks.
+const float blockRate = 20.0;
+void BlockRender(in vec2 fragCoord)
+{
+    // blockSize is how much it will try to render in 1 frame.
+    // adjust this smaller for more complex scenes, bigger for
+    // faster render times.
+    const float blockSize = 64.0;
+    // Make the block repeatedly scan across the image based on time.
+    float frame = floor(iTime * blockRate);
+    vec2 blockRes = floor(iResolution.xy / blockSize) + vec2(1.0);
+    // ugly bug with mod.
+    //float blockX = mod(frame, blockRes.x);
+    float blockX = fract(frame / blockRes.x) * blockRes.x;
+    //float blockY = mod(floor(frame / blockRes.x), blockRes.y);
+    float blockY = fract(floor(frame / blockRes.x) / blockRes.y) * blockRes.y;
+    // Don't draw anything outside the current block.
+    if ((fragCoord.x - blockX * blockSize >= blockSize) ||
+       (fragCoord.x - (blockX - 1.0) * blockSize < blockSize) ||
+       (fragCoord.y - blockY * blockSize >= blockSize) ||
+       (fragCoord.y - (blockY - 1.0) * blockSize < blockSize))
+    {
+        discard;
+    }
+}
+#endif
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+#ifdef NON_REALTIME_HQ_RENDER
+    // Optionally render a non-realtime scene with high quality
+    BlockRender(fragCoord);
+#endif
+
+    // Do a multi-pass render
+    vec3 finalColor = vec3(0.0);
+#ifdef NON_REALTIME_HQ_RENDER
+    for (float i = 0.0; i < antialiasingSamples; i++)
+    {
+        const float motionBlurLengthInSeconds = 1.0 / 60.0;
+        // Set this to the time in seconds of the frame to render.
+           localTime = frameToRenderHQ;
+        // This line will motion-blur the renders
+        localTime += Hash11(v21(fragCoord + seed)) * motionBlurLengthInSeconds;
+        // Jitter the pixel position so we get antialiasing when we do multiple passes.
+        vec2 jittered = fragCoord.xy + vec2(
+            Hash21(fragCoord + seed),
+            Hash21(fragCoord*7.234567 + seed)
+            );
+        // don't antialias if only 1 sample.
+        if (antialiasingSamples == 1.0) jittered = fragCoord;
+        // Accumulate one pass of raytracing into our pixel value
+           finalColor += RayTrace(jittered);
+        // Change the random seed for each pass.
+           seed *= 1.01234567;
+    }
+    // Average all accumulated pixel intensities
+    finalColor /= antialiasingSamples;
+#else
+    // Regular real-time rendering
+    localTime = iTime;
+    finalColor = RayTrace(fragCoord);
+#endif
+
+    fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
+
+
diff --git a/hacks/glx/glsl/gimbalharmonics.glsl b/hacks/glx/glsl/gimbalharmonics.glsl
new file mode 100644 (file)
index 0000000..de1224c
--- /dev/null
@@ -0,0 +1,320 @@
+// Title:  Gimbal Harmonics
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/llS3zd
+// Date:   12-May-2015
+// Desc:   I like visualizations of different frequencies next to each other. So I tried one with discs. I stuck with the same lighting and materials as my last shader.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+^This means do anything you want with this code. Because we are programmers, not lawyers.
+
+-Otavio Good
+*/
+
+float localTime = 0.0;
+float marchCount;
+
+float PI=3.14159265;
+
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+
+vec3 RotateX(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(v.x, cos * v.y + sin * v.z, -sin * v.y + cos * v.z);
+}
+vec3 RotateY(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(cos * v.x - sin * v.z, v.y, sin * v.x + cos * v.z);
+}
+vec3 RotateZ(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(cos * v.x + sin * v.y, -sin * v.x + cos * v.y, v.z);
+}
+
+
+/*vec3 GetEnvColor(vec3 rayDir, vec3 sunDir)
+{
+       vec3 tex = texture(iChannel0, rayDir).xyz;
+       tex = tex * tex;        // gamma correct
+    return tex;
+}*/
+
+// This is a procedural environment map with a giant overhead softbox,
+// 4 lights in a horizontal circle, and a bottom-to-top fade.
+vec3 GetEnvColor2(vec3 rayDir, vec3 sunDir)
+{
+    // fade bottom to top so it looks like the softbox is casting light on a floor
+    // and it's bouncing back
+    vec3 final = vec3(1.0) * dot(-rayDir, sunDir) * 0.5 + 0.5;
+    final *= 0.125;
+    // overhead softbox, stretched to a rectangle
+    if ((rayDir.y > abs(rayDir.x)*1.0) && (rayDir.y > abs(rayDir.z*0.25))) final = vec3(2.0)*rayDir.y;
+    // fade the softbox at the edges with a rounded rectangle.
+    float roundBox = length(max(abs(rayDir.xz/max(0.0,rayDir.y))-vec2(0.9, 4.0),0.0))-0.1;
+    final += vec3(0.8)* pow(saturate(1.0 - roundBox*0.5), 6.0);
+    // purple lights from side
+    final += vec3(8.0,6.0,7.0) * saturate(0.001/(1.0 - abs(rayDir.x)));
+    // yellow lights from side
+    final += vec3(8.0,7.0,6.0) * saturate(0.001/(1.0 - abs(rayDir.z)));
+    return vec3(final);
+}
+
+/*vec3 GetEnvColorReflection(vec3 rayDir, vec3 sunDir, float ambient)
+{
+       vec3 tex = texture(iChannel0, rayDir).xyz;
+       tex = tex * tex;
+    vec3 texBack = texture(iChannel0, rayDir).xyz;
+    vec3 texDark = pow(texBack, vec3(50.0)).zzz;       // fake hdr texture
+    texBack += texDark*0.5 * ambient;
+    return texBack*texBack*texBack;
+}*/
+
+vec3 camPos = vec3(0.0), camFacing;
+vec3 camLookat=vec3(0,0.0,0);
+
+// polynomial smooth min (k = 0.1);
+float smin( float a, float b, float k )
+{
+    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
+    return mix( b, a, h ) - k*h*(1.0-h);
+}
+
+vec2 matMin(vec2 a, vec2 b)
+{
+       if (a.x < b.x) return a;
+       else return b;
+}
+
+float spinTime;
+
+const float thick = 0.85;
+const float spacer = 0.01;
+const float thickSpace = thick - spacer;
+float Disc(vec3 p, float scale)
+{
+    float len = length(p.xz);
+    // infinite cylinder
+    float dist = len - scale;
+    // cut out the inner disc
+    dist = max(dist, -(len - thick*scale));
+    //dist = max(dist, -(length(p.xz + vec2(thick*scale, 0.0)) - thick*scale*0.15));
+    // cut off half the disc because that looks cool maybe.
+    dist = max(dist, -p.z);
+    // make it flat, but with nice rounded edges so reflections look good. (slow)
+    dist = -smin(-dist, -(abs(p.y)-0.025), 0.015*scale);
+    //dist = max(dist, abs(p.y)-0.025);
+    return dist;
+}
+
+// Calculate the distance field that defines the object.
+vec2 DistanceToObject(vec3 p)
+{
+    float dist = 1000000.0;
+    float currentThick = 8.0;
+    float harmonicTime = spinTime*0.125*3.14159*4.0;
+    // make 15 discs inside each other
+    for (int i = 0; i < 15; i++)
+    {
+        dist = min(dist, Disc(p, currentThick));
+        p = RotateX(p, harmonicTime);
+        p = RotateZ(p, harmonicTime);
+        // scale down a level
+        currentThick *= thickSpace;
+    }
+    vec2 distMat = vec2(dist, 0.0);
+    // ball in center
+    distMat = matMin(distMat, vec2(length(p) - 0.45, 6.0));
+    return distMat;
+}
+
+// dirVec MUST BE NORMALIZED FIRST!!!!
+float SphereIntersect(vec3 pos, vec3 dirVecPLZNormalizeMeFirst, vec3 spherePos, float rad)
+{
+    vec3 radialVec = pos - spherePos;
+    float b = dot(radialVec, dirVecPLZNormalizeMeFirst);
+    float c = dot(radialVec, radialVec) - rad * rad;
+    float h = b * b - c;
+    if (h < 0.0) return -1.0;
+    return -b - sqrt(h);
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+    localTime = iTime - 0.0;
+       // ---------------- First, set up the camera rays for ray marching ----------------
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+    float zoom = 1.7;
+    uv /= zoom;
+
+       // Camera up vector.
+       vec3 camUp=vec3(0,1,0);
+
+       // Camera lookat.
+       camLookat=vec3(0,0.0,0);
+
+    // debugging camera
+    float mx=iMouse.x/iResolution.x*PI*2.0-0.7 + localTime*3.1415 * 0.0625*0.666;
+       float my=-iMouse.y/iResolution.y*10.0 - sin(localTime * 0.31)*0.5;//*PI/2.01;
+       camPos += vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*(12.2);
+
+       // Camera setup.
+       vec3 camVec=normalize(camLookat - camPos);
+       vec3 sideNorm=normalize(cross(camUp, camVec));
+       vec3 upNorm=cross(camVec, sideNorm);
+       vec3 worldFacing=(camPos + camVec);
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;
+       vec3 rayVec = normalize(worldPix - camPos);
+
+       // ----------------------------------- Animate ------------------------------------
+    localTime = iTime*0.125;
+    // This is a wave function like a triangle wave, but with flat tops and bottoms.
+    // period is 1.0
+    float rampStep = min(3.0,max(1.0, abs((fract(localTime)-0.5)*1.0)*8.0))*0.5-0.5;
+    rampStep = smoothstep(0.0, 1.0, rampStep);
+    // lopsided triangle wave - goes up for 3 time units, down for 1.
+    float step31 = (max(0.0, (fract(localTime+0.125)-0.25)) - min(0.0,(fract(localTime+0.125)-0.25))*3.0)*0.333;
+
+    spinTime = step31 + localTime - 0.125;
+       // --------------------------------------------------------------------------------
+       vec2 distAndMat = vec2(0.5, 0.0);
+       float t = 0.0;
+       //float inc = 0.02;
+       float maxDepth = 21.0;
+       vec3 pos = vec3(0,0,0);
+    marchCount = 0.0;
+    // intersect with sphere first as optimization so we don't ray march more than is needed.
+    float hit = SphereIntersect(camPos, rayVec, vec3(0.0), 8.0);
+    if (hit >= 0.0)
+    {
+        t = hit;
+        // ray marching time
+        for (int i = 0; i < 120; i++)  // This is the count of the max times the ray actually marches.
+        {
+            pos = camPos + rayVec * t;
+            // *******************************************************
+            // This is _the_ function that defines the "distance field".
+            // It's really what makes the scene geometry.
+            // *******************************************************
+            distAndMat = DistanceToObject(pos);
+            // move along the ray
+            t += distAndMat.x;
+            if ((t > maxDepth) || (abs(distAndMat.x) < 0.0025)) break;
+            //marchCount+= 1.0;
+        }
+    }
+    else
+    {
+        t = maxDepth + 1.0;
+        distAndMat.x = 1000000.0;
+    }
+    // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this geometry.
+
+       vec3 sunDir = normalize(vec3(3.93, 10.82, -1.5));
+       vec3 finalColor = vec3(0.0);
+
+       // If a ray actually hit the object, let's light it.
+       //if (abs(distAndMat.x) < 0.75)
+    if (t <= maxDepth)
+       {
+        // calculate the normal from the distance field. The distance field is a volume, so if you
+        // sample the current point and neighboring points, you can use the difference to get
+        // the normal.
+        vec3 smallVec = vec3(0.005, 0, 0);
+        vec3 normalU = vec3(distAndMat.x - DistanceToObject(pos - smallVec.xyy).x,
+                           distAndMat.x - DistanceToObject(pos - smallVec.yxy).x,
+                           distAndMat.x - DistanceToObject(pos - smallVec.yyx).x);
+
+        vec3 normal = normalize(normalU);
+
+        // calculate 2 ambient occlusion values. One for global stuff and one
+        // for local stuff
+        float ambientS = 1.0;
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.1).x*10.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.2).x*5.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.4).x*2.5);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.8).x*1.25);
+        float ambient = ambientS * saturate(DistanceToObject(pos + normal * 1.6).x*1.25*0.5);
+        ambient *= saturate(DistanceToObject(pos + normal * 3.2).x*1.25*0.25);
+        ambient *= saturate(DistanceToObject(pos + normal * 6.4).x*1.25*0.125);
+        ambient = max(0.035, pow(ambient, 0.3));       // tone down ambient with a pow and min clamp it.
+        ambient = saturate(ambient);
+
+        // calculate the reflection vector for highlights
+        vec3 ref = reflect(rayVec, normal);
+        ref = normalize(ref);
+
+        // Trace a ray for the reflection
+        float sunShadow = 1.0;
+        float iter = 0.1;
+        vec3 nudgePos = pos + ref*0.3;// normal*0.02;  // don't start tracing too close or inside the object
+               for (int i = 0; i < 40; i++)
+        {
+            float tempDist = DistanceToObject(nudgePos + ref * iter).x;
+               sunShadow *= saturate(tempDist*50.0);
+            if (tempDist <= 0.0) break;
+            //iter *= 1.5;     // constant is more reliable than distance-based
+            iter += max(0.00, tempDist)*1.0;
+            if (iter > 9.0) break;
+        }
+        sunShadow = saturate(sunShadow);
+
+        // ------ Calculate texture color ------
+        vec3 texColor;
+        texColor = vec3(1.0);// vec3(0.65, 0.5, 0.4)*0.1;
+        texColor = vec3(0.85, 0.945 - distAndMat.y * 0.15, 0.93 + distAndMat.y * 0.35)*0.951;
+        if (distAndMat.y == 6.0) texColor = vec3(0.91, 0.1, 0.41)*10.5;
+        //texColor *= mix(vec3(0.3), vec3(1.0), tex3d(pos*0.5, normal).xxx);
+        texColor = max(texColor, vec3(0.0));
+        texColor *= 0.25;
+        //texColor += vec3(1.0, 0.0, 0.0) * 8.0/length(pos);
+
+        // ------ Calculate lighting color ------
+        // Start with sun color, standard lighting equation, and shadow
+        vec3 lightColor = vec3(0.0);// sunCol * saturate(dot(sunDir, normal)) * sunShadow*14.0;
+        // sky color, hemisphere light equation approximation, ambient occlusion
+        lightColor += vec3(0.1,0.35,0.95) * (normal.y * 0.5 + 0.5) * ambient * 0.2;
+        // ground color - another hemisphere light
+        lightColor += vec3(1.0) * ((-normal.y) * 0.5 + 0.5) * ambient * 0.2;
+
+
+        // finally, apply the light to the texture.
+        finalColor = texColor * lightColor;
+       // if (distAndMat.y == 6.0) finalColor += vec3(0.91, 0.032, 0.01)*0.2;
+        //if (distAndMat.y == ceil(mod(localTime, 4.0))) finalColor += vec3(0.0, 0.41, 0.72)*0.925;
+
+        // reflection environment map - this is most of the light
+        vec3 refColor = GetEnvColor2(ref, sunDir)*sunShadow;// * (length(normalU)/smallVec.x-0.875)*8.0;
+        finalColor += refColor * 0.35 * ambient;// * sunCol * sunShadow * 9.0 * texColor.g;
+
+        // fog
+               finalColor = mix(vec3(1.0, 0.41, 0.41) + vec3(1.0), finalColor, exp(-t*0.0007));
+        // visualize length of gradient of distance field to check distance field correctness
+        //finalColor = vec3(0.5) * (length(normalU) / smallVec.x);
+       }
+    else
+    {
+           finalColor = GetEnvColor2(rayVec, sunDir);// + vec3(0.1, 0.1, 0.1);
+    }
+    //finalColor += marchCount * vec3(1.0, 0.3, 0.91) * 0.001;
+
+    // vignette?
+    //finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
+    //finalColor *= 1.2;
+
+       // output the final color with sqrt for "gamma correction"
+       fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
+
+
diff --git a/hacks/glx/glsl/hexplasma.glsl b/hacks/glx/glsl/hexplasma.glsl
new file mode 100644 (file)
index 0000000..caf7c8e
--- /dev/null
@@ -0,0 +1,57 @@
+// Title:  Hexagon Plasma
+// Author: Nemerix
+// URL:    https://www.shadertoy.com/view/3fy3z3
+// Date:   26-May-2025
+// Desc:   Heavily inspired by https://www.shadertoy.com/view/WfS3Dd
+// 
+// I put this together after poking at it for a few hours, to make sure I actually learned something from it. :D
+
+// Shader by Nemerix, 2025-05-26.
+// Code made available under the MIT license.
+
+float sqr(float x) { return x*x; }
+
+float hexSdf(in vec2 pos)
+{
+    return max(max(abs(dot(pos, vec2(0,2))), abs(dot(pos, vec2(1.732,1)))), abs(dot(pos, vec2(1.732,-1))));
+}
+
+float smoothSdf(in vec2 pos)
+{
+    return mix(sqr(hexSdf(pos)), dot(pos, pos), smoothstep(0.8, 1.5, dot(pos, pos)));
+}
+
+float sfield(in vec2 s)
+{
+    return s.x * s.y;
+}
+
+vec3 cmap(in vec2 pos)
+{
+    return mix(vec3(0.1,0.6,0.8), vec3(0.5), 0.7 * tanh(dot(pos, pos)));
+}
+
+const mat2 R = mat2(0.6, 0.8, -0.8, 0.6);
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+    vec2 uv = (2.0 * fragCoord - iResolution.xy) / iResolution.y;
+    
+    float d = smoothSdf(uv) - 1.0;
+    d = sqrt(abs(d));
+    
+    vec2 samp = uv * d;
+    float y = 0.0;
+    float scale = 1.0;
+    
+    for (int i = 0; i < 4; ++i)
+    {
+        samp = sin(R * samp * hexSdf(samp) + vec2(iTime));
+        y += scale * sfield(samp);
+        scale *= 0.75;
+    }
+    
+    vec3 col = cmap(uv) / abs(y);
+    col = tanh(0.1 * col);
+    fragColor = vec4(col, 1);
+}
diff --git a/hacks/glx/glsl/logarithmiccircles.glsl b/hacks/glx/glsl/logarithmiccircles.glsl
new file mode 100644 (file)
index 0000000..e0542e7
--- /dev/null
@@ -0,0 +1,96 @@
+// Title:  B/W logarithmic circles II
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/mljcWR
+// Date:   10-Aug-2023
+// Desc:   // CC0: B/W logarithmic circles II
+// // Tweaking on an old shader on the bus.
+
+// CC0: B/W logarithmic circles II
+// Tweaking on an old shader on the bus.
+
+#define TIME        iTime
+#define RESOLUTION  iResolution
+#define PI          3.141592654
+#define TAU         (2.0*PI)
+#define ROT(a)      mat2(cos(a), sin(a), -sin(a), cos(a))
+
+// Carefully fine tuned. No thinking involved.
+const float ExpBy   = log2(4.1);
+const float Radius  = 0.3175;
+  
+float forward(float l) {
+  return exp2(ExpBy*l);
+}
+
+float reverse(float l) {
+  return log2(l)/ExpBy;
+}
+
+float modPolar(inout vec2 p, float repetitions) {
+  float angle = TAU/repetitions;
+  float a = atan(p.y, p.x) + angle/2.;
+  float r = length(p);
+  float c = floor(a/angle);
+  a = mod(a,angle) - angle/2.;
+  p = vec2(cos(a), sin(a))*r;
+  // For an odd number of repetitions, fix cell index of the cell in -x direction
+  // (cell index would be e.g. -5 and 5 in the two halves of the cell):
+  if (abs(c) >= (repetitions/2.0)) c = abs(c);
+  return c;
+}
+
+vec3 effect(vec2 p) {
+  float aa = 4.0/RESOLUTION.y;
+  vec3 col = vec3(0.1*smoothstep(-sqrt(0.5), sqrt(0.5), sin(0.5*TAU*p.y/aa)));
+  
+  float tm = 0.2*TIME;
+  mat2 rot0 = ROT(-0.5*tm); 
+  for (float i = 0.0; i < 2.0; ++i) {
+    float ltm = tm+0.5*i;
+    mat2 rot1 = ROT(i*0.5*TAU/8.0);
+    float mtm = fract(ltm);
+    float ntm = floor(ltm);
+    float zz = forward(mtm);
+  
+    vec2 p0 = p;
+    p0 *= rot0;
+    p0 *= rot1;
+    p0 /= zz;
+  
+    float l0 = length(p0);
+    
+    float n0 = ceil(reverse(l0));
+    float r0 = forward(n0);
+    float r1 = forward(n0-1.0);
+    float r = (r0+r1)/2.0;
+    float w = r0-r1;
+    float nn = n0;
+    n0 -= ntm;
+    vec2 p1 = p0;
+    float n1 = modPolar(p1, 8.0);
+    p1.x -= r;
+  
+    float a = 0.5*ltm+n1/8.0;
+    a = fract(a);
+    float d1 = length(p1)-Radius*w;
+    float d2 = length(p1)-Radius*w*smoothstep(0.0, 0.45, mod(a, 0.5));
+    d1 *= zz;
+    d2 *= zz;
+    vec3 ccol = vec3(1.0)*smoothstep(0.0, -aa, d2);
+    if (a >= 0.5) ccol = 1.0-ccol;
+    col = mix(col, ccol, smoothstep(0.0, -aa, d1));
+  }
+  col = sqrt(col);
+  return col;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 q = fragCoord/iResolution.xy;
+  vec2 p = -1. + 2. * q;
+  p.x *= RESOLUTION.x/RESOLUTION.y;
+  vec3 col = effect(p);
+  
+  fragColor = vec4(col, 1.0);
+}
+
+
diff --git a/hacks/glx/glsl/neongravity-0.glsl b/hacks/glx/glsl/neongravity-0.glsl
new file mode 100644 (file)
index 0000000..c16f9af
--- /dev/null
@@ -0,0 +1,88 @@
+// Title:  Abstract gravitational well II
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/43G3Wc
+// Date:   13-Jun-2024
+// Desc:   CC0: Abstract gravitational well II
+// msm01 reminded me of an old shader that I thought was neat, but it suffered from aliasing effects. Since then, I've learned a few new tricks, so I created this new version. Hopefully, it's an improvement
+
+// CC0: Abstract gravitational well II
+//  msm01 reminded me of an old shader that I felt was neat but suffered
+//  from alias effects. I have learnt a few new tricks since so I did
+//  made this new version. Hopefully improved.
+//  The old version: https://www.shadertoy.com/view/dlSXRR
+
+#define TIME            iTime
+#define RESOLUTION      iResolution
+
+// License: Unknowon, author: XorDev, found: https://github.com/XorDev/GM_FXAA
+vec4 fxaa(sampler2D tex, vec2 uv, vec2 texelSz) {
+  // See this blog
+  // https://mini.gmshaders.com/p/gm-shaders-mini-fxaa
+
+  // Maximum texel span
+  const float span_max    = 8.0;
+  // These are more technnical and probably don't need changing:
+  // Minimum "dir" reciprocal
+  const float reduce_min  = (1.0/128.0);
+  // Luma multiplier for "dir" reciprocal
+  const float reduce_mul  = (1.0/32.0);
+
+  const vec3  luma        = vec3(0.299, 0.587, 0.114);
+
+  // Sample center and 4 corners
+  vec3 rgbCC = texture(tex, uv).rgb;
+  vec3 rgb00 = texture(tex, uv+vec2(-0.5,-0.5)*texelSz).rgb;
+  vec3 rgb10 = texture(tex, uv+vec2(+0.5,-0.5)*texelSz).rgb;
+  vec3 rgb01 = texture(tex, uv+vec2(-0.5,+0.5)*texelSz).rgb;
+  vec3 rgb11 = texture(tex, uv+vec2(+0.5,+0.5)*texelSz).rgb;
+
+  //Get luma from the 5 samples
+  float lumaCC = dot(rgbCC, luma);
+  float luma00 = dot(rgb00, luma);
+  float luma10 = dot(rgb10, luma);
+  float luma01 = dot(rgb01, luma);
+  float luma11 = dot(rgb11, luma);
+
+  // Compute gradient from luma values
+  vec2 dir = vec2((luma01 + luma11) - (luma00 + luma10), (luma00 + luma01) - (luma10 + luma11));
+
+  // Diminish dir length based on total luma
+  float dirReduce = max((luma00 + luma10 + luma01 + luma11) * reduce_mul, reduce_min);
+
+  // Divide dir by the distance to nearest edge plus dirReduce
+  float rcpDir = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);
+
+  // Multiply by reciprocal and limit to pixel span
+  dir = clamp(dir * rcpDir, -span_max, span_max) * texelSz.xy;
+
+  // Average middle texels along dir line
+  vec4 A = 0.5 * (
+      texture(tex, uv - dir * (1.0/6.0))
+    + texture(tex, uv + dir * (1.0/6.0))
+    );
+
+  // Average with outer texels along dir line
+  vec4 B = A * 0.5 + 0.25 * (
+      texture(tex, uv - dir * (0.5))
+    + texture(tex, uv + dir * (0.5))
+    );
+
+
+  // Get lowest and highest luma values
+  float lumaMin = min(lumaCC, min(min(luma00, luma10), min(luma01, luma11)));
+  float lumaMax = max(lumaCC, max(max(luma00, luma10), max(luma01, luma11)));
+
+  // Get average luma
+  float lumaB = dot(B.rgb, luma);
+
+  //If the average is outside the luma range, using the middle average
+  return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? A : B;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 tsz = 1./RESOLUTION.xy;
+  vec2 q = fragCoord*tsz;
+  //fragColor = texture(iChannel0, q);
+  fragColor = fxaa(iChannel0, q, sqrt(2.)*tsz);
+}
+
diff --git a/hacks/glx/glsl/neongravity-1.glsl b/hacks/glx/glsl/neongravity-1.glsl
new file mode 100644 (file)
index 0000000..a5e8f5e
--- /dev/null
@@ -0,0 +1,258 @@
+// Title:  Abstract gravitational well II
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/43G3Wc
+// Date:   13-Jun-2024
+// Desc:   CC0: Abstract gravitational well II
+// msm01 reminded me of an old shader that I thought was neat, but it suffered from aliasing effects. Since then, I've learned a few new tricks, so I created this new version. Hopefully, it's an improvement
+
+// CC0: Abstract gravitational well II
+//  msm01 reminded me of an old shader that I felt was neat but suffered
+//  from alias effects. I have learnt a few new tricks since so I did
+//  made this new version. Hopefully improved.
+//  The old version: https://www.shadertoy.com/view/dlSXRR
+
+//#define I_DO_NOT_LIKE_THE_FLASH_EFFECT
+
+#define TIME            iTime
+#define RESOLUTION      iResolution
+
+#define PI              3.141592654
+#define TAU             (2.0*PI)
+
+#define TOLERANCE       0.001
+#define MAX_RAY_LENGTH  30.0
+#define MAX_RAY_MARCHES 100
+#define NORM_OFF        0.05
+#define ROT(a)          mat2(cos(a), sin(a), -sin(a), cos(a))
+
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+vec3 hsv2rgb(vec3 c) {
+  vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
+  return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), c.y);
+}
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+//  Macro version of above to enable compile-time constants
+#define HSV2RGB(c)  (c.z * mix(hsv2rgb_K.xxx, clamp(abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www) - hsv2rgb_K.xxx, 0.0, 1.0), c.y))
+
+const float hoff      = 0.0;
+const vec3 skyCol     = HSV2RGB(vec3(hoff+0.57, 0.70, 0.25));
+const vec3 glowCol    = HSV2RGB(vec3(hoff+0.025, 0.85, 0.5));
+const vec3 sunCol1    = HSV2RGB(vec3(hoff+0.60, 0.50, 0.5));
+const vec3 sunCol2    = HSV2RGB(vec3(hoff+0.05, 0.75, 25.0));
+const vec3 diffCol    = HSV2RGB(vec3(hoff+0.60, 0.75, 0.25));
+const vec3 sunDir1    = normalize(vec3(3., 3.0, -7.0));
+
+// License: Unknown, author: Matt Taylor (https://github.com/64), found: https://64.github.io/tonemapping/
+vec3 aces_approx(vec3 v) {
+  v = max(v, 0.0);
+  v *= 0.6;
+  float a = 2.51;
+  float b = 0.03;
+  float c = 2.43;
+  float d = 0.59;
+  float e = 0.14;
+  return clamp((v*(a*v+b))/(v*(c*v+d)+e), 0.0, 1.0);
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/spherefunctions/
+float sphereD(vec3 ro, vec3 rd, vec4 sph, float dbuffer) {
+    float ndbuffer = dbuffer/sph.w;
+    vec3  rc = (ro - sph.xyz)/sph.w;
+       
+    float b = dot(rd,rc);
+    float c = dot(rc,rc) - 1.0;
+    float h = b*b - c;
+    if( h<0.0 ) return 0.0;
+    h = sqrt( h );
+    float t1 = -b - h;
+    float t2 = -b + h;
+
+    if( t2<0.0 || t1>ndbuffer ) return 0.0;
+    t1 = max( t1, 0.0 );
+    t2 = min( t2, ndbuffer );
+
+    float i1 = -(c*t1 + b*t1*t1 + t1*t1*t1/3.0);
+    float i2 = -(c*t2 + b*t2*t2 + t2*t2*t2/3.0);
+    return (i2-i1)*(3.0/4.0);
+}
+
+// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/
+float mod1(inout float p, float size) {
+  float halfsize = size*0.5;
+  float c = floor((p + halfsize)/size);
+  p = mod(p + halfsize, size) - halfsize;
+  return c;
+}
+
+// License: CC0, author: Mårten Rånge, found: https://github.com/mrange/glsl-snippets
+vec2 toPolar(vec2 p) {
+  return vec2(length(p), atan(p.y, p.x));
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/distfunctions/
+float rayPlane(vec3 ro, vec3 rd, vec4 p) {
+  return -(dot(ro,p.xyz)+p.w)/dot(rd,p.xyz);
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
+float box(vec2 p, vec2 b) {
+  vec2 d = abs(p)-b;
+  return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
+float parabola(vec2 pos, float k) {
+  pos = pos.yx;
+  pos.x = abs(pos.x);
+  float ik = 1.0/k;
+  float p = ik*(pos.y - 0.5*ik)/3.0;
+  float q = 0.25*ik*ik*pos.x;
+  float h = q*q - p*p*p;
+  float r = sqrt(abs(h));
+  float x = (h>0.0) ? 
+      pow(q+r,1.0/3.0) - pow(abs(q-r),1.0/3.0)*sign(r-q) :
+      2.0*cos(atan(r,q)/3.0)*sqrt(p);
+    return length(pos-vec2(x,k*x*x)) * sign(pos.x-x);
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/distfunctions/
+float parabola(vec3 p, float k, float o) {
+  vec2 q = vec2(length(p.xz) - o, p.y);
+  return parabola(q, k);
+}
+
+float df(vec3 p) {
+  return parabola(p, .9, 0.5);
+}
+
+
+vec3 normal(vec3 pos) {
+  vec2  eps = vec2(NORM_OFF,0.0);
+  vec3 nor;
+  nor.x = df(pos+eps.xyy) - df(pos-eps.xyy);
+  nor.y = df(pos+eps.yxy) - df(pos-eps.yxy);
+  nor.z = df(pos+eps.yyx) - df(pos-eps.yyx);
+  return normalize(nor);
+}
+
+float rayMarch(vec3 ro, vec3 rd) {
+  float t = 0.0;
+  const float tol = TOLERANCE;
+  vec2 dti = vec2(1e10,0.0);
+  int i = 0;
+  for (i = 0; i < MAX_RAY_MARCHES; ++i) {
+    float d = df(ro + rd*t);
+    if (d<dti.x) { dti=vec2(d,t); }
+    if (d < TOLERANCE || t > MAX_RAY_LENGTH) {
+      break;
+    }
+    t += d;
+  }
+  if(i==MAX_RAY_MARCHES) { t=dti.y; };
+  return t;
+}
+
+vec3 render0(vec3 ro, vec3 rd) {
+  vec3 col = vec3(0.0);
+  float sd = max(dot(sunDir1, rd), 0.0);
+  float sf = 1.0001-sd;
+  col += clamp(vec3(0.0025/max(abs(rd.y), 0.5*fwidth(rd.y)))*glowCol, 0.0, 1.0);
+  col += 0.75*skyCol*pow((1.0-abs(rd.y)), 8.0);
+  col += 2.0*sunCol1*pow(sd, 100.0);
+  col += sunCol2*pow(sd, 800.0);
+
+  float tp1  = rayPlane(ro, rd, vec4(vec3(0.0, -1.0, 0.0), 6.0));
+
+  if (tp1 > 0.0) {
+    vec3 pos  = ro + tp1*rd;
+    vec2 pp = pos.xz;
+    float db = box(pp, vec2(5.0, 9.0))-3.0;
+    
+    col += vec3(4.0)*skyCol*rd.y*rd.y*smoothstep(0.25, 0.0, db);
+    col += vec3(0.8)*skyCol*exp(-0.5*max(db, 0.0));
+    col += 0.25*sqrt(skyCol)*max(-db, 0.0);
+  }
+
+  return clamp(col, 0.0, 10.0);;
+}
+
+
+vec3 render1(vec3 ro, vec3 rd) {
+  float t = rayMarch(ro, rd);
+
+  vec3 col = vec3(0.0);
+
+  vec3 p = ro+rd*t;
+  vec3 n = normal(p);
+  vec3 r = reflect(rd, n);
+  float fre = 1.0+dot(rd, n);
+  fre *= fre;
+  float dif = dot(sunDir1, n); 
+
+  if (t < MAX_RAY_LENGTH) {
+    const float ExpBy = log2(1.5);
+    float a = 0.2*TIME;
+    vec2 pp = toPolar(p.xz);
+    pp.y -= TAU/24.0;
+    float la = length(pp.x*exp2(ExpBy*fract(a)));
+    la = log2(la)/ExpBy;
+    float lo = pp.y;
+    vec2 fw = fwidth(vec2(la ,lo));
+    mod1(la, 1.0);
+    mod1(lo, TAU/12.0);
+
+    float gdla = abs(la)-0.01;
+    float gdlo = abs(lo)-0.0025;
+    
+    col = 1E-2*glowCol/max(gdla, 1E-3+3E-1*fw.x);
+    col += 1E-2*glowCol/max(gdlo, 1E-3+1E-1*fw.y);
+    col *= smoothstep(1.0, 0.98, fre);
+    col += mix(0.33, 1.0, fre)*render0(p, r);
+    col += sunCol1*dif*dif*diffCol;
+    
+#ifdef I_DO_NOT_LIKE_THE_FLASH_EFFECT
+    const float flash = 0.;
+#else
+    float flash = exp(-6.*fract(a+0.15));
+#endif
+    float sd = sphereD(ro, rd, vec4(0.,-0.25,0.,1.+flash), t);
+    col += sd*sd*mix(20.,60., flash)*glowCol;
+  }
+
+  return col;
+}
+
+vec3 effect(vec2 p, vec2 pp) {
+  float tm  = TIME*0.5;
+  
+  vec3 ro = 1.0*vec3(5.0, 3.0, 0.);
+  ro.xz *= ROT(-0.1*tm);
+  const vec3 la = vec3(0.0, 0.5, 0.0);
+  const vec3 up = normalize(vec3(0.0, 1.0, 0.0));
+
+  vec3 ww = normalize(la - ro);
+  vec3 uu = normalize(cross(up, ww ));
+  vec3 vv = (cross(ww,uu));
+  const float fov = tan(TAU/6.);
+  vec3 rd = normalize(-p.x*uu + p.y*vv + fov*ww);
+
+  vec3 col = render1(ro, rd);
+  col -= 0.015*vec3(3.,2.,1.)*(length(p)+0.25);
+  col *= smoothstep(1.5, 0.5, length(pp));
+  col = aces_approx(col); 
+  col = sqrt(col);
+  
+  return col;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 q = fragCoord/RESOLUTION.xy;
+  vec2 p = -1. + 2. * q;
+  vec2 pp = p;
+  p.x *= RESOLUTION.x/RESOLUTION.y;
+  vec3 col = vec3(0.0);
+  col = effect(p, pp);
+  fragColor = vec4(col, 1.0);
+}
+
diff --git a/hacks/glx/glsl/neontriangulator.glsl b/hacks/glx/glsl/neontriangulator.glsl
new file mode 100644 (file)
index 0000000..3a6d92e
--- /dev/null
@@ -0,0 +1,303 @@
+// Title:  Neon Triangulator
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/tXGGRD
+// Date:   09-Jul-2025
+// Desc:   CC0: Neon triangulator
+//   Haven't done a synthwave shader in awhile so here goes.
+
+// CC0: Neon triangulator
+//  Haven't done a synthwave shader in awhile so here goes.
+
+#define ROT(a)      mat2(cos(a), sin(a), -sin(a), cos(a))
+
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+vec3 hsv2rgb(vec3 c) {
+  vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
+  return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), c.y);
+}
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+//  Macro version of above to enable compile-time constants
+#define HSV2RGB(c)  (c.z * mix(hsv2rgb_K.xxx, clamp(abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www) - hsv2rgb_K.xxx, 0.0, 1.0), c.y))
+
+const float 
+    PI            = acos(-1.)
+  , TAU           = 2.*PI
+  , MaxDistance   = 10.
+  , Tolerance     = 3e-3
+  , NormalEpsilon = 1e-3
+  , MaxIter       = 77.
+  , LightDiv      = 3.
+  , SimplexOff    = sqrt(2.)/3. 
+  , MaxBounces    = 4.
+  ;
+
+const vec3 
+    sunCol   = HSV2RGB(vec3(.72,.9,4e-4))
+  , absCol   = HSV2RGB(vec3(.75,.33,.6))
+  ;
+
+// License: Unknown, author: Matt Taylor (https://github.com/64), found: https://64.github.io/tonemapping/
+vec3 aces_approx(vec3 v) {
+  const float 
+      a = 2.51
+    , b = 0.03
+    , c = 2.43
+    , d = 0.59
+    , e = 0.14
+    ;
+  v = max(v, 0.)*.6;
+  return clamp((v*(a*v+b))/(v*(c*v+d)+e), 0.0, 1.0);
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/articles/distfunctions2d/distfunctions2d.htm
+float box(vec2 p, vec2 b) {
+  vec2 d = abs(p)-b;
+  return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
+}
+
+// License: Unknown, author: Unknown, found: don't remember
+float hash(float co) {
+  return fract(sin(co*12.9898) * 13758.5453);
+}
+
+// License: Unknown, author: Unknown, found: don't remember
+vec2 hash2(vec2 p) {
+  p = vec2(dot (p, vec2 (127.1, 311.7)), dot (p, vec2 (269.5, 183.3)));
+  return fract(sin(p)*43758.5453123);
+}
+
+vec2 shash2(vec2 p) {
+  return hash2(p)*2.-1.;
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/sdfxor/
+//  Based on jt's: https://www.shadertoy.com/view/ssG3WK
+float xor(float a, float b) {
+  return max( min(a,b), -max(a,b) );
+}
+
+float boxPattern(vec2 p, float hh, vec2 sz) {
+  const float 
+      zz = 2.0
+    ;
+  float 
+      d = 1E3
+    , z = 2.
+    , dd
+    ;
+  p /= z;
+  for (float i = 0.; i < 3.; ++i) {
+    vec2 
+        n = round(p)
+      , h = shash2(n + i+hh)
+      , c = p - n
+      ;
+    d = xor(d, box(c - h * .4, sz)/z);
+    z *= zz;                 
+    p *= zz;
+    p += vec2(3.14,2.71);              
+  }
+
+  return d;              
+}
+
+float modPolar3(inout vec2 p) {
+  const vec2 r = normalize(vec2(sqrt(3.), -1.));
+  float n = p.y < 0.0 ? -1. : 1.;
+  vec2 ap = vec2(p.x, abs(p.y));
+  float d = dot(ap, r);
+  if (d > 0.) return 0.;
+  ap -= 2. * d * r;
+  ap.y *= -n;
+  p = ap;
+  return n;
+}
+
+// Inputs
+vec2 g_h;
+// Outputs
+vec3 g_gd;
+vec2 g_d ;
+vec3 g_lp;
+vec3 g_pp;
+vec2 g_c ;
+
+float df(vec3 p) {
+  const mat2 
+      R1  = ROT(PI/3.)
+    ; 
+  const vec2 
+      off2 = R1*vec2(SimplexOff,0.0)
+    ;
+
+  float loff = -2.*g_h.x*iTime;
+  vec3 op = p;
+  p.z -= loff;
+  float R = round(p.z/LightDiv)*LightDiv;
+  g_lp = vec3(0,0,loff+round((p.z+LightDiv*.47)/LightDiv)*LightDiv);
+  p.z -= R;
+  p.xy = -p.yx;
+  float 
+      n = modPolar3(p.xy)
+    , d0 = SimplexOff*.5-p.x
+    , d1 = length(p.xz-.44*vec2(SimplexOff,0.))-.001
+    , d2
+    , d3 = 1E3
+    , d4 = 1E3
+    , d5 = 
+        length(op.xy-vec2(0,-.1)+.1*sin(-TAU*g_h*iTime+2.*op.z*vec2(1, sqrt(2.))))
+      + smoothstep(-sqrt(.5),-.5, sin((op.z+iTime+g_h.y*(iTime+123.))/TAU))*.2
+    , d = d0
+    ;
+  if (g_h.x > 0.) {
+    d3 = d5;
+    d4 = d5*.25;
+  }
+  d = min(d, d1);
+  g_pp = vec3(p.y,op.z,n);
+  p.y = abs(p.y);
+
+  d2= length(p.xy-off2) - .01;
+  d = min(d, d2);
+  d = min(d, d3);
+  g_gd = min(g_gd, vec3(d1,d2,d4));
+  g_d = vec2(d0,d3);
+  g_c = vec2(n,floor((op.z-.05)/LightDiv));
+  return d;
+}
+
+float rayMarch(vec3 ro, vec3 rd, float init, out float i) {
+  float t=init;
+  for (i=0.;i<MaxIter;++i) {
+    vec3 p = ro+t*rd;
+    float d=df(p);
+    if (t > MaxDistance)return MaxDistance;
+    if (d < Tolerance)  return t;
+    t += d;
+  }
+  return t;
+}
+
+vec3 normal(vec3 pos) {
+  const vec2 
+      eps = vec2(NormalEpsilon, 0.0)
+    ;
+  return normalize(vec3(
+      df(pos+eps.xyy)-df(pos-eps.xyy)
+    , df(pos+eps.yxy)-df(pos-eps.yxy)
+    , df(pos+eps.yyx)-df(pos-eps.yyx))
+    );
+}
+
+vec3 render(vec3 ro, vec3 rd, float noise) {
+  const float 
+      aa = 0.00025
+    ;
+  float 
+      nn    = 0.
+    , initt = .2*noise
+    ;
+  vec3 
+      col  =vec3(0)
+    , cabs =vec3(1.)
+    ;
+  for (float l=0.;l<MaxBounces;++l) {
+    if (dot(vec3(1),cabs) < .01)
+      break;
+    float 
+        h0 = hash(nn)
+      , h1 = fract(8667.*h0)
+      ;
+    g_h = vec2(h0,h1);
+    g_gd = vec3(1E3);
+    float 
+        i
+      , t = rayMarch(ro, rd, initt,i)
+      ;
+    vec2 
+        d2 = g_d
+      , c  = g_c
+      ;
+    vec3 
+         gd = g_gd
+       , pp = g_pp
+       , lp = g_lp
+       , p  = ro+rd*t
+       ;
+    float d = df(p);
+    vec3 
+        ld = normalize(lp-p)
+      , n  = normal(p)
+      , r  = reflect(rd,n)
+      ;
+    vec2 
+        sz = .5*sqrt(hash2(c+1.23))
+      ;
+    if (c.x+c.y < 3.) {
+      sz = vec2(-1);
+    }
+    float 
+        pd  = boxPattern(pp.xy,h0, sz)
+      , tol = Tolerance*3.
+      , phit= d2.x <= tol ? 1. : 0. 
+      , pf  = smoothstep(aa, -aa, pd)*phit
+      , mgd = min(min(gd.x,gd.y),gd.z)
+      ;    
+    if (t < MaxDistance) {
+      vec3 
+          ccol     = vec3(0)
+        , difCol0  = hsv2rgb(vec3(.7+.15*(3.*p.y-p.x),.9,.25))
+        , glowCol0 = 2e-4*difCol0
+        , glowCol1 = hsv2rgb(vec3(.6+.2*h1,.9,2e-4))
+        ;
+      ccol += difCol0*pow(max(dot(n,ld),0.), mix(2.,4., pf));
+      ccol += difCol0*pow(max(dot(reflect(rd,n),ld),0.), mix(40.,80., pf));
+      ccol += glowCol0/max(gd.x*gd.x, 5e-6);
+      ccol += glowCol0/max(gd.y*gd.y, 5e-5)*(1.+sin(1e2*p.z));
+      ccol += glowCol1/max(gd.z*gd.z, 5e-6);
+      ccol *= cabs;
+
+      col += ccol;
+      rd = r;
+      cabs *= absCol*pf;
+      nn += pp.z*1.2+1.23;
+      ro = p+n*.02;
+      initt = noise*.02;
+      
+      if (mgd < tol) {
+        cabs = vec3(0.);
+      }
+    } else {
+      break;
+    }
+  }
+  return col;
+}
+
+
+vec3 effect(vec2 p, float noise) {
+  const vec3
+      up = vec3(0, 1, 0)
+    , ww = normalize(vec3(0, 0, 1))
+    , uu  = normalize(cross(up, ww))
+    , vv  = cross(ww,uu)
+    ;
+  vec3
+      ro = vec3(0,0,iTime)
+    , rd  = normalize(p.y*vv -p.x*uu + 2.*ww)
+    , col = render(ro, rd, noise)
+    ;
+  col += sunCol/(1.00001+dot(abs(rd), normalize(vec3(0,0,-1))));    
+
+  col -= .02*vec3(2,3,1)*(length(p)+.25);
+  col = aces_approx(col);
+  col = sqrt(col);
+  return col;
+}
+
+void mainImage(out vec4 O, vec2 C) {
+  vec2 r = iResolution.xy, p = (2.*C-r)/r.y;
+  O = vec4(effect(p, fract(dot(C,sin(C)))), 1);
+}
+
diff --git a/hacks/glx/glsl/protophore.glsl b/hacks/glx/glsl/protophore.glsl
new file mode 100644 (file)
index 0000000..e0d8458
--- /dev/null
@@ -0,0 +1,356 @@
+// Title:  Protophore
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/XljGDz
+// Date:   06-Apr-2015
+// Desc:   I put together this fractal and then watched some tutorials on how to light sports cars for photography. I think the key is to get the giant softbox up top with just the right fade at the edges. I also ray march 1 reflection.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+^This means do anything you want with this code. Because we are programmers, not lawyers.
+
+-Otavio Good
+*/
+
+// Number of times the fractal repeats
+#define RECURSION_LEVELS 4
+// Animation splits the sphere in different directions
+// This ended up running a significantly slower fps and not looking very different. :(
+//#define SPLIT_ANIM
+
+float localTime = 0.0;
+float marchCount;
+
+float PI=3.14159265;
+
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+
+vec3 RotateX(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(v.x, cos * v.y + sin * v.z, -sin * v.y + cos * v.z);
+}
+vec3 RotateY(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(cos * v.x - sin * v.z, v.y, sin * v.x + cos * v.z);
+}
+vec3 RotateZ(vec3 v, float rad)
+{
+  float cos = cos(rad);
+  float sin = sin(rad);
+  return vec3(cos * v.x + sin * v.y, -sin * v.x + cos * v.y, v.z);
+}
+
+
+/*vec3 GetEnvColor(vec3 rayDir, vec3 sunDir)
+{
+       vec3 tex = texture(iChannel0, rayDir).xyz;
+       tex = tex * tex;        // gamma correct
+    return tex;
+}*/
+
+// This is a procedural environment map with a giant overhead softbox,
+// 4 lights in a horizontal circle, and a bottom-to-top fade.
+vec3 GetEnvColor2(vec3 rayDir, vec3 sunDir)
+{
+    // fade bottom to top so it looks like the softbox is casting light on a floor
+    // and it's bouncing back
+    vec3 final = vec3(1.0) * dot(-rayDir, sunDir) * 0.5 + 0.5;
+    final *= 0.125;
+    // overhead softbox, stretched to a rectangle
+    if ((rayDir.y > abs(rayDir.x)*1.0) && (rayDir.y > abs(rayDir.z*0.25))) final = vec3(2.0)*rayDir.y;
+    // fade the softbox at the edges with a rounded rectangle.
+    float roundBox = length(max(abs(rayDir.xz/max(0.0,rayDir.y))-vec2(0.9, 4.0),0.0))-0.1;
+    final += vec3(0.8)* pow(saturate(1.0 - roundBox*0.5), 6.0);
+    // purple lights from side
+    final += vec3(8.0,6.0,7.0) * saturate(0.001/(1.0 - abs(rayDir.x)));
+    // yellow lights from side
+    final += vec3(8.0,7.0,6.0) * saturate(0.001/(1.0 - abs(rayDir.z)));
+    return vec3(final);
+}
+
+/*vec3 GetEnvColorReflection(vec3 rayDir, vec3 sunDir, float ambient)
+{
+       vec3 tex = texture(iChannel0, rayDir).xyz;
+       tex = tex * tex;
+    vec3 texBack = texture(iChannel0, rayDir).xyz;
+    vec3 texDark = pow(texBack, vec3(50.0)).zzz;       // fake hdr texture
+    texBack += texDark*0.5 * ambient;
+    return texBack*texBack*texBack;
+}*/
+
+vec3 camPos = vec3(0.0), camFacing;
+vec3 camLookat=vec3(0,0.0,0);
+
+// polynomial smooth min (k = 0.1);
+float smin( float a, float b, float k )
+{
+    float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
+    return mix( b, a, h ) - k*h*(1.0-h);
+}
+
+vec2 matMin(vec2 a, vec2 b)
+{
+       if (a.x < b.x) return a;
+       else return b;
+}
+
+float spinTime;
+vec3 diagN = normalize(vec3(-1.0));
+float cut = 0.77;
+float inner = 0.333;
+float outness = 1.414;
+float finWidth;
+float teeth;
+float globalTeeth;
+
+vec2 sphereIter(vec3 p, float radius, float subA)
+{
+    finWidth = 0.1;
+    teeth = globalTeeth;
+    float blender = 0.25;
+    vec2 final = vec2(1000000.0, 0.0);
+    for (int i = 0; i < RECURSION_LEVELS; i++)
+    {
+#ifdef SPLIT_ANIM
+        // rotate top and bottom of sphere opposite directions
+        p = RotateY(p, spinTime*sign(p.y)*0.05/blender);
+#endif
+        // main sphere
+        float d = length(p) - radius*outness;
+#ifdef SPLIT_ANIM
+        // subtract out disc at the place where rotation happens so we don't have artifacts
+        d = max(d, -(max(length(p) - radius*outness + 0.1, abs(p.y) - finWidth*0.25)));
+#endif
+
+        // calc new position at 8 vertices of cube, scaled
+        vec3 corners = abs(p) + diagN * radius;
+        float lenCorners = length(corners);
+        // subtract out main sphere hole, mirrored on all axises
+        float subtracter = lenCorners - radius * subA;
+        // make mirrored fins that go through all vertices of the cube
+        vec3 ap = abs(-p) * 0.7071;    // 1/sqrt(2) to keep distance field normalized
+        subtracter = max(subtracter, -(abs(ap.x-ap.y) - finWidth));
+        subtracter = max(subtracter, -(abs(ap.y-ap.z) - finWidth));
+        subtracter = max(subtracter, -(abs(ap.z-ap.x) - finWidth));
+        // subtract sphere from fins so they don't intersect the inner spheres.
+        // also animate them so they are like teeth
+        subtracter = min(subtracter, lenCorners - radius * subA + teeth);
+        // smoothly subtract out that whole complex shape
+        d = -smin(-d, subtracter, blender);
+        //vec2 sphereDist = sphereB(abs(p) + diagN * radius, radius * inner, cut);     // recurse
+        // do a material-min with the last iteration
+        final = matMin(final, vec2(d, float(i)));
+
+#ifndef SPLIT_ANIM
+        corners = RotateY(corners, spinTime*0.25/blender);
+#endif
+        // Simple rotate 90 degrees on X axis to keep things fresh
+        p = vec3(corners.x, corners.z, -corners.y);
+        // Scale things for the next iteration / recursion-like-thing
+        radius *= inner;
+        teeth *= inner;
+        finWidth *= inner;
+        blender *= inner;
+    }
+    // Bring in the final smallest-sized sphere
+    float d = length(p) - radius*outness;
+    final = matMin(final, vec2(d, 6.0));
+    return final;
+}
+
+vec2 DistanceToObject(vec3 p)
+{
+    vec2 distMat = sphereIter(p, 5.2 / outness, cut);
+    return distMat;
+}
+
+// dirVec MUST BE NORMALIZED FIRST!!!!
+float SphereIntersect(vec3 pos, vec3 dirVecPLZNormalizeMeFirst, vec3 spherePos, float rad)
+{
+    vec3 radialVec = pos - spherePos;
+    float b = dot(radialVec, dirVecPLZNormalizeMeFirst);
+    float c = dot(radialVec, radialVec) - rad * rad;
+    float h = b * b - c;
+    if (h < 0.0) return -1.0;
+    return -b - sqrt(h);
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+    localTime = iTime - 0.0;
+       // ---------------- First, set up the camera rays for ray marching ----------------
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+    float zoom = 1.7;
+    uv /= zoom;
+
+       // Camera up vector.
+       vec3 camUp=vec3(0,1,0);
+
+       // Camera lookat.
+       camLookat=vec3(0,0.0,0);
+
+    // debugging camera
+    float mx=iMouse.x/iResolution.x*PI*2.0-0.7 + localTime*3.1415 * 0.0625*0.666;
+       float my=-iMouse.y/iResolution.y*10.0 - sin(localTime * 0.31)*0.5;//*PI/2.01;
+       camPos += vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*(12.2);
+
+       // Camera setup.
+       vec3 camVec=normalize(camLookat - camPos);
+       vec3 sideNorm=normalize(cross(camUp, camVec));
+       vec3 upNorm=cross(camVec, sideNorm);
+       vec3 worldFacing=(camPos + camVec);
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;
+       vec3 rayVec = normalize(worldPix - camPos);
+
+       // ----------------------------------- Animate ------------------------------------
+    localTime = iTime*0.5;
+    // This is a wave function like a triangle wave, but with flat tops and bottoms.
+    // period is 1.0
+    float rampStep = min(3.0,max(1.0, abs((fract(localTime)-0.5)*1.0)*8.0))*0.5-0.5;
+    rampStep = smoothstep(0.0, 1.0, rampStep);
+    // lopsided triangle wave - goes up for 3 time units, down for 1.
+    float step31 = (max(0.0, (fract(localTime+0.125)-0.25)) - min(0.0,(fract(localTime+0.125)-0.25))*3.0)*0.333;
+
+    spinTime = step31 + localTime;
+    //globalTeeth = 0.0 + max(0.0, sin(localTime*3.0))*0.9;
+    globalTeeth = rampStep*0.99;
+    cut = max(0.48, min(0.77, localTime));
+       // --------------------------------------------------------------------------------
+       vec2 distAndMat = vec2(0.5, 0.0);
+       float t = 0.0;
+       //float inc = 0.02;
+       float maxDepth = 24.0;
+       vec3 pos = vec3(0,0,0);
+    marchCount = 0.0;
+    // intersect with sphere first as optimization so we don't ray march more than is needed.
+    float hit = SphereIntersect(camPos, rayVec, vec3(0.0), 5.6);
+    if (hit >= 0.0)
+    {
+        t = hit;
+        // ray marching time
+        for (int i = 0; i < 290; i++)  // This is the count of the max times the ray actually marches.
+        {
+            pos = camPos + rayVec * t;
+            // *******************************************************
+            // This is _the_ function that defines the "distance field".
+            // It's really what makes the scene geometry.
+            // *******************************************************
+            distAndMat = DistanceToObject(pos);
+            // adjust by constant because deformations mess up distance function.
+            t += distAndMat.x * 0.7;
+            //if (t > maxDepth) break;
+            if ((t > maxDepth) || (abs(distAndMat.x) < 0.0025)) break;
+            marchCount+= 1.0;
+        }
+    }
+    else
+    {
+        t = maxDepth + 1.0;
+        distAndMat.x = 1000000.0;
+    }
+    // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this geometry.
+
+       vec3 sunDir = normalize(vec3(3.93, 10.82, -1.5));
+       vec3 finalColor = vec3(0.0);
+
+       // If a ray actually hit the object, let's light it.
+       //if (abs(distAndMat.x) < 0.75)
+    if (t <= maxDepth)
+       {
+        // calculate the normal from the distance field. The distance field is a volume, so if you
+        // sample the current point and neighboring points, you can use the difference to get
+        // the normal.
+        vec3 smallVec = vec3(0.005, 0, 0);
+        vec3 normalU = vec3(distAndMat.x - DistanceToObject(pos - smallVec.xyy).x,
+                           distAndMat.x - DistanceToObject(pos - smallVec.yxy).x,
+                           distAndMat.x - DistanceToObject(pos - smallVec.yyx).x);
+
+        vec3 normal = normalize(normalU);
+
+        // calculate 2 ambient occlusion values. One for global stuff and one
+        // for local stuff
+        float ambientS = 1.0;
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.1).x*10.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.2).x*5.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.4).x*2.5);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.8).x*1.25);
+        float ambient = ambientS * saturate(DistanceToObject(pos + normal * 1.6).x*1.25*0.5);
+        ambient *= saturate(DistanceToObject(pos + normal * 3.2).x*1.25*0.25);
+        ambient *= saturate(DistanceToObject(pos + normal * 6.4).x*1.25*0.125);
+        ambient = max(0.035, pow(ambient, 0.3));       // tone down ambient with a pow and min clamp it.
+        ambient = saturate(ambient);
+
+        // calculate the reflection vector for highlights
+        vec3 ref = reflect(rayVec, normal);
+        ref = normalize(ref);
+
+        // Trace a ray for the reflection
+        float sunShadow = 1.0;
+        float iter = 0.1;
+        vec3 nudgePos = pos + normal*0.02;     // don't start tracing too close or inside the object
+               for (int i = 0; i < 40; i++)
+        {
+            float tempDist = DistanceToObject(nudgePos + ref * iter).x;
+               sunShadow *= saturate(tempDist*50.0);
+            if (tempDist <= 0.0) break;
+            //iter *= 1.5;     // constant is more reliable than distance-based
+            iter += max(0.00, tempDist)*1.0;
+            if (iter > 4.2) break;
+        }
+        sunShadow = saturate(sunShadow);
+
+        // ------ Calculate texture color ------
+        vec3 texColor;
+        texColor = vec3(1.0);// vec3(0.65, 0.5, 0.4)*0.1;
+        texColor = vec3(0.85, 0.945 - distAndMat.y * 0.15, 0.93 + distAndMat.y * 0.35)*0.951;
+        if (distAndMat.y == 6.0) texColor = vec3(0.91, 0.1, 0.41)*10.5;
+        //texColor *= mix(vec3(0.3), vec3(1.0), tex3d(pos*0.5, normal).xxx);
+        texColor = max(texColor, vec3(0.0));
+        texColor *= 0.25;
+
+        // ------ Calculate lighting color ------
+        // Start with sun color, standard lighting equation, and shadow
+        vec3 lightColor = vec3(0.0);// sunCol * saturate(dot(sunDir, normal)) * sunShadow*14.0;
+        // sky color, hemisphere light equation approximation, ambient occlusion
+        lightColor += vec3(0.1,0.35,0.95) * (normal.y * 0.5 + 0.5) * ambient * 0.2;
+        // ground color - another hemisphere light
+        lightColor += vec3(1.0) * ((-normal.y) * 0.5 + 0.5) * ambient * 0.2;
+
+
+        // finally, apply the light to the texture.
+        finalColor = texColor * lightColor;
+        //if (distAndMat.y == ceil(mod(localTime, 4.0))) finalColor += vec3(0.0, 0.41, 0.72)*0.925;
+
+        // reflection environment map - this is most of the light
+        vec3 refColor = GetEnvColor2(ref, sunDir)*sunShadow;
+        finalColor += refColor * 0.35 * ambient;// * sunCol * sunShadow * 9.0 * texColor.g;
+
+        // fog
+               finalColor = mix(vec3(1.0, 0.41, 0.41) + vec3(1.0), finalColor, exp(-t*0.0007));
+        // visualize length of gradient of distance field to check distance field correctness
+        //finalColor = vec3(0.5) * (length(normalU) / smallVec.x);
+       }
+    else
+    {
+           finalColor = GetEnvColor2(rayVec, sunDir);// + vec3(0.1, 0.1, 0.1);
+    }
+    //finalColor += marchCount * vec3(1.0, 0.3, 0.91) * 0.001;
+
+    // vignette?
+    //finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
+    //finalColor *= 1.95;
+
+       // output the final color with sqrt for "gamma correction"
+       fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
+
+
diff --git a/hacks/glx/glsl/selfreflect.glsl b/hacks/glx/glsl/selfreflect.glsl
new file mode 100644 (file)
index 0000000..7af474c
--- /dev/null
@@ -0,0 +1,378 @@
+// Title:  Let's self reflect
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/XfyXRV
+// Date:   11-May-2024
+// Desc:   CC0: Let's self reflect
+// Always enjoyed the videos of Platonic solids with inner mirrors
+// I made some previous attempts but thought I make another attempt it
+
+// CC0: Let's self reflect
+//  Always enjoyed the videos of Platonic solids with inner mirrors
+//  I made some previous attempts but thought I make another attempt it
+
+// Reducing the alias effects on the inner reflections turned out to be a bit tricky. 
+//  Simplest solution is just to run run fullscreen on a 4K screen ;)
+
+// Function to generate the solid found here: https://www.shadertoy.com/view/MsKGzw
+
+// Tinker with these parameters to create different solids
+// -------------------------------------------------------
+const float rotation_speed= 0.25;
+
+const float poly_U        = 1.;   // [0, inf]
+const float poly_V        = 0.5;  // [0, inf]
+const float poly_W        = 1.0;  // [0, inf]
+const int   poly_type     = 3;    // [2, 5]
+const float poly_zoom     = 2.0;
+
+const float inner_sphere  = 1.;
+
+const float refr_index    = 0.9;
+
+#define MAX_BOUNCES2        6
+// -------------------------------------------------------
+
+
+
+#define TIME        iTime
+#define RESOLUTION  iResolution
+#define PI          3.141592654
+#define TAU         (2.0*PI)
+
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+vec3 hsv2rgb(vec3 c) {
+  vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
+  return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), c.y);
+}
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+//  Macro version of above to enable compile-time constants
+#define HSV2RGB(c)  (c.z * mix(hsv2rgb_K.xxx, clamp(abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www) - hsv2rgb_K.xxx, 0.0, 1.0), c.y))
+
+#define TOLERANCE2          0.0005
+//#define MAX_RAY_LENGTH2   10.0
+#define MAX_RAY_MARCHES2    50
+#define NORM_OFF2           0.005
+#define BACKSTEP2
+
+#define TOLERANCE3          0.0005
+#define MAX_RAY_LENGTH3     10.0
+#define MAX_RAY_MARCHES3    90
+#define NORM_OFF3           0.005
+
+const vec3 rayOrigin    = vec3(0.0, 1., -5.);
+const vec3 sunDir       = normalize(-rayOrigin);
+
+
+const vec3 sunCol       = HSV2RGB(vec3(0.06 , 0.90, 1E-2))*1.;
+const vec3 bottomBoxCol = HSV2RGB(vec3(0.66, 0.80, 0.5))*1.;
+const vec3 topBoxCol    = HSV2RGB(vec3(0.60, 0.90, 1.))*1.;
+const vec3 glowCol0     = HSV2RGB(vec3(0.05 , 0.7, 1E-3))*1.;
+const vec3 glowCol1     = HSV2RGB(vec3(0.95, 0.7, 1E-3))*1.;
+const vec3 beerCol      = -HSV2RGB(vec3(0.15+0.5, 0.7, 2.)); 
+const float rrefr_index = 1./refr_index;
+
+
+// License: Unknown, author: knighty, found: https://www.shadertoy.com/view/MsKGzw
+const float poly_cospin   = cos(PI/float(poly_type));
+const float poly_scospin  = sqrt(0.75-poly_cospin*poly_cospin);
+const vec3  poly_nc       = vec3(-0.5, -poly_cospin, poly_scospin);
+const vec3  poly_pab      = vec3(0., 0., 1.);
+const vec3  poly_pbc_     = vec3(poly_scospin, 0., 0.5);
+const vec3  poly_pca_     = vec3(0., poly_scospin, poly_cospin);
+const vec3  poly_p        = normalize((poly_U*poly_pab+poly_V*poly_pbc_+poly_W*poly_pca_));
+const vec3  poly_pbc      = normalize(poly_pbc_);
+const vec3  poly_pca      = normalize(poly_pca_);
+
+mat3 g_rot;
+vec2 g_gd;
+  
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/noacos/
+mat3 rot(vec3 d, vec3 z) {
+  vec3  v = cross( z, d );
+  float c = dot( z, d );
+  float k = 1.0/(1.0+c);
+
+  return mat3( v.x*v.x*k + c,     v.y*v.x*k - v.z,    v.z*v.x*k + v.y,
+               v.x*v.y*k + v.z,   v.y*v.y*k + c,      v.z*v.y*k - v.x,
+               v.x*v.z*k - v.y,   v.y*v.z*k + v.x,    v.z*v.z*k + c    );
+}
+
+// License: Unknown, author: Matt Taylor (https://github.com/64), found: https://64.github.io/tonemapping/
+vec3 aces_approx(vec3 v) {
+  v = max(v, 0.0);
+  v *= 0.6;
+  float a = 2.51;
+  float b = 0.03;
+  float c = 2.43;
+  float d = 0.59;
+  float e = 0.14;
+  return clamp((v*(a*v+b))/(v*(c*v+d)+e), 0.0, 1.0);
+}
+
+float sphere(vec3 p, float r) {
+  return length(p) - r;
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/distfunctions/
+float box(vec2 p, vec2 b) {
+  vec2 d = abs(p)-b;
+  return length(max(d,0.0)) + min(max(d.x,d.y),0.0);
+}
+  
+// License: Unknown, author: knighty, found: https://www.shadertoy.com/view/MsKGzw
+void poly_fold(inout vec3 pos) {
+  vec3 p = pos;
+
+  for(int i = 0; i < poly_type; ++i){
+    p.xy  = abs(p.xy);
+    p    -= 2.*min(0., dot(p,poly_nc)) * poly_nc;
+  }
+  
+  pos = p;
+}
+
+float poly_plane(vec3 pos) {
+  float d0 = dot(pos, poly_pab);
+  float d1 = dot(pos, poly_pbc);
+  float d2 = dot(pos, poly_pca);
+  float d = d0;
+  d = max(d, d1);
+  d = max(d, d2);
+  return d;
+}
+
+float poly_corner(vec3 pos) {
+  float d = length(pos) - .0125;
+  return d;
+}
+
+float dot2(vec3 p) {
+  return dot(p, p);
+}
+
+float poly_edge(vec3 pos) {
+  float dla = dot2(pos-min(0., pos.x)*vec3(1., 0., 0.));
+  float dlb = dot2(pos-min(0., pos.y)*vec3(0., 1., 0.));
+  float dlc = dot2(pos-min(0., dot(pos, poly_nc))*poly_nc);
+  return sqrt(min(min(dla, dlb), dlc))-2E-3;
+}
+
+vec3 shape(vec3 pos) {
+  pos *= g_rot;
+  pos /= poly_zoom;
+  poly_fold(pos);
+  pos -= poly_p;
+
+  return vec3(poly_plane(pos), poly_edge(pos), poly_corner(pos))*poly_zoom;
+}
+
+vec3 render0(vec3 ro, vec3 rd) {
+  vec3 col = vec3(0.0);
+  
+  float srd  = sign(rd.y);
+  float tp   = -(ro.y-6.)/abs(rd.y);
+
+  if (srd < 0.) {
+    col += bottomBoxCol*exp(-0.5*(length((ro + tp*rd).xz)));
+  }
+
+  if (srd > 0.0) {
+    vec3 pos  = ro + tp*rd;
+    vec2 pp = pos.xz;
+    float db = box(pp, vec2(5.0, 9.0))-3.0;
+    
+    col += topBoxCol*rd.y*rd.y*smoothstep(0.25, 0.0, db);
+    col += 0.2*topBoxCol*exp(-0.5*max(db, 0.0));
+    col += 0.05*sqrt(topBoxCol)*max(-db, 0.0);
+  }
+
+
+  col += sunCol/(1.001-dot(sunDir, rd));
+  return col; 
+}
+
+float df2(vec3 p) {
+  vec3 ds = shape(p);
+  float d2 = ds.y-5E-3;
+  float d0 = min(-ds.x, d2);
+  float d1 = sphere(p, inner_sphere);
+  g_gd = min(g_gd, vec2(d2, d1));
+  float d = (min(d0, d1));
+  return d;
+}
+
+float rayMarch2(vec3 ro, vec3 rd, float tinit) {
+  float t = tinit;
+#if defined(BACKSTEP2)
+  vec2 dti = vec2(1e10,0.0);
+#endif
+  int i;
+  for (i = 0; i < MAX_RAY_MARCHES2; ++i) {
+    float d = df2(ro + rd*t);
+#if defined(BACKSTEP2)
+    if (d<dti.x) { dti=vec2(d,t); }
+#endif  
+    // Bouncing in a closed shell, will never miss
+    if (d < TOLERANCE2/* || t > MAX_RAY_LENGTH3 */) {
+      break;
+    }
+    t += d;
+  }
+#if defined(BACKSTEP2)
+  if(i==MAX_RAY_MARCHES2) { t=dti.y; };
+#endif  
+  return t;
+}
+
+vec3 normal2(vec3 pos) {
+  vec2  eps = vec2(NORM_OFF2,0.0);
+  vec3 nor;
+  nor.x = df2(pos+eps.xyy) - df2(pos-eps.xyy);
+  nor.y = df2(pos+eps.yxy) - df2(pos-eps.yxy);
+  nor.z = df2(pos+eps.yyx) - df2(pos-eps.yyx);
+  return normalize(nor);
+}
+
+vec3 render2(vec3 ro, vec3 rd, float db) {
+  vec3 agg = vec3(0.0);
+  float ragg = 1.;
+  float tagg = 0.;
+  
+  for (int bounce = 0; bounce < MAX_BOUNCES2; ++bounce) {
+    if (ragg < 0.1) break;
+    g_gd      = vec2(1E3);
+    float t2  = rayMarch2(ro, rd, min(db+0.05, 0.3));
+    vec2 gd2  = g_gd;
+    tagg      += t2;
+    
+    vec3 p2   = ro+rd*t2;
+    vec3 n2   = normal2(p2);
+    vec3 r2   = reflect(rd, n2);
+    vec3 rr2  = refract(rd, n2, rrefr_index);
+    float fre2= 1.+dot(n2,rd);
+    
+    vec3 beer = ragg*exp(0.2*beerCol*tagg);
+    agg += glowCol1*beer*((1.+tagg*tagg*4E-2)*6./max(gd2.x, 5E-4+tagg*tagg*2E-4/ragg));
+    vec3 ocol = 0.2*beer*render0(p2, rr2);
+    if (gd2.y <= TOLERANCE2) {
+      ragg *= 1.-0.9*fre2;
+    } else {
+      agg     += ocol;
+      ragg    *= 0.8;
+    }
+    
+    ro        = p2;
+    rd        = r2;
+    db        = gd2.x; 
+  }
+
+
+  return agg;
+}
+
+float df3(vec3 p) {
+  vec3 ds = shape(p);
+  g_gd = min(g_gd, ds.yz);
+  const float sw = 0.02;
+  float d1 = min(ds.y, ds.z)-sw;
+  float d0 = ds.x;
+  d0 = min(d0, ds.y);
+  d0 = min(d0, ds.z);
+  return d0;
+}
+
+float rayMarch3(vec3 ro, vec3 rd, float tinit, out int iter) {
+  float t = tinit;
+  int i;
+  for (i = 0; i < MAX_RAY_MARCHES3; ++i) {
+    float d = df3(ro + rd*t);
+    if (d < TOLERANCE3 || t > MAX_RAY_LENGTH3) {
+      break;
+    }
+    t += d;
+  }
+  iter = i;
+  return t;
+}
+
+vec3 normal3(vec3 pos) {
+  vec2  eps = vec2(NORM_OFF3,0.0);
+  vec3 nor;
+  nor.x = df3(pos+eps.xyy) - df3(pos-eps.xyy);
+  nor.y = df3(pos+eps.yxy) - df3(pos-eps.yxy);
+  nor.z = df3(pos+eps.yyx) - df3(pos-eps.yyx);
+  return normalize(nor);
+}
+
+vec3 render3(vec3 ro, vec3 rd) {
+  int iter;
+
+  vec3 skyCol = render0(ro, rd);
+  vec3 col  = skyCol;
+
+  g_gd      = vec2(1E3);
+  float t1  = rayMarch3(ro, rd, 0.1, iter);
+  vec2 gd1  = g_gd;
+  vec3 p1   = ro+t1*rd;
+  vec3 n1   = normal3(p1);
+  vec3 r1   = reflect(rd, n1);
+  vec3 rr1  = refract(rd, n1, refr_index);
+  float fre1= 1.+dot(rd, n1);
+  fre1 *= fre1;
+
+  float ifo = mix(0.5, 1., smoothstep(1.0, 0.9, float(iter)/float(MAX_RAY_MARCHES3)));
+
+  if (t1 < MAX_RAY_LENGTH3) {
+    col = render0(p1, r1)*(0.5+0.5*fre1)*ifo;
+    vec3 icol = render2(p1, rr1, gd1.x); 
+    if (gd1.x > TOLERANCE3 && gd1.y > TOLERANCE3 && rr1 != vec3(0.)) {
+      col += icol*(1.-0.75*fre1)*ifo;
+    }
+  }
+
+  col += (glowCol0+1.*fre1*(glowCol0))/max(gd1.x, 3E-4);
+  return col;
+
+}
+
+  
+vec3 effect(vec2 p, vec2 pp) {
+  const float fov = 2.0;
+  
+  const vec3 up = vec3(0., 1., 0.);
+  const vec3 la   = vec3(0.0);
+
+  const vec3 ww = normalize(normalize(la-rayOrigin));
+  const vec3 uu = normalize(cross(up, ww));
+  const vec3 vv = cross(ww, uu);
+  
+  vec3 rd = normalize(-p.x*uu + p.y*vv + fov*ww);
+
+  vec3 col = vec3(0.0);
+  col = render3(rayOrigin, rd);
+  
+  col -= 2E-2*vec3(2.,3.,1.)*(length(p)+0.25);
+  col = aces_approx(col);
+  col = sqrt(col);
+  return col;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 q = fragCoord/RESOLUTION.xy;
+  vec2 p = -1. + 2. * q;
+  vec2 pp = p;
+  p.x *= RESOLUTION.x/RESOLUTION.y;
+
+  float a = TIME*rotation_speed;
+  vec3 r0 = vec3(1.0, sin(vec2(sqrt(0.5), 1.0)*a));
+  vec3 r1 = vec3(cos(vec2(sqrt(0.5), 1.0)*0.913*a), 1.0);
+  mat3 rot = rot(normalize(r0), normalize(r1));
+  g_rot = rot;
+
+  vec3 col = effect(p, pp);
+  
+  fragColor = vec4(col, 1.0);
+}
+
+
diff --git a/hacks/glx/glsl/skyline.glsl b/hacks/glx/glsl/skyline.glsl
new file mode 100644 (file)
index 0000000..edbe91b
--- /dev/null
@@ -0,0 +1,888 @@
+// Title:  Skyline
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/XtsSWs
+// Date:   23-Sep-2015
+// Desc:   I have always wanted to make a procedural city. The architecture was limited by what I could do in real-time, but I tried to give it enough complexity that it would look realistic.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+^ This means do ANYTHING YOU WANT with this code. Because we are programmers, not lawyers.
+-Otavio Good
+*/
+
+// ---------------- Config ----------------
+// This is an option that lets you render high quality frames for screenshots. It enables
+// stochastic antialiasing and motion blur automatically for any shader.
+//#define NON_REALTIME_HQ_RENDER
+const float frameToRenderHQ = 50.0; // Time in seconds of frame to render
+const float antialiasingSamples = 16.0; // 16x antialiasing - too much might make the shader compiler angry.
+
+//#define MANUAL_CAMERA
+
+
+// --------------------------------------------------------
+// These variables are for the non-realtime block renderer.
+float localTime = 0.0;
+float seed = 1.0;
+
+// Animation variables
+float fade = 1.0;
+vec3 sunDir;
+vec3 sunCol;
+float exposure = 1.0;
+vec3 skyCol, horizonCol;
+
+// other
+float marchCount = 0.0;
+
+// ---- noise functions ----
+float v31(vec3 a)
+{
+    return a.x + a.y * 37.0 + a.z * 521.0;
+}
+float v21(vec2 a)
+{
+    return a.x + a.y * 37.0;
+}
+float Hash11(float a)
+{
+    return fract(sin(a)*10403.9);
+}
+float Hash21(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(sin(f)*104003.9);
+}
+vec2 Hash22(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(cos(f)*vec2(10003.579, 37049.7));
+}
+vec2 Hash12(float f)
+{
+    return fract(cos(f)*vec2(10003.579, 37049.7));
+}
+float Hash1d(float u)
+{
+    return fract(sin(u)*143.9);        // scale this down to kill the jitters
+}
+float Hash2d(vec2 uv)
+{
+    float f = uv.x + uv.y * 37.0;
+    return fract(sin(f)*104003.9);
+}
+float Hash3d(vec3 uv)
+{
+    float f = uv.x + uv.y * 37.0 + uv.z * 521.0;
+    return fract(sin(f)*110003.9);
+}
+float mixP(float f0, float f1, float a)
+{
+    return mix(f0, f1, a*a*(3.0-2.0*a));
+}
+const vec2 zeroOne = vec2(0.0, 1.0);
+float noise2d(vec2 uv)
+{
+    vec2 fr = fract(uv.xy);
+    vec2 fl = floor(uv.xy);
+    float h00 = Hash2d(fl);
+    float h10 = Hash2d(fl + zeroOne.yx);
+    float h01 = Hash2d(fl + zeroOne);
+    float h11 = Hash2d(fl + zeroOne.yy);
+    return mixP(mixP(h00, h10, fr.x), mixP(h01, h11, fr.x), fr.y);
+}
+float noise(vec3 uv)
+{
+    vec3 fr = fract(uv.xyz);
+    vec3 fl = floor(uv.xyz);
+    float h000 = Hash3d(fl);
+    float h100 = Hash3d(fl + zeroOne.yxx);
+    float h010 = Hash3d(fl + zeroOne.xyx);
+    float h110 = Hash3d(fl + zeroOne.yyx);
+    float h001 = Hash3d(fl + zeroOne.xxy);
+    float h101 = Hash3d(fl + zeroOne.yxy);
+    float h011 = Hash3d(fl + zeroOne.xyy);
+    float h111 = Hash3d(fl + zeroOne.yyy);
+    return mixP(
+        mixP(mixP(h000, h100, fr.x),
+             mixP(h010, h110, fr.x), fr.y),
+        mixP(mixP(h001, h101, fr.x),
+             mixP(h011, h111, fr.x), fr.y)
+        , fr.z);
+}
+
+const float PI=3.14159265;
+
+vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); }
+vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); }
+float saturate(float a) { return clamp(a, 0.0, 1.0); }
+
+// This function basically is a procedural environment map that makes the sun
+vec3 GetSunColorSmall(vec3 rayDir, vec3 sunDir)
+{
+       vec3 localRay = normalize(rayDir);
+       float dist = 1.0 - (dot(localRay, sunDir) * 0.5 + 0.5);
+       float sunIntensity = 0.05 / dist;
+    sunIntensity += exp(-dist*150.0)*7000.0;
+       sunIntensity = min(sunIntensity, 40000.0);
+       return sunCol * sunIntensity*0.025;
+}
+
+vec3 GetEnvMap(vec3 rayDir, vec3 sunDir)
+{
+    // fade the sky color, multiply sunset dimming
+    vec3 finalColor = mix(horizonCol, skyCol, pow(saturate(rayDir.y), 0.47))*0.95;
+    // make clouds - just a horizontal plane with noise
+    float n = noise2d(rayDir.xz/rayDir.y*1.0);
+    n += noise2d(rayDir.xz/rayDir.y*2.0)*0.5;
+    n += noise2d(rayDir.xz/rayDir.y*4.0)*0.25;
+    n += noise2d(rayDir.xz/rayDir.y*8.0)*0.125;
+    n = pow(abs(n), 3.0);
+    n = mix(n * 0.2, n, saturate(abs(rayDir.y * 8.0)));  // fade clouds in distance
+    finalColor = mix(finalColor, (vec3(1.0)+sunCol*10.0)*0.75*saturate((rayDir.y+0.2)*5.0), saturate(n*0.125));
+
+    // add the sun
+    finalColor += GetSunColorSmall(rayDir, sunDir);
+    return finalColor;
+}
+
+vec3 GetEnvMapSkyline(vec3 rayDir, vec3 sunDir, float height)
+{
+    vec3 finalColor = GetEnvMap(rayDir, sunDir);
+
+    // Make a skyscraper skyline reflection.
+    float radial = atan(rayDir.z, rayDir.x)*4.0;
+    float skyline = floor((sin(5.3456*radial) + sin(1.234*radial)+ sin(2.177*radial))*0.6);
+    radial *= 4.0;
+    skyline += floor((sin(5.0*radial) + sin(1.234*radial)+ sin(2.177*radial))*0.6)*0.1;
+    float mask = saturate((rayDir.y*8.0 - skyline-2.5+height)*24.0);
+    float vert = sign(sin(radial*32.0))*0.5+0.5;
+    float hor = sign(sin(rayDir.y*256.0))*0.5+0.5;
+    mask = saturate(mask + (1.0-hor*vert)*0.05);
+    finalColor = mix(finalColor * vec3(0.1,0.07,0.05), finalColor, mask);
+
+       return finalColor;
+}
+
+// min function that supports materials in the y component
+vec2 matmin(vec2 a, vec2 b)
+{
+    if (a.x < b.x) return a;
+    else return b;
+}
+
+// ---- shapes defined by distance fields ----
+// See this site for a reference to more distance functions...
+// https://iquilezles.org/articles/distfunctions
+
+// signed box distance field
+float sdBox(vec3 p, vec3 radius)
+{
+  vec3 dist = abs(p) - radius;
+  return min(max(dist.x, max(dist.y, dist.z)), 0.0) + length(max(dist, 0.0));
+}
+
+// capped cylinder distance field
+float cylCap(vec3 p, float r, float lenRad)
+{
+    float a = length(p.xy) - r;
+    a = max(a, abs(p.z) - lenRad);
+    return a;
+}
+
+// k should be negative. -4.0 works nicely.
+// smooth blending function
+float smin(float a, float b, float k)
+{
+       return log2(exp2(k*a)+exp2(k*b))/k;
+}
+
+float Repeat(float a, float len)
+{
+    return mod(a, len) - 0.5 * len;
+}
+
+// Distance function that defines the car.
+// Basically it's 2 boxes smooth-blended together and a mirrored cylinder for the wheels.
+vec2 Car(vec3 baseCenter, float unique)
+{
+    // bottom box
+    float car = sdBox(baseCenter + vec3(0.0, -0.008, 0.001), vec3(0.01, 0.00225, 0.0275));
+    // top box smooth blended
+    car = smin(car, sdBox(baseCenter + vec3(0.0, -0.016, 0.008), vec3(0.005, 0.0005, 0.01)), -160.0);
+    // mirror the z axis to duplicate the cylinders for wheels
+    vec3 wMirror = baseCenter + vec3(0.0, -0.005, 0.0);
+    wMirror.z = abs(wMirror.z)-0.02;
+    float wheels = cylCap((wMirror).zyx, 0.004, 0.0135);
+    // Set materials
+    vec2 distAndMat = vec2(wheels, 3.0);       // car wheels
+    // Car material is some big number that's unique to each car
+    // so I can have each car be a different color
+    distAndMat = matmin(distAndMat, vec2(car, 100000.0 + unique));     // car
+    return distAndMat;
+}
+
+// How much space between voxel borders and geometry for voxel ray march optimization
+float voxelPad = 0.2;
+// p should be in [0..1] range on xz plane
+// pint is an integer pair saying which city block you are on
+vec2 CityBlock(vec3 p, vec2 pint)
+{
+    // Get random numbers for this block by hashing the city block variable
+    vec4 rand;
+    rand.xy = Hash22(pint);
+    rand.zw = Hash22(rand.xy);
+    vec2 rand2 = Hash22(rand.zw);
+
+    // Radius of the building
+    float baseRad = 0.2 + (rand.x) * 0.1;
+    baseRad = floor(baseRad * 20.0+0.5)/20.0;  // try to snap this for window texture
+
+    // make position relative to the middle of the block
+    vec3 baseCenter = p - vec3(0.5, 0.0, 0.5);
+    float height = rand.w*rand.z + 0.1; // height of first building block
+    // Make the city skyline higher in the middle of the city.
+    float downtown = saturate(4.0 / length(pint.xy));
+    height *= downtown;
+    height *= 1.5+(baseRad-0.15)*20.0;
+    height += 0.1;     // minimum building height
+    //height += sin(iTime + pint.x);   // animate the building heights if you're feeling silly
+    height = floor(height*20.0)*0.05;  // height is in floor units - each floor is 0.05 high.
+       float d = sdBox(baseCenter, vec3(baseRad, height, baseRad)); // large building piece
+
+    // road
+    d = min(d, p.y);
+
+    //if (length(pint.xy) > 8.0) return vec2(d, mat);  // Hack to LOD in the distance
+
+    // height of second building section
+    float height2 = max(0.0, rand.y * 2.0 - 1.0) * downtown;
+    height2 = floor(height2*20.0)*0.05;        // floor units
+    rand2 = floor(rand2*20.0)*0.05;    // floor units
+    // size pieces of building
+       d = min(d, sdBox(baseCenter - vec3(0.0, height, 0.0), vec3(baseRad, height2 - rand2.y, baseRad*0.4)));
+       d = min(d, sdBox(baseCenter - vec3(0.0, height, 0.0), vec3(baseRad*0.4, height2 - rand2.x, baseRad)));
+    // second building section
+    if (rand2.y > 0.25)
+    {
+               d = min(d, sdBox(baseCenter - vec3(0.0, height, 0.0), vec3(baseRad*0.8, height2, baseRad*0.8)));
+        // subtract off piece from top so it looks like there's a wall around the roof.
+        float topWidth = baseRad;
+        if (height2 > 0.0) topWidth = baseRad * 0.8;
+               d = max(d, -sdBox(baseCenter - vec3(0.0, height+height2, 0.0), vec3(topWidth-0.0125, 0.015, topWidth-0.0125)));
+    }
+    else
+    {
+        // Cylinder top section of building
+               if (height2 > 0.0) d = min(d, cylCap((baseCenter - vec3(0.0, height, 0.0)).xzy, baseRad*0.8, height2));
+    }
+    // mini elevator shaft boxes on top of building
+       d = min(d, sdBox(baseCenter - vec3((rand.x-0.5)*baseRad, height+height2, (rand.y-0.5)*baseRad),
+                     vec3(baseRad*0.3*rand.z, 0.1*rand2.y, baseRad*0.3*rand2.x+0.025)));
+    // mirror another box (and scale it) so we get 2 boxes for the price of 1.
+    vec3 boxPos = baseCenter - vec3((rand2.x-0.5)*baseRad, height+height2, (rand2.y-0.5)*baseRad);
+    float big = sign(boxPos.x);
+    boxPos.x = abs(boxPos.x)-0.02 - baseRad*0.3*rand.w;
+       d = min(d, sdBox(boxPos,
+    vec3(baseRad*0.3*rand.w, 0.07*rand.y, baseRad*0.2*rand.x + big*0.025)));
+
+    // Put domes on some building tops for variety
+    if (rand.y < 0.04)
+    {
+        d = min(d, length(baseCenter - vec3(0.0, height, 0.0)) - baseRad*0.8);
+    }
+
+    //d = max(d, p.y);  // flatten the city for debugging cars
+
+    // Need to make a material variable.
+    vec2 distAndMat = vec2(d, 0.0);
+    // sidewalk box with material
+    distAndMat = matmin(distAndMat, vec2(sdBox(baseCenter, vec3(0.35, 0.005, 0.35)), 1.0));
+
+    return distAndMat;
+}
+
+// This is the distance function that defines all the scene's geometry.
+// The input is a position in space.
+// The output is the distance to the nearest surface and a material index.
+vec2 DistanceToObject(vec3 p)
+{
+    //p.y += noise2d((p.xz)*0.0625)*8.0; // Hills
+    vec3 rep = p;
+    rep.xz = fract(p.xz); // [0..1] for representing the position in the city block
+    vec2 distAndMat = CityBlock(rep, floor(p.xz));
+
+    // Set up the cars. This is doing a lot of mirroring and repeating because I
+    // only want to do a single call to the car distance function for all the
+    // cars in the scene. And there's a lot of traffic!
+    vec3 p2 = p;
+    rep.xyz = p2;
+    float carTime = localTime*0.2;  // Speed of car driving
+    float crossStreet = 1.0;  // whether we are north/south or east/west
+    float repeatDist = 0.25;  // Car density bumper to bumper
+    // If we are going north/south instead of east/west (?) make cars that are
+    // stopped in the street so we don't have collisions.
+    if (abs(fract(rep.x)-0.5) < 0.35)
+    {
+        p2.x += 0.05;
+        p2.xz = p2.zx * vec2(-1.0,1.0);  // Rotate 90 degrees
+        rep.xz = p2.xz;
+        crossStreet = 0.0;
+        repeatDist = 0.1;  // Denser traffic on cross streets
+    }
+    
+    rep.z += floor(p2.x);      // shift so less repitition between parallel blocks
+    rep.x = Repeat(p2.x - 0.5, 1.0);   // repeat every block
+    rep.z = rep.z*sign(rep.x); // mirror but keep cars facing the right way
+    rep.x = (rep.x*sign(rep.x))-0.09;
+    rep.z -= carTime * crossStreet;    // make cars move
+    float uniqueID = floor(rep.z/repeatDist);  // each car gets a unique ID that we can use for colors
+    rep.z = Repeat(rep.z, repeatDist); // repeat the line of cars every quarter block
+    rep.x += (Hash11(uniqueID)*0.075-0.01);    // nudge cars left and right to take both lanes
+    float frontBack = Hash11(uniqueID*0.987)*0.18-0.09;
+    frontBack *= sin(localTime*2.0 + uniqueID);
+    rep.z += frontBack * crossStreet; // nudge cars forward back for variation
+    vec2 carDist = Car(rep, uniqueID); // car distance function
+
+    // Drop the cars in the scene with materials
+    distAndMat = matmin(distAndMat, carDist);
+
+    return distAndMat;
+}
+
+// This basically makes a procedural texture map for the sides of the buildings.
+// It makes a texture, a normal for normal mapping, and a mask for window reflection.
+void CalcWindows(vec2 block, vec3 pos, inout vec3 texColor, inout float windowRef, inout vec3 normal)
+{
+    vec3 hue = vec3(Hash21(block)*0.8, Hash21(block*7.89)*0.4, Hash21(block*37.89)*0.5);
+    texColor += hue*0.4;
+    texColor *= 0.75;
+    float window = 0.0;
+    window = max(window, mix(0.2, 1.0, floor(fract(pos.y*20.0-0.35)*2.0+0.1)));
+    if (pos.y < 0.05) window = 1.0;
+    float winWidth = Hash21(block*4.321)*2.0;
+    if ((winWidth < 1.3) && (winWidth >= 1.0)) winWidth = 1.3;
+    window = max(window, mix(0.2, 1.0, floor(fract(pos.x * 40.0+0.05)*winWidth)));
+    window = max(window, mix(0.2, 1.0, floor(fract(pos.z * 40.0+0.05)*winWidth)));
+    if (window < 0.5)
+    {
+        windowRef += 1.0;
+    }
+    window *= Hash21(block*1.123);
+    texColor *= window;
+
+    float wave = floor(sin((pos.y*40.0-0.1)*PI)*0.505-0.5)+1.0;
+    normal.y -= max(-1.0, min(1.0, -wave*0.5));
+    float pits = min(1.0, abs(sin((pos.z*80.0)*PI))*4.0)-1.0;
+    normal.z += pits*0.25;
+    pits = min(1.0, abs(sin((pos.x*80.0)*PI))*4.0)-1.0;
+    normal.x += pits*0.25;
+}
+
+// Input is UV coordinate of pixel to render.
+// Output is RGB color.
+vec3 RayTrace(in vec2 fragCoord )
+{
+    marchCount = 0.0;
+       // -------------------------------- animate ---------------------------------------
+    sunCol = vec3(258.0, 248.0, 200.0) / 3555.0;
+       sunDir = normalize(vec3(0.93, 1.0, 1.0));
+    horizonCol = vec3(1.0, 0.95, 0.85)*0.9;
+    skyCol = vec3(0.3,0.5,0.95);
+    exposure = 1.0;
+    fade = 1.0;
+
+       vec3 camPos, camUp, camLookat;
+       // ------------------- Set up the camera rays for ray marching --------------------
+    // Map uv to [-1.0..1.0]
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+    uv /= 2.0;  // zoom in
+
+#ifdef MANUAL_CAMERA
+    // Camera up vector.
+       camUp=vec3(0,1,0);
+
+       // Camera lookat.
+       camLookat=vec3(0,0.0,0);
+
+    // debugging camera
+    float mx=-iMouse.x/iResolution.x*PI*2.0;// + localTime * 0.05;
+       float my=iMouse.y/iResolution.y*3.14*0.5 + PI/2.0;// + sin(localTime * 0.3)*0.8+0.1;//*PI/2.01;
+       camPos = vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*7.35;//7.35
+#else
+    // Do the camera fly-by animation and different scenes.
+    // Time variables for start and end of each scene
+    const float t0 = 0.0;
+    const float t1 = 8.0;
+    const float t2 = 14.0;
+    const float t3 = 24.0;
+    const float t4 = 38.0;
+    const float t5 = 56.0;
+    const float t6 = 58.0;
+    /*const float t0 = 0.0;
+    const float t1 = 0.0;
+    const float t2 = 0.0;
+    const float t3 = 0.0;
+    const float t4 = 0.0;
+    const float t5 = 16.0;
+    const float t6 = 18.0;*/
+    // Repeat the animation after time t6
+    localTime = fract(localTime / t6) * t6;
+    if (localTime < t1)
+    {
+        float time = localTime - t0;
+        float alpha = time / (t1 - t0);
+        fade = saturate(time);
+        fade *= saturate(t1 - localTime);
+        camPos = vec3(13.0, 3.3, -3.5);
+        camPos.x -= smoothstep(0.0, 1.0, alpha) * 4.8;
+        camUp=vec3(0,1,0);
+        camLookat=vec3(0,1.5,1.5);
+    } else if (localTime < t2)
+    {
+        float time = localTime - t1;
+        float alpha = time / (t2 - t1);
+        fade = saturate(time);
+        fade *= saturate(t2 - localTime);
+        camPos = vec3(26.0, 0.05+smoothstep(0.0, 1.0, alpha)*0.4, 2.0);
+        camPos.z -= alpha * 2.8;
+        camUp=vec3(0,1,0);
+        camLookat=vec3(camPos.x-0.3,-8.15,-40.0);
+        
+        sunDir = normalize(vec3(0.95, 0.6, 1.0));
+        sunCol = vec3(258.0, 248.0, 160.0) / 3555.0;
+        exposure *= 0.7;
+        skyCol *= 1.5;
+    } else if (localTime < t3)
+    {
+        float time = localTime - t2;
+        float alpha = time / (t3 - t2);
+        fade = saturate(time);
+        fade *= saturate(t3 - localTime);
+        camPos = vec3(12.0, 6.3, -0.5);
+        camPos.y -= alpha * 5.5;
+        camPos.x = cos(alpha*1.0) * 5.2;
+        camPos.z = sin(alpha*1.0) * 5.2;
+        camUp=normalize(vec3(0,1,-0.5 + alpha * 0.5));
+        camLookat=vec3(0,1.0,-0.5);
+    } else if (localTime < t4)
+    {
+        float time = localTime - t3;
+        float alpha = time / (t4 - t3);
+        fade = saturate(time);
+        fade *= saturate(t4 - localTime);
+        camPos = vec3(2.15-alpha*0.5, 0.02, -1.0-alpha*0.2);
+        camPos.y += smoothstep(0.0,1.0,alpha*alpha) * 3.4;
+        camUp=normalize(vec3(0,1,0.0));
+        camLookat=vec3(0,0.5+alpha,alpha*5.0);
+    } else if (localTime < t5)
+    {
+        float time = localTime - t4;
+        float alpha = time / (t5 - t4);
+        fade = saturate(time);
+        fade *= saturate(t5 - localTime);
+        camPos = vec3(-2.0, 1.3- alpha*1.2, -10.5-alpha*0.5);
+        camUp=normalize(vec3(0,1,0.0));
+        camLookat=vec3(-2.0,0.3+alpha,-0.0);
+        sunDir = normalize(vec3(0.5-alpha*0.6, 0.3-alpha*0.3, 1.0));
+        sunCol = vec3(258.0, 148.0, 60.0) / 3555.0;
+        localTime *= 16.0;
+        exposure *= 0.4;
+        horizonCol = vec3(1.0, 0.5, 0.35)*2.0;
+        skyCol = vec3(0.75,0.5,0.95);
+
+    } else if (localTime < t6)
+    {
+        fade = 0.0;
+        camPos = vec3(26.0, 100.0, 2.0);
+        camUp=vec3(0,1,0);
+        camLookat=vec3(0.3,0.15,0.0);
+    }
+#endif
+
+       // Camera setup for ray tracing / marching
+       vec3 camVec=normalize(camLookat - camPos);
+       vec3 sideNorm=normalize(cross(camUp, camVec));
+       vec3 upNorm=cross(camVec, sideNorm);
+       vec3 worldFacing=(camPos + camVec);
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;
+       vec3 rayVec = normalize(worldPix - camPos);
+
+       // ----------------------------- Ray march the scene ------------------------------
+       vec2 distAndMat;  // Distance and material
+       float t = 0.05;// + Hash2d(uv)*0.1;     // random dither-fade things close to the camera
+       const float maxDepth = 45.0; // farthest distance rays will travel
+       vec3 pos = vec3(0.0);
+    const float smallVal = 0.000625;
+       // ray marching time
+    for (int i = 0; i < 250; i++)      // This is the count of the max times the ray actually marches.
+    {
+        marchCount+=1.0;
+        // Step along the ray.
+        pos = (camPos + rayVec * t);
+        // This is _the_ function that defines the "distance field".
+        // It's really what makes the scene geometry. The idea is that the
+        // distance field returns the distance to the closest object, and then
+        // we know we are safe to "march" along the ray by that much distance
+        // without hitting anything. We repeat this until we get really close
+        // and then break because we have effectively hit the object.
+        distAndMat = DistanceToObject(pos);
+
+        // 2d voxel walk through the city blocks.
+        // The distance function is not continuous at city block boundaries,
+        // so we have to pause our ray march at each voxel boundary.
+        float walk = distAndMat.x;
+        float dx = -fract(pos.x);
+        if (rayVec.x > 0.0) dx = fract(-pos.x);
+        float dz = -fract(pos.z);
+        if (rayVec.z > 0.0) dz = fract(-pos.z);
+        float nearestVoxel = min(fract(dx/rayVec.x), fract(dz/rayVec.z))+voxelPad;
+        nearestVoxel = max(voxelPad, nearestVoxel);// hack that assumes streets and sidewalks are this wide.
+        //nearestVoxel = max(nearestVoxel, t * 0.02); // hack to stop voxel walking in the distance.
+        walk = min(walk, nearestVoxel);
+
+        // move down the ray a safe amount
+        t += walk;
+        // If we are very close to the object, let's call it a hit and exit this loop.
+        if ((t > maxDepth) || (abs(distAndMat.x) < smallVal)) break;
+    }
+
+    // Ray trace a ground plane to infinity
+    float alpha = -camPos.y / rayVec.y;
+    if ((t > maxDepth) && (rayVec.y < -0.0))
+    {
+        pos.xz = camPos.xz + rayVec.xz * alpha;
+        pos.y = -0.0;
+        t = alpha;
+        distAndMat.y = 0.0;
+        distAndMat.x = 0.0;
+    }
+       // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this geometry.
+       vec3 finalColor = vec3(0.0);
+
+       // If a ray actually hit the object, let's light it.
+    if ((t <= maxDepth) || (t == alpha))
+       {
+        float dist = distAndMat.x;
+        // calculate the normal from the distance field. The distance field is a volume, so if you
+        // sample the current point and neighboring points, you can use the difference to get
+        // the normal.
+        vec3 smallVec = vec3(smallVal, 0, 0);
+        vec3 normalU = vec3(dist - DistanceToObject(pos - smallVec.xyy).x,
+                           dist - DistanceToObject(pos - smallVec.yxy).x,
+                           dist - DistanceToObject(pos - smallVec.yyx).x);
+        vec3 normal = normalize(normalU);
+
+        // calculate 2 ambient occlusion values. One for global stuff and one
+        // for local stuff
+        float ambientS = 1.0;
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.0125).x*80.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.025).x*40.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.05).x*20.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.1).x*10.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.2).x*5.0);
+        ambientS *= saturate(DistanceToObject(pos + normal * 0.4).x*2.5);
+        //ambientS *= saturate(DistanceToObject(pos + normal * 0.8).x*1.25);
+        float ambient = ambientS;// * saturate(DistanceToObject(pos + normal * 1.6).x*1.25*0.5);
+        //ambient *= saturate(DistanceToObject(pos + normal * 3.2)*1.25*0.25);
+        //ambient *= saturate(DistanceToObject(pos + normal * 6.4)*1.25*0.125);
+        ambient = max(0.025, pow(ambient, 0.5));       // tone down ambient with a pow and min clamp it.
+        ambient = saturate(ambient);
+
+        // calculate the reflection vector for highlights
+        vec3 ref = reflect(rayVec, normal);
+
+        // Trace a ray toward the sun for sun shadows
+        float sunShadow = 1.0;
+        float iter = 0.01;
+        vec3 nudgePos = pos + normal*0.002;    // don't start tracing too close or inside the object
+               for (int i = 0; i < 40; i++)
+        {
+            vec3 shadowPos = nudgePos + sunDir * iter;
+            float tempDist = DistanceToObject(shadowPos).x;
+               sunShadow *= saturate(tempDist*150.0);  // Shadow hardness
+            if (tempDist <= 0.0) break;
+
+            float walk = tempDist;
+            float dx = -fract(shadowPos.x);
+            if (sunDir.x > 0.0) dx = fract(-shadowPos.x);
+            float dz = -fract(shadowPos.z);
+            if (sunDir.z > 0.0) dz = fract(-shadowPos.z);
+            float nearestVoxel = min(fract(dx/sunDir.x), fract(dz/sunDir.z))+smallVal;
+            nearestVoxel = max(0.2, nearestVoxel);// hack that assumes streets and sidewalks are this wide.
+            walk = min(walk, nearestVoxel);
+
+            iter += max(0.01, walk);
+            if (iter > 4.5) break;
+        }
+        sunShadow = saturate(sunShadow);
+
+        // make a few frequencies of noise to give it some texture
+        float n =0.0;
+        n += noise(pos*32.0);
+        n += noise(pos*64.0);
+        n += noise(pos*128.0);
+        n += noise(pos*256.0);
+        n += noise(pos*512.0);
+        n = mix(0.7, 0.95, n);
+
+        // ------ Calculate texture color  ------
+        vec2 block = floor(pos.xz);
+        vec3 texColor = vec3(0.95, 1.0, 1.0);
+        texColor *= 0.8;
+        float windowRef = 0.0;
+        // texture map the sides of buildings
+        if ((normal.y < 0.1) && (distAndMat.y == 0.0))
+        {
+            vec3 posdx = dFdx(pos);
+            vec3 posdy = dFdy(pos);
+            vec3 posGrad = posdx * Hash21(uv) + posdy * Hash21(uv*7.6543);
+
+            // Quincunx antialias the building texture and normal map.
+            // I guess procedural textures are hard to mipmap.
+            vec3 colTotal = vec3(0.0);
+            vec3 colTemp = texColor;
+            vec3 nTemp = vec3(0.0);
+            CalcWindows(block, pos, colTemp, windowRef, nTemp);
+            colTotal = colTemp;
+
+            colTemp = texColor;
+            CalcWindows(block, pos + posdx * 0.666, colTemp, windowRef, nTemp);
+            colTotal += colTemp;
+
+            colTemp = texColor;
+            CalcWindows(block, pos + posdx * 0.666 + posdy * 0.666, colTemp, windowRef, nTemp);
+            colTotal += colTemp;
+
+            colTemp = texColor;
+            CalcWindows(block, pos + posdy * 0.666, colTemp, windowRef, nTemp);
+            colTotal += colTemp;
+
+            colTemp = texColor;
+            CalcWindows(block, pos + posdx * 0.333 + posdy * 0.333, colTemp, windowRef, nTemp);
+            colTotal += colTemp;
+
+            texColor = colTotal * 0.2;
+            windowRef *= 0.2;
+
+            normal = normalize(normal + nTemp * 0.2);
+        }
+        else
+        {
+            // Draw the road
+            float xroad = abs(fract(pos.x+0.5)-0.5);
+            float zroad = abs(fract(pos.z+0.5)-0.5);
+            float road = saturate((min(xroad, zroad)-0.143)*480.0);
+            texColor *= 1.0-normal.y*0.95*Hash21(block*9.87)*road; // change rooftop color
+            texColor *= mix(0.1, 1.0, road);
+
+            // double yellow line in middle of road
+            float yellowLine = saturate(1.0-(min(xroad, zroad)-0.002)*480.0);
+            yellowLine *= saturate((min(xroad, zroad)-0.0005)*480.0);
+            yellowLine *= saturate((xroad*xroad+zroad*zroad-0.05)*880.0);
+            texColor = mix(texColor, vec3(1.0, 0.8, 0.3), yellowLine);
+
+            // white dashed lines on road
+            float whiteLine = saturate(1.0-(min(xroad, zroad)-0.06)*480.0);
+            whiteLine *= saturate((min(xroad, zroad)-0.056)*480.0);
+            whiteLine *= saturate((xroad*xroad+zroad*zroad-0.05)*880.0);
+            whiteLine *= saturate(1.0-(fract(zroad*8.0)-0.5)*280.0);  // dotted line
+            whiteLine *= saturate(1.0-(fract(xroad*8.0)-0.5)*280.0);
+            texColor = mix(texColor, vec3(0.5), whiteLine);
+
+            whiteLine = saturate(1.0-(min(xroad, zroad)-0.11)*480.0);
+            whiteLine *= saturate((min(xroad, zroad)-0.106)*480.0);
+            whiteLine *= saturate((xroad*xroad+zroad*zroad-0.06)*880.0);
+            texColor = mix(texColor, vec3(0.5), whiteLine);
+
+            // crosswalk
+            float crossWalk = saturate(1.0-(fract(xroad*40.0)-0.5)*280.0);
+            crossWalk *= saturate((zroad-0.15)*880.0);
+            crossWalk *= saturate((-zroad+0.21)*880.0)*(1.0-road);
+            crossWalk *= n*n;
+            texColor = mix(texColor, vec3(0.25), crossWalk);
+            crossWalk = saturate(1.0-(fract(zroad*40.0)-0.5)*280.0);
+            crossWalk *= saturate((xroad-0.15)*880.0);
+            crossWalk *= saturate((-xroad+0.21)*880.0)*(1.0-road);
+            crossWalk *= n*n;
+            texColor = mix(texColor, vec3(0.25), crossWalk);
+
+            {
+                // sidewalk cracks
+                float sidewalk = 1.0;
+                vec2 blockSize = vec2(100.0);
+                if (pos.y > 0.1) blockSize = vec2(10.0, 50);
+                //sidewalk *= pow(abs(sin(pos.x*blockSize)), 0.025);
+                //sidewalk *= pow(abs(sin(pos.z*blockSize)), 0.025);
+                sidewalk *= saturate(abs(sin(pos.z*blockSize.x)*800.0/blockSize.x));
+                sidewalk *= saturate(abs(sin(pos.x*blockSize.y)*800.0/blockSize.y));
+                sidewalk = saturate(mix(0.7, 1.0, sidewalk));
+                sidewalk = saturate((1.0-road) + sidewalk);
+                texColor *= sidewalk;
+            }
+        }
+        // Car tires are almost black to not call attention to their ugly.
+        if (distAndMat.y == 3.0)
+        {
+            texColor = vec3(0.05);
+        }
+
+        // apply noise
+        texColor *= vec3(1.0)*n*0.05;
+        texColor *= 0.7;
+        texColor = saturate(texColor);
+
+        float windowMask = 0.0;
+        if (distAndMat.y >= 100.0)
+        {
+            // car texture and windows
+            texColor = vec3(Hash11(distAndMat.y)*1.0, Hash11(distAndMat.y*8.765), Hash11(distAndMat.y*17.731))*0.1;
+            texColor = pow(abs(texColor), vec3(0.2));  // bias toward white
+            texColor = max(vec3(0.25), texColor);  // not too saturated color.
+            texColor.z = min(texColor.y, texColor.z);  // no purple cars. just not realistic. :)
+            texColor *= Hash11(distAndMat.y*0.789) * 0.15;
+            windowMask = saturate( max(0.0, abs(pos.y - 0.0175)*3800.0)-10.0);
+            vec2 dirNorm = abs(normalize(normal.xz));
+            float pillars = saturate(1.0-max(dirNorm.x, dirNorm.y));
+            pillars = pow(max(0.0, pillars-0.15), 0.125);
+            windowMask = max(windowMask, pillars);
+            texColor *= windowMask;
+        }
+
+        // ------ Calculate lighting color ------
+        // Start with sun color, standard lighting equation, and shadow
+        vec3 lightColor = vec3(100.0)*sunCol * saturate(dot(sunDir, normal)) * sunShadow;
+        // weighted average the near ambient occlusion with the far for just the right look
+        float ambientAvg = (ambient*3.0 + ambientS) * 0.25;
+        // Add sky color with ambient acclusion
+        lightColor += (skyCol * saturate(normal.y *0.5+0.5))*pow(ambientAvg, 0.35)*2.5;
+        lightColor *= 4.0;
+
+        // finally, apply the light to the texture.
+        finalColor = texColor * lightColor;
+        // Reflections for cars
+        if (distAndMat.y >= 100.0)
+        {
+            float yfade = max(0.01, min(1.0, ref.y*100.0));
+            // low-res way of making lines at the edges of car windows. Not sure I like it.
+            yfade *= (saturate(1.0-abs(dFdx(windowMask)*dFdy(windowMask))*250.995));
+            finalColor += GetEnvMapSkyline(ref, sunDir, pos.y-1.5)*0.3*yfade*max(0.4,sunShadow);
+// jwz: GLSL 4.10, GLES 3.0: "No matching function for call to texture(sampler2D, vec3)"
+//     This must just be an error; dunno why it works on the shadertoy web site.
+//          finalColor += saturate(texture(iChannel0, ref).xyz-0.35)*0.15*max(0.2,sunShadow);
+            finalColor += saturate(texture(iChannel0, ref.xy).xyz-0.35)*0.15*max(0.2,sunShadow);
+        }
+        // reflections for building windows
+        if (windowRef != 0.0)
+        {
+            finalColor *= mix(1.0, 0.6, windowRef);
+            float yfade = max(0.01, min(1.0, ref.y*100.0));
+            finalColor += GetEnvMapSkyline(ref, sunDir, pos.y-0.5)*0.6*yfade*max(0.6,sunShadow)*windowRef;//*(windowMask*0.5+0.5);
+// jwz: GLSL 4.10, GLES 3.0: "No matching function for call to texture(sampler2D, vec3)"
+//          finalColor += saturate(texture(iChannel0, ref).xyz-0.35)*0.15*max(0.25,sunShadow)*windowRef;
+            finalColor += saturate(texture(iChannel0, ref.xy).xyz-0.35)*0.15*max(0.25,sunShadow)*windowRef;
+        }
+        finalColor *= 0.9;
+        // fog that fades to reddish plus the sun color so that fog is brightest towards sun
+        vec3 rv2 = rayVec;
+        rv2.y *= saturate(sign(rv2.y));
+        vec3 fogColor = GetEnvMap(rv2, sunDir);
+        fogColor = min(vec3(9.0), fogColor);
+        finalColor = mix(fogColor, finalColor, exp(-t*0.02));
+
+        // visualize length of gradient of distance field to check distance field correctness
+        //finalColor = vec3(0.5) * (length(normalU) / smallVec.x);
+        //finalColor = vec3(marchCount)/255.0;
+       }
+    else
+    {
+        // Our ray trace hit nothing, so draw sky.
+        finalColor = GetEnvMap(rayVec, sunDir);
+    }
+
+    // vignette?
+    finalColor *= vec3(1.0) * saturate(1.0 - length(uv/2.5));
+    finalColor *= 1.3*exposure;
+
+       // output the final color without gamma correction - will do gamma later.
+       return vec3(clamp(finalColor, 0.0, 1.0)*saturate(fade+0.2));
+}
+
+#ifdef NON_REALTIME_HQ_RENDER
+// This function breaks the image down into blocks and scans
+// through them, rendering 1 block at a time. It's for non-
+// realtime things that take a long time to render.
+
+// This is the frame rate to render at. Too fast and you will
+// miss some blocks.
+const float blockRate = 20.0;
+void BlockRender(in vec2 fragCoord)
+{
+    // blockSize is how much it will try to render in 1 frame.
+    // adjust this smaller for more complex scenes, bigger for
+    // faster render times.
+    const float blockSize = 64.0;
+    // Make the block repeatedly scan across the image based on time.
+    float frame = floor(iTime * blockRate);
+    vec2 blockRes = floor(iResolution.xy / blockSize) + vec2(1.0);
+    // ugly bug with mod.
+    //float blockX = mod(frame, blockRes.x);
+    float blockX = fract(frame / blockRes.x) * blockRes.x;
+    //float blockY = mod(floor(frame / blockRes.x), blockRes.y);
+    float blockY = fract(floor(frame / blockRes.x) / blockRes.y) * blockRes.y;
+    // Don't draw anything outside the current block.
+    if ((fragCoord.x - blockX * blockSize >= blockSize) ||
+       (fragCoord.x - (blockX - 1.0) * blockSize < blockSize) ||
+       (fragCoord.y - blockY * blockSize >= blockSize) ||
+       (fragCoord.y - (blockY - 1.0) * blockSize < blockSize))
+    {
+        discard;
+    }
+}
+#endif
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+#ifdef NON_REALTIME_HQ_RENDER
+    // Optionally render a non-realtime scene with high quality
+    BlockRender(fragCoord);
+#endif
+
+    // Do a multi-pass render
+    vec3 finalColor = vec3(0.0);
+#ifdef NON_REALTIME_HQ_RENDER
+    for (float i = 0.0; i < antialiasingSamples; i++)
+    {
+        const float motionBlurLengthInSeconds = 1.0 / 60.0;
+        // Set this to the time in seconds of the frame to render.
+           localTime = frameToRenderHQ;
+        // This line will motion-blur the renders
+        localTime += Hash11(v21(fragCoord + seed)) * motionBlurLengthInSeconds;
+        // Jitter the pixel position so we get antialiasing when we do multiple passes.
+        vec2 jittered = fragCoord.xy + vec2(
+            Hash21(fragCoord + seed),
+            Hash21(fragCoord*7.234567 + seed)
+            );
+        // don't antialias if only 1 sample.
+        if (antialiasingSamples == 1.0) jittered = fragCoord;
+        // Accumulate one pass of raytracing into our pixel value
+           finalColor += RayTrace(jittered);
+        // Change the random seed for each pass.
+           seed *= 1.01234567;
+    }
+    // Average all accumulated pixel intensities
+    finalColor /= antialiasingSamples;
+#else
+    // Regular real-time rendering
+    localTime = iTime;
+    finalColor = RayTrace(fragCoord);
+#endif
+
+    fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
+
+
diff --git a/hacks/glx/glsl/stardome.glsl b/hacks/glx/glsl/stardome.glsl
new file mode 100644 (file)
index 0000000..39e20d1
--- /dev/null
@@ -0,0 +1,300 @@
+// Title:  Stars and galaxy
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/stBcW1
+// Date:   10-Apr-2022
+// Desc:   License CC0: Stars and galaxy
+// Bit of sunday tinkering lead to stars and a galaxy
+// Didn't turn out as I envisioned but it turned out to something
+// that I liked so sharing it.
+
+// License CC0: Stars and galaxy
+// Bit of sunday tinkering lead to stars and a galaxy
+// Didn't turn out as I envisioned but it turned out to something
+// that I liked so sharing it.
+
+// Controls how many layers of stars
+#define LAYERS            5.0
+
+#define PI                3.141592654
+#define TAU               (2.0*PI)
+#define TIME              mod(iTime, 30.0)
+#define TTIME             (TAU*TIME)
+#define RESOLUTION        iResolution
+#define ROT(a)            mat2(cos(a), sin(a), -sin(a), cos(a))
+
+// License: Unknown, author: nmz (twitter: @stormoid), found: https://www.shadertoy.com/view/NdfyRM
+float sRGB(float t) { return mix(1.055*pow(t, 1./2.4) - 0.055, 12.92*t, step(t, 0.0031308)); }
+// License: Unknown, author: nmz (twitter: @stormoid), found: https://www.shadertoy.com/view/NdfyRM
+vec3 sRGB(in vec3 c) { return vec3 (sRGB(c.x), sRGB(c.y), sRGB(c.z)); }
+
+// License: Unknown, author: Matt Taylor (https://github.com/64), found: https://64.github.io/tonemapping/
+vec3 aces_approx(vec3 v) {
+  v = max(v, 0.0);
+  v *= 0.6f;
+  float a = 2.51f;
+  float b = 0.03f;
+  float c = 2.43f;
+  float d = 0.59f;
+  float e = 0.14f;
+  return clamp((v*(a*v+b))/(v*(c*v+d)+e), 0.0f, 1.0f);
+}
+
+// License: Unknown, author: Unknown, found: don't remember
+float tanh_approx(float x) {
+  //  Found this somewhere on the interwebs
+  //  return tanh(x);
+  float x2 = x*x;
+  return clamp(x*(27.0 + x2)/(27.0+9.0*x2), -1.0, 1.0);
+}
+
+
+// License: WTFPL, author: sam hocevar, found: https://stackoverflow.com/a/17897228/418488
+const vec4 hsv2rgb_K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
+vec3 hsv2rgb(vec3 c) {
+  vec3 p = abs(fract(c.xxx + hsv2rgb_K.xyz) * 6.0 - hsv2rgb_K.www);
+  return c.z * mix(hsv2rgb_K.xxx, clamp(p - hsv2rgb_K.xxx, 0.0, 1.0), c.y);
+}
+
+// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/
+vec2 mod2(inout vec2 p, vec2 size) {
+  vec2 c = floor((p + size*0.5)/size);
+  p = mod(p + size*0.5,size) - size*0.5;
+  return c;
+}
+
+// License: Unknown, author: Unknown, found: don't remember
+vec2 hash2(vec2 p) {
+  p = vec2(dot (p, vec2 (127.1, 311.7)), dot (p, vec2 (269.5, 183.3)));
+  return fract(sin(p)*43758.5453123);
+}
+
+vec2 shash2(vec2 p) {
+  return -1.0+2.0*hash2(p);
+}
+
+vec3 toSpherical(vec3 p) {
+  float r   = length(p);
+  float t   = acos(p.z/r);
+  float ph  = atan(p.y, p.x);
+  return vec3(r, t, ph);
+}
+
+
+// License: CC BY-NC-SA 3.0, author: Stephane Cuillerdier - Aiekick/2015 (twitter:@aiekick), found: https://www.shadertoy.com/view/Mt3GW2
+vec3 blackbody(float Temp) {
+  vec3 col = vec3(255.);
+  col.x = 56100000. * pow(Temp,(-3. / 2.)) + 148.;
+  col.y = 100.04 * log(Temp) - 623.6;
+  if (Temp > 6500.) col.y = 35200000. * pow(Temp,(-3. / 2.)) + 184.;
+  col.z = 194.18 * log(Temp) - 1448.6;
+  col = clamp(col, 0., 255.)/255.;
+  if (Temp < 1000.) col *= Temp/1000.;
+  return col;
+}
+
+
+// License: MIT, author: Inigo Quilez, found: https://www.shadertoy.com/view/XslGRr
+float noise(vec2 p) {
+  // Found at https://www.shadertoy.com/view/sdlXWX
+  // Which then redirected to IQ shader
+  vec2 i = floor(p);
+  vec2 f = fract(p);
+  vec2 u = f*f*(3.-2.*f);
+  
+  float n =
+         mix( mix( dot(shash2(i + vec2(0.,0.) ), f - vec2(0.,0.)), 
+                   dot(shash2(i + vec2(1.,0.) ), f - vec2(1.,0.)), u.x),
+              mix( dot(shash2(i + vec2(0.,1.) ), f - vec2(0.,1.)), 
+                   dot(shash2(i + vec2(1.,1.) ), f - vec2(1.,1.)), u.x), u.y);
+
+  return 2.0*n;              
+}
+
+float fbm(vec2 p, float o, float s, int iters) {
+  p *= s;
+  p += o;
+
+  const float aa = 0.5;
+  const mat2 pp = 2.04*ROT(1.0);
+
+  float h = 0.0;
+  float a = 1.0;
+  float d = 0.0;
+  for (int i = 0; i < iters; ++i) {
+    d += a;
+    h += a*noise(p);
+    p += vec2(10.7, 8.3);
+    p *= pp;
+    a *= aa;
+  }
+  h /= d;
+  
+  return h;
+}
+
+float height(vec2 p) {
+  float h = fbm(p, 0.0, 5.0, 5);
+  h *= 0.3;
+  h += 0.0;
+  return (h);
+}
+
+vec3 stars(vec3 ro, vec3 rd, vec2 sp, float hh) {
+  vec3 col = vec3(0.0);
+  
+  const float m = LAYERS;
+  hh = tanh_approx(20.0*hh);
+
+  for (float i = 0.0; i < m; ++i) {
+    vec2 pp = sp+0.5*i;
+    float s = i/(m-1.0);
+    vec2 dim  = vec2(mix(0.05, 0.003, s)*PI);
+    vec2 np = mod2(pp, dim);
+    vec2 h = hash2(np+127.0+i);
+    vec2 o = -1.0+2.0*h;
+    float y = sin(sp.x);
+    pp += o*dim*0.5;
+    pp.y *= y;
+    float l = length(pp);
+  
+    float h1 = fract(h.x*1667.0);
+    float h2 = fract(h.x*1887.0);
+    float h3 = fract(h.x*2997.0);
+
+    vec3 scol = mix(8.0*h2, 0.25*h2*h2, s)*blackbody(mix(3000.0, 22000.0, h1*h1));
+
+    vec3 ccol = col + exp(-(mix(6000.0, 2000.0, hh)/mix(2.0, 0.25, s))*max(l-0.001, 0.0))*scol;
+    col = h3 < y ? ccol : col;
+  }
+  
+  return col;
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/spherefunctions
+vec2 raySphere(vec3 ro, vec3 rd, vec4 sph) {
+  vec3 oc = ro - sph.xyz;
+  float b = dot( oc, rd );
+  float c = dot( oc, oc ) - sph.w*sph.w;
+  float h = b*b - c;
+  if( h<0.0 ) return vec2(-1.0);
+  h = sqrt( h );
+  return vec2(-b - h, -b + h);
+}
+
+
+vec4 moon(vec3 ro, vec3 rd, vec2 sp, vec3 lp, vec4 md) {
+  vec2 mi = raySphere(ro, rd, md);
+  
+  vec3 p    = ro + mi.x*rd;
+  vec3 n    = normalize(p-md.xyz);
+  vec3 r    = reflect(rd, n);
+  vec3 ld   = normalize(lp - p);
+  float fre = dot(n, rd)+1.0;
+  fre = pow(fre, 15.0);
+  float dif = max(dot(ld, n), 0.0);
+  float spe = pow(max(dot(ld, r), 0.0), 8.0);
+  float i = 0.5*tanh_approx(20.0*fre*spe+0.05*dif);
+  vec3 col = blackbody(1500.0)*i+hsv2rgb(vec3(0.6, mix(0.6, 0.0, i), i));
+
+  float t = tanh_approx(0.25*(mi.y-mi.x));
+ 
+  return vec4(vec3(col), t);
+}
+
+vec3 sky(vec3 ro, vec3 rd, vec2 sp, vec3 lp, out float cf) {
+  float ld = max(dot(normalize(lp-ro), rd),0.0);
+  float y = -0.5+sp.x/PI;
+  y = max(abs(y)-0.02, 0.0)+0.1*smoothstep(0.5, PI, abs(sp.y));
+  vec3 blue = hsv2rgb(vec3(0.6, 0.75, 0.35*exp(-15.0*y)));
+  float ci = pow(ld, 10.0)*2.0*exp(-25.0*y); 
+  vec3 yellow = blackbody(1500.0)*ci;
+  cf = ci;
+  return blue+yellow;
+}
+
+vec3 galaxy(vec3 ro, vec3 rd, vec2 sp, out float sf) {
+  vec2 gp = sp;
+  gp *= ROT(0.67);
+  gp += vec2(-1.0, 0.5);
+  float h1 = height(2.0*sp);
+  float gcc = dot(gp, gp);
+  float gcx = exp(-(abs(3.0*(gp.x))));
+  float gcy = exp(-abs(10.0*(gp.y)));
+  float gh = gcy*gcx;
+  float cf = smoothstep(0.05, -0.2, -h1);
+  vec3 col = vec3(0.0);
+  col += blackbody(mix(300.0, 1500.0, gcx*gcy))*gcy*gcx;
+  col += hsv2rgb(vec3(0.6, 0.5, 0.00125/gcc));
+  col *= mix(mix(0.15, 1.0, gcy*gcx), 1.0, cf);
+  sf = gh*cf;
+  return col;
+}
+
+vec3 grid(vec3 ro, vec3 rd, vec2 sp) {
+  const float m = 1.0;
+
+  const vec2 dim = vec2(1.0/8.0*PI);
+  vec2 pp = sp;
+  vec2 np = mod2(pp, dim);
+
+  vec3 col = vec3(0.0);
+
+  float y = sin(sp.x);
+  float d = min(abs(pp.x), abs(pp.y*y));
+  
+  float aa = 2.0/RESOLUTION.y;
+  
+  col += 2.0*vec3(0.5, 0.5, 1.0)*exp(-2000.0*max(d-0.00025, 0.0));
+  
+  return 0.25*tanh(col);
+}
+
+vec3 color(vec3 ro, vec3 rd, vec3 lp, vec4 md) {
+  vec2 sp = toSpherical(rd.xzy).yz;
+
+  float sf = 0.0;
+  float cf = 0.0;
+  vec3 col = vec3(0.0);
+
+  vec4 mcol = moon(ro, rd, sp, lp, md);
+
+  col += stars(ro, rd, sp, sf)*(1.0-tanh_approx(2.0*cf));
+  col += galaxy(ro, rd, sp, sf);
+  col = mix(col, mcol.xyz, mcol.w);
+  col += sky(ro, rd, sp, lp, cf);
+  col += grid(ro, rd, sp);
+
+  if (rd.y < 0.0)
+  {
+    col = vec3(0.0);
+  }
+
+  return col;
+}
+
+void mainImage(out vec4 fragColor, in vec2 fragCoord) {
+  vec2 q = fragCoord/iResolution.xy;
+  vec2 p = -1.0 + 2.0*q;
+  p.x *= RESOLUTION.x/RESOLUTION.y;
+
+  vec3 ro = vec3(0.0, 0.0, 0.0);
+  vec3 lp = 500.0*vec3(1.0, -0.25, 0.0);
+  vec4 md = 50.0*vec4(vec3(1.0, 1., -0.6), 0.5);
+  vec3 la = vec3(1.0, 0.5, 0.0);
+  vec3 up = vec3(0.0, 1.0, 0.0);
+  la.xz *= ROT(TTIME/60.0-PI/2.0);
+  
+  vec3 ww = normalize(la - ro);
+  vec3 uu = normalize(cross(up, ww));
+  vec3 vv = normalize(cross(ww,uu));
+  vec3 rd = normalize(p.x*uu + p.y*vv + 2.0*ww);
+  vec3 col= color(ro, rd, lp, md);
+  
+  col *= smoothstep(0.0, 4.0, TIME)*smoothstep(30.0, 26.0, TIME);
+  col = aces_approx(col);
+  col = sRGB(col);
+
+  fragColor = vec4(col,1.0);
+}
+
+
diff --git a/hacks/glx/glsl/starnest.glsl b/hacks/glx/glsl/starnest.glsl
new file mode 100644 (file)
index 0000000..c33601b
--- /dev/null
@@ -0,0 +1,70 @@
+// Title:  Star Nest
+// Author: Kali
+// URL:    https://www.shadertoy.com/view/XlfGRj
+// Date:   16-Jun-2013
+// Desc:   3D kaliset fractal - volumetric rendering and some tricks. I put the params on top to play with. Mouse enabled to explore different regions.
+
+// Star Nest by Pablo Roman Andrioli
+// License: MIT
+
+#define iterations 17
+#define formuparam 0.53
+
+#define volsteps 20
+#define stepsize 0.1
+
+#define zoom   0.800
+#define tile   0.850
+#define speed  0.010 
+
+#define brightness 0.0015
+#define darkmatter 0.300
+#define distfading 0.730
+#define saturation 0.850
+
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+       //get coords and direction
+       vec2 uv=fragCoord.xy/iResolution.xy-.5;
+       uv.y*=iResolution.y/iResolution.x;
+       vec3 dir=vec3(uv*zoom,1.);
+       float time=iTime*speed+.25;
+
+       //mouse rotation
+       float a1=.5+iMouse.x/iResolution.x*2.;
+       float a2=.8+iMouse.y/iResolution.y*2.;
+       mat2 rot1=mat2(cos(a1),sin(a1),-sin(a1),cos(a1));
+       mat2 rot2=mat2(cos(a2),sin(a2),-sin(a2),cos(a2));
+       dir.xz*=rot1;
+       dir.xy*=rot2;
+       vec3 from=vec3(1.,.5,0.5);
+       from+=vec3(time*2.,time,-2.);
+       from.xz*=rot1;
+       from.xy*=rot2;
+       
+       //volumetric rendering
+       float s=0.1,fade=1.;
+       vec3 v=vec3(0.);
+       for (int r=0; r<volsteps; r++) {
+               vec3 p=from+s*dir*.5;
+               p = abs(vec3(tile)-mod(p,vec3(tile*2.))); // tiling fold
+               float pa,a=pa=0.;
+               for (int i=0; i<iterations; i++) { 
+                       p=abs(p)/dot(p,p)-formuparam; // the magic formula
+                       a+=abs(length(p)-pa); // absolute sum of average change
+                       pa=length(p);
+               }
+               float dm=max(0.,darkmatter-a*a*.001); //dark matter
+               a*=a*a; // add contrast
+               if (r>6) fade*=1.-dm; // dark matter, don't render near
+               //v+=vec3(dm,dm*.5,0.);
+               v+=fade;
+               v+=vec3(s,s*s,s*s*s*s)*a*brightness*fade; // coloring based on distance
+               fade*=distfading; // distance fading
+               s+=stepsize;
+       }
+       v=mix(vec3(length(v)),v,saturation); //color adjust
+       fragColor = vec4(v*.01,1.);     
+       
+}
diff --git a/hacks/glx/glsl/stripeytorus.glsl b/hacks/glx/glsl/stripeytorus.glsl
new file mode 100644 (file)
index 0000000..7244a05
--- /dev/null
@@ -0,0 +1,200 @@
+// Title:  Saturday Torus
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/fd33zn
+// Date:   14-Aug-2021
+// Desc:   License CC0: Saturday Torus
+// Inspired by: https://www.istockphoto.com/photo/black-and-white-stripes-projection-on-torus-gm488221403-39181884
+
+// License CC0: Saturday Torus
+//  Inspired by: https://www.istockphoto.com/photo/black-and-white-stripes-projection-on-torus-gm488221403-39181884
+
+#define PI          3.141592654
+#define TAU         (2.0*PI)
+#define TIME        iTime
+#define TTIME       (TAU*TIME)
+#define RESOLUTION  iResolution
+#define ROT(a)      mat2(cos(a), sin(a), -sin(a), cos(a))
+#define PCOS(x)     (0.5+0.5*cos(x))
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/intersectors
+float rayTorus(vec3 ro, vec3 rd, vec2 tor) {
+  float po = 1.0;
+
+  float Ra2 = tor.x*tor.x;
+  float ra2 = tor.y*tor.y;
+
+  float m = dot(ro,ro);
+  float n = dot(ro,rd);
+
+  // bounding sphere
+  {
+    float h = n*n - m + (tor.x+tor.y)*(tor.x+tor.y);
+    if(h<0.0) return -1.0;
+    //float t = -n-sqrt(h); // could use this to compute intersections from ro+t*rd
+  }
+
+  // find quartic equation
+  float k = (m - ra2 - Ra2)/2.0;
+  float k3 = n;
+  float k2 = n*n + Ra2*rd.z*rd.z + k;
+  float k1 = k*n + Ra2*ro.z*rd.z;
+  float k0 = k*k + Ra2*ro.z*ro.z - Ra2*ra2;
+
+  #ifndef TORUS_REDUCE_PRECISION
+  // prevent |c1| from being too close to zero
+  if(abs(k3*(k3*k3 - k2) + k1) < 0.01)
+  {
+    po = -1.0;
+    float tmp=k1; k1=k3; k3=tmp;
+    k0 = 1.0/k0;
+    k1 = k1*k0;
+    k2 = k2*k0;
+    k3 = k3*k0;
+  }
+  #endif
+
+  float c2 = 2.0*k2 - 3.0*k3*k3;
+  float c1 = k3*(k3*k3 - k2) + k1;
+  float c0 = k3*(k3*(-3.0*k3*k3 + 4.0*k2) - 8.0*k1) + 4.0*k0;
+
+
+  c2 /= 3.0;
+  c1 *= 2.0;
+  c0 /= 3.0;
+
+  float Q = c2*c2 + c0;
+  float R = 3.0*c0*c2 - c2*c2*c2 - c1*c1;
+
+  float h = R*R - Q*Q*Q;
+  float z = 0.0;
+  if(h < 0.0) {
+    // 4 intersections
+    float sQ = sqrt(Q);
+    z = 2.0*sQ*cos(acos(R/(sQ*Q)) / 3.0);
+  } else {
+    // 2 intersections
+    float sQ = pow(sqrt(h) + abs(R), 1.0/3.0);
+    z = sign(R)*abs(sQ + Q/sQ);
+  }
+  z = c2 - z;
+
+  float d1 = z   - 3.0*c2;
+  float d2 = z*z - 3.0*c0;
+  if(abs(d1) < 1.0e-4) {
+    if(d2 < 0.0) return -1.0;
+    d2 = sqrt(d2);
+  } else {
+    if(d1 < 0.0) return -1.0;
+    d1 = sqrt(d1/2.0);
+    d2 = c1/d1;
+  }
+
+  //----------------------------------
+
+  float result = 1e20;
+
+  h = d1*d1 - z + d2;
+  if(h > 0.0) {
+    h = sqrt(h);
+    float t1 = -d1 - h - k3; t1 = (po<0.0)?2.0/t1:t1;
+    float t2 = -d1 + h - k3; t2 = (po<0.0)?2.0/t2:t2;
+    if(t1 > 0.0) result=t1;
+    if(t2 > 0.0) result=min(result,t2);
+  }
+
+  h = d1*d1 - z - d2;
+  if(h > 0.0) {
+    h = sqrt(h);
+    float t1 = d1 - h - k3;  t1 = (po<0.0)?2.0/t1:t1;
+    float t2 = d1 + h - k3;  t2 = (po<0.0)?2.0/t2:t2;
+    if(t1 > 0.0) result=min(result,t1);
+    if(t2 > 0.0) result=min(result,t2);
+  }
+
+  return result;
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/articles/intersectors
+vec3 torusNormal(vec3 pos, vec2 tor) {
+  return normalize(pos*(dot(pos,pos)- tor.y*tor.y - tor.x*tor.x*vec3(1.0,1.0,-1.0)));
+}
+
+// License: Unknown, author: Unknown, found: don't remember
+float tanh_approx(float x) {
+  //  Found this somewhere on the interwebs
+  //  return tanh(x);
+  float x2 = x*x;
+  return clamp(x*(27.0 + x2)/(27.0+9.0*x2), -1.0, 1.0);
+}
+
+vec3 color(vec2 p, vec2 q) {
+  const float rdd = 2.0;
+  vec3 ro  = 1.*vec3(0., 0.75, -0.2);
+  vec3 la  = vec3(0.0, 0.0, 0.2);
+  vec3 up  = vec3(0.3, 0.0, 1.0);
+  vec3 lp1 = ro;
+  lp1.xy  *= ROT(0.85);
+  lp1.xz  *= ROT(-0.5);
+
+  vec3 ww = normalize(la - ro);
+  vec3 uu = normalize(cross(up, ww));
+  vec3 vv = normalize(cross(ww,uu));
+  vec3 rd = normalize(p.x*uu + p.y*vv + rdd*ww);
+
+  const vec2 tor = 0.55*vec2(1.0, 0.75);
+  float td    = rayTorus(ro, rd, tor);
+  vec3  tpos  = ro + rd*td;
+  vec3  tnor  = -torusNormal(tpos, tor);
+  vec3  tref  = reflect(rd, tnor);
+
+  vec3  ldif1 = lp1 - tpos;
+  float ldd1  = dot(ldif1, ldif1);
+  float ldl1  = sqrt(ldd1);
+  vec3  ld1   = ldif1/ldl1;
+  vec3  sro   = tpos+0.05*tnor;
+  float sd    = rayTorus(sro, ld1, tor);
+  vec3  spos  = sro+ld1*sd;
+  vec3  snor  = -torusNormal(spos, tor);
+
+  float dif1  = max(dot(tnor, ld1), 0.0);
+  float spe1  = pow(max(dot(tref, ld1), 0.0), 10.0);
+  float r     = length(tpos.xy);
+  float a     = atan(tpos.y, tpos.x)-PI*tpos.z/(r+0.5*abs(tpos.z))-TTIME/45.0;
+  float s     = mix(0.05, 0.5, tanh_approx(2.0*abs(td-0.75)));
+  vec3  bcol0 = vec3(0.3);  
+  vec3  bcol1 = vec3(0.025);  
+  vec3  tcol  = mix(bcol0, bcol1, smoothstep(-s, s, sin(9.0*a)));
+
+  vec3 col = vec3(0.0);
+
+  if (td > -1.0) {
+    col += tcol*mix(0.2, 1.0, dif1/ldd1)+0.25*spe1;
+    col *= sqrt(abs(dot(rd, tnor)));
+  }
+  
+  if (sd < ldl1) {
+    col *= mix(1.0, 0.0, pow(abs(dot(ld1, snor)), 3.0*tanh_approx(sd)));
+  }
+
+  return col;
+}
+
+// License: MIT, author: Inigo Quilez, found: https://iquilezles.org/www/index.htm
+vec3 postProcess(vec3 col, vec2 q) {
+  col = clamp(col, 0.0, 1.0);
+  col = pow(col, 1.0/vec3(2.2));
+  col = col*0.6+0.4*col*col*(3.0-2.0*col);
+  col = mix(col, vec3(dot(col, vec3(0.33))), -0.4);
+  col *=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7);
+  return col;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 q = fragCoord/iResolution.xy;
+  vec2 p = -1. + 2. * q;
+  p.x *= RESOLUTION.x/RESOLUTION.y;
+  vec3 col = color(p, q);
+  col = postProcess(col, q);
+  fragColor = vec4(col, 1.0);
+}
+
diff --git a/hacks/glx/glsl/synthwavecity.glsl b/hacks/glx/glsl/synthwavecity.glsl
new file mode 100644 (file)
index 0000000..798b8ce
--- /dev/null
@@ -0,0 +1,116 @@
+// Title:  Synthwave City
+// Author: 3w36zj6
+// URL:    https://www.shadertoy.com/view/7lKyDD
+// Date:   26-Aug-2022
+// Desc:   Original: https://www.shadertoy.com/view/3t3GDB
+
+// Original: https://www.shadertoy.com/view/3t3GDB
+// Original License: CC BY 3.0
+// Original Author: Jan Mróz (jaszunio15)
+
+float sdSkyscraper(vec2 p, float w, float h)
+{
+  vec2 k1 = vec2(0.0, h);
+  vec2 k2 = vec2(-w, h);
+  p.x = abs(p.x);
+  vec2 ca = p - vec2(0.0, h);
+  vec2 cb = p - k1 + k2;
+  float s = (cb.x < 0.0 && ca.y < 0.0) ? - 1.0 : 1.0;
+  return s * (dot(ca, ca));
+}
+
+float sun(vec2 uv, float battery)
+{
+  float val = smoothstep(0.7, 0.69, length(uv));
+  float bloom = smoothstep(0.7, 0.0, length(uv));
+  float cut = 5.0 * sin((uv.y + iTime * 0.2 * (1.02)) * 60.0)
+    + clamp(uv.y * 15.0, -6.0, 6.0);
+  cut = clamp(cut, 0.0, 1.0);
+  return clamp(val * cut, 0.0, 1.0) + bloom * 0.6;
+}
+
+float grid(vec2 uv, float battery)
+{
+  vec2 size = vec2(uv.y, uv.y * uv.y * 0.2) * 0.01;
+  uv += vec2(0.0, iTime * 4.0 * (battery + 0.05));
+  uv = abs(fract(uv) - 0.5);
+  vec2 lines = smoothstep(size, vec2(0.0), uv);
+  lines += smoothstep(size * 5.0, vec2(0.0), uv) * 0.4 * battery;
+  return clamp(lines.x + lines.y, 0.0, 3.0);
+}
+
+void mainImage(out vec4 fragColor, in vec2 fragCoord)
+{
+  vec2 uv = (2.0 * fragCoord.xy - iResolution.xy) / iResolution.y;
+  float battery = 1.0;
+
+  float fog = smoothstep(0.2, -0.05, abs(uv.y + 0.2));
+  vec3 col = vec3(0.0, 0.1, 0.2);
+  if (uv.y < -0.2)
+  {
+    uv.y = 3.0 / (abs(uv.y + 0.2) + 0.05);
+    uv.x *= uv.y * 1.0;
+    float gridVal = grid(uv, battery);
+    col = mix(col, vec3(1.0, 0.25, 0.5), gridVal);
+  }
+  else
+  {
+    uv.y -= 0.34;
+    col = vec3(1.0, 0.4, 0.4);
+    float sunVal = sun(uv, battery);
+    col = mix(col, vec3(1.0, 0.85, 0.3), uv.y * 2.5 + 0.2);
+    col = mix(vec3(0.0, 0.0, 0.0), col, sunVal);
+    //uv.y += 0.37;
+    col += vec3(0.1 + 1.25 * (1.0 - smoothstep(-0.2, 0.8, (0.2 + uv.y))), 0.15 * (1.0 - smoothstep(-0.2, 0.8, (0.2 + uv.y))), 0.7 - 0.45 * (smoothstep(-0.2, 0.8, (0.2 + uv.y))));
+    //col += vec3(0.75,0.1,0.45);
+
+    // bldg
+    uv.y -= 0.2;
+    float bldgD = max(-uv.y * 1.2 + 0.18, 0.0);
+    float bldgVal1 = sdSkyscraper(uv + vec2(0.1 * mod(0.0 + iTime, 40.0) - 2.0, 0.5), 0.1, 0.15);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal1, 0.0));
+    float bldgVal2 = sdSkyscraper(uv + vec2(0.1 * mod(2.5 + iTime, 40.0) - 2.0, 0.5), 0.1, 0.2);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal2, 0.0));
+    float bldgVal3 = sdSkyscraper(uv + vec2(0.1 * mod(6.0 + iTime, 40.0) - 2.0, 0.5), 0.2, 0.05);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal3, 0.0));
+    float bldgVal4 = sdSkyscraper(uv + vec2(0.1 * mod(0.0 + iTime, 40.0) - 2.0, 0.5), 0.02, 0.35);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal4, 0.0));
+
+    float bldgVal5 = sdSkyscraper(uv + vec2(0.1 * mod(10.5 + iTime, 40.0) - 2.0, 0.5), 0.2, 0.25);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal5, 0.0));
+    float bldgVal6 = sdSkyscraper(uv + vec2(0.1 * mod(13.0 + iTime, 40.0) - 2.0, 0.5), 0.2, 0.12);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal6, 0.0));
+    float bldgVal7 = sdSkyscraper(uv + vec2(0.1 * mod(16.0 + iTime, 40.0) - 2.0, 0.5), 0.05, 0.2);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal7, 0.0));
+    float bldgVal8 = sdSkyscraper(uv + vec2(0.1 * mod(17.0 + iTime, 40.0) - 2.0, 0.5), 0.08, 0.3);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal8, 0.0));
+
+    float bldgVal9 = sdSkyscraper(uv + vec2(0.1 * mod(20.0 + iTime, 40.0) - 2.0, 0.5), 0.18, 0.4);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal9, 0.0));
+    float bldgVal10 = sdSkyscraper(uv + vec2(0.1 * mod(24.5 + iTime, 40.0) - 2.0, 0.5), 0.23, 0.02);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal10, 0.0));
+    float bldgVal11 = sdSkyscraper(uv + vec2(0.1 * mod(27.8 + iTime, 40.0) - 2.0, 0.5), 0.05, 0.315);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal11, 0.0));
+    float bldgVal12 = sdSkyscraper(uv + vec2(0.1 * mod(30.0 + iTime, 40.0) - 2.0, 0.5), 0.14, 0.1);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal12, 0.0));
+
+    float bldgVal13 = sdSkyscraper(uv + vec2(0.1 * mod(32.2 + iTime, 40.0) - 2.0, 0.5), 0.06, 0.03);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal13, 0.0));
+    float bldgVal14 = sdSkyscraper(uv + vec2(0.1 * mod(34.1 + iTime, 40.0) - 2.0, 0.5), 0.09, 0.02);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal14, 0.0));
+    float bldgVal15 = sdSkyscraper(uv + vec2(0.1 * mod(37.0 + iTime, 40.0) - 2.0, 0.5), 0.1, 0.315);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal15, 0.0));
+    float bldgVal16 = sdSkyscraper(uv + vec2(0.1 * mod(36.9 + iTime, 40.0) - 2.0, 0.5), 0.14, 0.27);
+    col = mix(col, mix(vec3(0.0, 0.0, 0.25), vec3(1.0, 0.0, 0.5), bldgD), step(bldgVal16, 0.0));
+
+    float bldgVal = min(min(min(min(bldgVal1, bldgVal2), min(bldgVal3, bldgVal4)), min(min(bldgVal5, bldgVal6), min(bldgVal7, bldgVal8))), min(min(min(bldgVal9, bldgVal10), min(bldgVal11, bldgVal12)), min(min(bldgVal13, bldgVal14), min(bldgVal15, bldgVal16))));
+
+    //col += mix( col, mix(vec3(1.0, 0.12, 0.8), vec3(0.0, 0.0, 0.2), clamp(uv.y * 3.5 + 3.0, 0.0, 1.0)), step(0.0, bldgVal) );
+  }
+
+  col += fog * fog * fog;
+  col = mix(vec3(0.75, 0.1, 0.45) * 0.2, col, battery * 0.7);
+
+  fragColor = vec4(col, 1.0);
+}
+
diff --git a/hacks/glx/glsl/topologica.glsl b/hacks/glx/glsl/topologica.glsl
new file mode 100644 (file)
index 0000000..d73ed65
--- /dev/null
@@ -0,0 +1,110 @@
+// Title:  Topologica
+// Author: otaviogood
+// URL:    https://www.shadertoy.com/view/4djXzz
+// Date:   20-Aug-2014
+// Desc:   At some point I stopped understanding exactly what makes this work, but it just kept getting cooler. Mostly, it's stepping through a low frequency noise function that ramps up to a 1/x pulse. But then there are lots of tweaks on top of that.
+
+/*--------------------------------------------------------------------------------------
+License CC0 - http://creativecommons.org/publicdomain/zero/1.0/
+To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
+----------------------------------------------------------------------------------------
+^ This means do ANYTHING YOU WANT with this code. Because we are programmers, not lawyers.
+-Otavio Good
+*/
+
+// various noise functions
+float Hash3d(vec3 uv)
+{
+    float f = uv.x + uv.y * 37.0 + uv.z * 521.0;
+    return fract(cos(f*3.333)*100003.9);
+}
+float mixP(float f0, float f1, float a)
+{
+    return mix(f0, f1, a*a*(3.0-2.0*a));
+}
+const vec2 zeroOne = vec2(0.0, 1.0);
+float noise(vec3 uv)
+{
+    vec3 fr = fract(uv.xyz);
+    vec3 fl = floor(uv.xyz);
+    float h000 = Hash3d(fl);
+    float h100 = Hash3d(fl + zeroOne.yxx);
+    float h010 = Hash3d(fl + zeroOne.xyx);
+    float h110 = Hash3d(fl + zeroOne.yyx);
+    float h001 = Hash3d(fl + zeroOne.xxy);
+    float h101 = Hash3d(fl + zeroOne.yxy);
+    float h011 = Hash3d(fl + zeroOne.xyy);
+    float h111 = Hash3d(fl + zeroOne.yyy);
+    return mixP(
+        mixP(mixP(h000, h100, fr.x), mixP(h010, h110, fr.x), fr.y),
+        mixP(mixP(h001, h101, fr.x), mixP(h011, h111, fr.x), fr.y)
+        , fr.z);
+}
+
+float PI=3.14159265;
+#define saturate(a) clamp(a, 0.0, 1.0)
+// Weird for loop trick so compiler doesn't unroll loop
+// By making the zero a variable instead of a constant, the compiler can't unroll the loop and
+// that speeds up compile times by a lot.
+#define ZERO_TRICK max(0, -iFrame)
+
+float Density(vec3 p)
+{
+    float final = noise(p*0.06125);
+    float other = noise(p*0.06125 + 1234.567);
+    other -= 0.5;
+    final -= 0.5;
+    final = 0.1/(abs(final*final*other));
+    final += 0.5;
+    return final*0.0001;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord )
+{
+       // ---------------- First, set up the camera rays for ray marching ----------------
+       vec2 uv = fragCoord.xy/iResolution.xy * 2.0 - 1.0;
+
+       // Camera up vector.
+       vec3 camUp=vec3(0,1,0); // vuv
+
+       // Camera lookat.
+       vec3 camLookat=vec3(0,0.0,0);   // vrp
+
+       float mx=iMouse.x/iResolution.x*PI*2.0 + iTime * 0.01;
+       float my=-iMouse.y/iResolution.y*10.0 + sin(iTime * 0.03)*0.2+0.2;//*PI/2.01;
+       vec3 camPos=vec3(cos(my)*cos(mx),sin(my),cos(my)*sin(mx))*(200.2);      // prp
+
+       // Camera setup.
+       vec3 camVec=normalize(camLookat - camPos);//vpn
+       vec3 sideNorm=normalize(cross(camUp, camVec));  // u
+       vec3 upNorm=cross(camVec, sideNorm);//v
+       vec3 worldFacing=(camPos + camVec);//vcv
+       vec3 worldPix = worldFacing + uv.x * sideNorm * (iResolution.x/iResolution.y) + uv.y * upNorm;//scrCoord
+       vec3 relVec = normalize(worldPix - camPos);//scp
+
+       // --------------------------------------------------------------------------------
+       float t = 0.0;
+       float inc = 0.02;
+       float maxDepth = 70.0;
+       vec3 pos = vec3(0,0,0);
+    float density = 0.0;
+       // ray marching time
+    for (int i = ZERO_TRICK; i < 37; i++)      // This is the count of how many times the ray actually marches.
+    {
+        if ((t > maxDepth)) break;
+        pos = camPos + relVec * t;
+        float temp = Density(pos);
+
+        inc = 1.9 + temp*0.05; // add temp because this makes it look extra crazy!
+        density += temp * inc;
+        t += inc;
+    }
+
+       // --------------------------------------------------------------------------------
+       // Now that we have done our ray marching, let's put some color on this.
+       vec3 finalColor = vec3(0.01,0.1,1.0)* density*0.2;
+
+       // output the final color with sqrt for "gamma correction"
+       fragColor = vec4(sqrt(clamp(finalColor, 0.0, 1.0)),1.0);
+}
+
diff --git a/hacks/glx/glsl/truchetzoom.glsl b/hacks/glx/glsl/truchetzoom.glsl
new file mode 100644 (file)
index 0000000..665c738
--- /dev/null
@@ -0,0 +1,234 @@
+// Title:  Another truchet experiment
+// Author: mrange
+// URL:    https://www.shadertoy.com/view/4cBcDy
+// Date:   05-Aug-2024
+// Desc:   CC0: Another truchet experiment
+//   That's it for tonight
+
+// CC0: Another truchet experiment
+//  That's it for tonight
+
+#define DISTORT
+
+
+#define TIME        iTime
+#define RESOLUTION  iResolution
+#define ROT(a)      mat2(cos(a), sin(a), -sin(a), cos(a))
+
+const float
+  pi    = acos(-1.)
+, tau   = pi*2.
+, phi   = (1.+sqrt(5.))*0.5
+, phi2  = phi*phi
+, phi3  = phi*phi2
+, phi4  = phi2*phi2
+, iphi  = 1./phi
+, iphi2 = 1./phi2
+, iphi3 = 1./phi3
+, iphi4 = 1./phi4
+;
+
+float geometric(float a, float r) {
+  return a/(1.-r);
+}
+
+float igeometric(float a, float r, float x) {
+  return log2(1.-x*(1.-r)/a)/log2(r);
+}
+
+vec2 geometric2(float a, float r, float n) {
+  float rn = pow(r, n);
+  float rn1 = rn*r;
+  return (a/(1.-r))*(1.-vec2(rn, rn1));
+}
+
+float badSquare(vec2 p, float b) {
+  vec2 d = abs(p)-b;
+  return max(d.x,d.y);
+}
+
+vec4 boxySpiralCoord(vec2 p, float z, out float side) {
+  float px = p.x;
+  float ax = abs(px);
+  float sx = sign(px);
+  float a = px > 0. ? phi2 : 1.;
+  a *= z;
+  float gdx     = geometric(a, iphi4); 
+  ax            -= gdx;
+  float x       = igeometric(a, iphi4, -ax);
+  float nx      = floor(x);
+  vec2  lx      = geometric2(a, iphi4, nx)-gdx;
+  float minx    = lx.x;
+  float maxx    = lx.y;
+  float radiusx = (maxx-minx)*0.5;
+  float meanx   = minx+radiusx;
+  
+  p -= vec2(-1.,1./3.)*meanx*sx;
+  side = sx;
+  return vec4(p, radiusx, 2.*nx+(sx>0.?0.:1.));
+}
+
+vec2 toSmith(vec2 p)  {
+  // z = (p + 1)/(-p + 1)
+  // (x,y) = ((1+x)*(1-x)-y*y,2y)/((1-x)*(1-x) + y*y)
+  float d = (1.0 - p.x)*(1.0 - p.x) + p.y*p.y;
+  float x = (1.0 + p.x)*(1.0 - p.x) - p.y*p.y;
+  float y = 2.0*p.y;
+  return vec2(x,y)/d;
+}
+
+vec2 fromSmith(vec2 p)  {
+  // z = (p - 1)/(p + 1)
+  // (x,y) = ((x+1)*(x-1)+y*y,2y)/((x+1)*(x+1) + y*y)
+  float d = (p.x + 1.0)*(p.x + 1.0) + p.y*p.y;
+  float x = (p.x + 1.0)*(p.x - 1.0) + p.y*p.y;
+  float y = 2.0*p.y;
+  return vec2(x,y)/d;
+}
+
+
+vec2 transform(vec2 p) {
+#ifdef DISTORT  
+  vec2 sp0 = toSmith(p-0.);
+  vec2 sp1 = toSmith(p+vec2(1.0)*ROT(0.12*TIME));
+  vec2 sp2 = toSmith(p-vec2(1.0)*ROT(0.23*TIME));
+  p = fromSmith(sp0+sp1-sp2);
+  p *= ROT(-TIME*0.125);
+#endif
+
+  return p;
+}
+
+float segment(vec2 p, vec3 sz) {
+  p.x = abs(p.x);
+  p.x -= sz.x;
+  
+  float d = 
+      p.x > 0.
+    ? length(p)
+    : abs(p.y)
+    ;
+  d -= sz.y;
+  d = abs(d);
+  d -= sz.z;
+
+  return d;
+
+}
+
+float big(float anim, float n) {
+  float a = 0.125*pi*n+tau*anim*2.;
+  return 0.75+0.25*smoothstep((0.5), 0.9, sin(a));
+}
+
+vec3 effect(vec3 col, vec2 p) {
+  const float aas = 1.;
+  vec2 np = p + aas/RESOLUTION.y;
+  vec2 tp = transform(p);
+  vec2 ntp = transform(np);
+  float aa = sqrt(2.0)/aas*distance(tp, ntp);
+  p = tp;
+
+
+  float anim = TIME*0.125;
+
+  float pft = fract(anim);
+  float nft = floor(anim);
+  float piz = exp2(log2(phi4)*pft);
+  float sx;
+  float sy;
+  vec4 gcx = boxySpiralCoord(p, piz,sx);
+  vec4 gcy = boxySpiralCoord(vec2(p.y,-p.x), phi*piz,sy);
+
+  float dbx = badSquare(gcx.xy, gcx.z);
+  float dby = badSquare(gcy.xy, gcy.z);
+
+  float nx = 1.+2.*gcx.w+4.*nft;
+  float ny = 2.*gcy.w+4.*nft;
+
+  float db;
+  vec4 gc;
+  float n;
+  float s; 
+  if (dbx < dby) {
+    db = dbx;
+    gc = gcx;
+    n = nx;
+    s = sx;
+  } else {
+    db = dby;
+    gc = gcy;
+    n = ny;
+    s = sy;
+  }
+  
+  if (s == -1.) {
+    gc.xy = -gc.xy;
+  }
+ 
+  float l3 = length(gc.xy-gc.z*vec2(1.,-1.));
+  float l4 = length(gc.xy+gc.z*vec2(1.,-1.));
+  float l5 = length(gc.xy-gc.z*vec2(-1.,-1.+2.*iphi));
+
+  float f = gc.z*iphi*0.7;
+  float cr = gc.z*0.02;
+  float ds3 = l3 - big(anim, n)*f*phi2*phi;
+  float ds4 = l4 - big(anim, n+3.)*f;
+  float ds5 = l5 - big(anim, n+4.)*iphi*f;
+
+
+  float dbkg, dfgd;
+
+  float w = 0.025*gc.z; 
+  float h = 0.12*gc.z;
+
+  dbkg = segment((gc.xy-gc.z).yx, vec3(h*phi4,f*phi,w*phi3));
+  dbkg = min(dbkg, segment((gc.xy+gc.z), vec3(h*phi3,f,w*phi2)));
+  dbkg = min(dbkg, abs(ds4)-w);
+  dbkg = min(dbkg, abs(ds5)-w*iphi);
+
+  dbkg = min(dbkg, l5 - cr);
+  dbkg = min(dbkg, l4 - cr*phi);
+  dbkg = min(dbkg, l3 - cr*phi4);
+
+  float sw = w;
+  dfgd = segment((gc.xy-gc.z*vec2(-1.,-1.+2.*(iphi+iphi4))).yx, vec3(h,f*iphi3,w*iphi));
+  float dfgd_ = abs(ds3)-w*phi3;
+  if (dfgd_ < dfgd) {
+    dfgd = dfgd_;
+  } else {
+    sw *= iphi3;
+  }
+
+  const vec3 ocol = vec3(0.);
+  vec3 bcol = vec3(sqrt(0.5));
+  const vec3 fcol = vec3(sqrt(0.5));
+
+  if (dbkg < dfgd) {
+    bcol *= 1.-exp(-max(dfgd/sw,0.));
+  }
+  
+  col = mix(col, bcol, smoothstep(aa, -aa, dbkg));
+  col = mix(col, fcol, smoothstep(aa, -aa, dfgd));
+
+  return col;
+}
+
+void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
+  vec2 q = fragCoord/RESOLUTION.xy;
+  vec2 p = -1. + 2. * q;
+  p += 1E-3;
+  p.x *= RESOLUTION.x/RESOLUTION.y;
+
+  vec2 fc = fragCoord;
+  float thickness = 4.;  // jwz
+  vec3 col = vec3(mod(fc.y,thickness*2.) < thickness ? 0.05 : 0.0);
+  col = effect(col, p);
+
+
+  col = sqrt(col);
+  
+  fragColor = vec4(col, 1.0);
+}
+
+
index 2ee1c6505621eefbb0920cc1c1f3e430ceb85b07..51a2bcda64100e73fd6b9af3ad41da7922aef986 100644 (file)
@@ -142,7 +142,8 @@ typedef struct {
   int nsprites;                        /* how many sprites are animating right now */
   sprite *sprites[10];         /* pointers to the live sprites */
 
-  anim_state state;
+  anim_state state;            /* state of the overall animation */
+  double title_opacity;                /* the state of the image title */
 
   double now;                  /* current time in seconds */
   double dawn_of_time;         /* when the program launched */
@@ -1219,7 +1220,8 @@ tick_sprites (ModeInfo *mi)
                   ostate == IN_PANZOOM     ? "IN_PANZOOM" :
                   ostate == MID_PANZOOM    ? "MID_PANZOOM" :
                   ostate == RECENTER       ? "RECENTER" :
-                  ostate == TRANSITION_OUT ? "TRANSITION_OUT" : "???"),
+                  ostate == TRANSITION_OUT ? "TRANSITION_OUT" :
+                  ostate == TRANSITION_PANZOOM ? "TRANSITION_PANZOOM" : "???"),
                  (ss->state == LOADING        ? "LOADING" :
                   ss->state == FIRST_IN       ? "FIRST_IN" :
                   ss->state == IN_PANZOOM     ? "IN_PANZOOM" :
@@ -1395,6 +1397,58 @@ tick_sprites (ModeInfo *mi)
       fprintf (stderr, "%s: %d sprites\n", blurb(), ss->nsprites);
       abort();
     }
+
+  /* The state machine for drawing titles is a bit disconnected from the
+     rest of the state machine, since there's a single title that spans
+     multiple sprites. We want to start it fading in once an image is
+     fully visible, and start it fading out before the transition to a
+     new image.  And either or both of transition_seconds or fade_seconds
+     might be 0.
+   */
+  if (do_titles)
+    {
+      double oopacity = ss->title_opacity;
+      double t = ss->now - ss->start_time;
+
+      /* When should the title start fading in? */
+      double start = (transition_seconds
+                      ? transition_seconds
+                      : fade_seconds);
+
+      /* When should the title finish fading out? */
+      double end = (transition_seconds && fade_seconds
+                    ? image_seconds + fade_seconds
+                    : transition_seconds
+                    ? image_seconds
+                    : image_seconds - fade_seconds);
+
+      double sec_fade = 3;     /* Duration of fade for titles */
+      double dur;
+
+      /* Try to show titles even if --duration is very short. */
+      dur = end - start;
+      if (sec_fade > dur / 2)
+        sec_fade = dur / 2;
+
+      if (transition_seconds == 0 && fade_seconds == 0)
+        sec_fade = 0;  /* If images are doing jump cuts, so do titles. */
+
+      if (dur <= 0.5 && sec_fade > 0)
+        ss->title_opacity = 0;                                 /* DEAD */
+      else if (t <= start)
+        ss->title_opacity = 0;                                 /* NEW  */
+      else if (t <= start + sec_fade)
+        ss->title_opacity = (t - start) / sec_fade;            /* IN   */
+      else if (t <= end - sec_fade)
+        ss->title_opacity = 1;                                 /* FULL */
+      else if (t <= end)
+        ss->title_opacity = (end - t) / sec_fade;              /* OUT  */
+      else
+        ss->title_opacity = 0;                                 /* DEAD */
+
+      if (ss->title_opacity != oopacity)
+        ss->redisplay_needed_p = True;
+    }
 }
 
 
@@ -1427,7 +1481,7 @@ draw_sprites (ModeInfo *mi)
   for (i = 0; i < ss->nsprites; i++)
     draw_sprite (mi, ss->sprites[i]);
 
-  if (do_titles)
+  if (do_titles && ss->title_opacity > 0)
     {
       sprite *sp = (ss->nsprites > 0
                     ? ss->sprites[ss->nsprites-1]
@@ -1435,20 +1489,7 @@ draw_sprites (ModeInfo *mi)
       if (sp && sp->img && sp->img->loaded_p &&
           sp->img->title && *sp->img->title)
         {
-          double start = (transition_seconds
-                          ? transition_seconds : fade_seconds);
-          double end   = (image_seconds -
-                          (transition_seconds ? 0 : pan_seconds));
-          double secs = ss->now - ss->start_time;
-          double sec_fade = 3;
-          GLfloat alpha = 1;
-          if (secs - start <= sec_fade)
-            alpha = (secs - start) / sec_fade;
-          else if (secs + sec_fade >= end)
-            alpha = (end - secs) / sec_fade;
-          if (alpha < 0) alpha = 0;
-          if (alpha > 1) alpha = 1;
-          glColor4f (1, 1, 1, alpha);
+          glColor4f (1, 1, 1, ss->title_opacity);
           print_texture_label (mi->dpy, ss->font_data,
                                mi->xgwa.width, mi->xgwa.height,
                                1, sp->img->title);
@@ -1742,7 +1783,7 @@ init_slideshow (ModeInfo *mi)
              blurb(), transition_seconds, pan_seconds, fade_seconds,
              image_seconds, zoom);
 
-  sanity_check(mi);
+  sanity_check (mi);
 
   if (verbose_p)
     fprintf (stderr,
diff --git a/hacks/glx/hexplasma.man b/hacks/glx/hexplasma.man
new file mode 100644 (file)
index 0000000..ca3f064
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+hexplasma \- hexagon plasma screen saver.
+.SH SYNOPSIS
+.B hexplasma
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+A hexagon in a plasma field.
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/3fy3z3
+.SH COPYRIGHT
+Copyright \(co 2025 by Nemerix.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Nemerix, 2025.
index abc20973924e69c14a53c253d16a61fd1cae53a2..2780dd31b1300decec45152d7ad65fec0f928041 100644 (file)
@@ -4,7 +4,7 @@
 static const char sccsid[] = "@(#)hopffibration.c  1.1 25/02/01 xlockmore";
 #endif
 
-/* Copyright (c) 2025 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2025-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -21,6 +21,7 @@ static const char sccsid[] = "@(#)hopffibration.c  1.1 25/02/01 xlockmore";
  *
  * REVISION HISTORY:
  * C. Steger - 25/02/06: Initial version
+ * C. Steger - 26/01/02: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -490,7 +491,7 @@ typedef struct {
   float *norm;
   int *tri;
   Bool use_shaders, use_msaa_fbo, use_shadow_fbo;
-  Bool shadow_fbo_req_col_tex;
+  Bool shadow_fbo_req_col_tex, use_vao;
   GLuint shader_program, shadow_program;
   GLint pos_index, normal_index, color_index;
   GLint mv_index, proj_index, lmvp_index;
@@ -513,6 +514,7 @@ typedef struct {
   GLuint base_point_num_tri;
   GLuint default_draw_fbo, default_read_fbo;
   GLuint msaa_fbo, msaa_rb_color, msaa_rb_depth;
+  GLuint vertex_array_object;
   GLint msaa_samples;
   GLuint shadow_fbo;
   GLuint shadow_tex, shadow_col_tex, shadow_dummy_tex;
@@ -539,180 +541,169 @@ static float base_offset[3] = {
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n"
-  "precision highp sampler2DShadow;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "attribute vec3 VertexNormal;\n"
-  "attribute vec4 VertexColor;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 ShadowCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "in vec3 VertexNormal;\n"
-  "in vec4 VertexColor;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "out vec4 ShadowCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform mat4 MatLightMVP;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  Color = VertexColor;\n"
-  "  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  ShadowCoord = 0.5f*MatLightMVP*vec4(VertexPosition,1.0f)+0.5f;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 ShadowCoord;\n"
-  "\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatAmbient;\n"
-  "uniform vec4 MatDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool UseShadows;\n"
-  "uniform float ShadowPixSize;\n"
-  "uniform sampler2DShadow ShadowTex;\n"
-  "\n"
-  "float SampleShadowPCF(int x, int y)\n"
-  "{\n"
-  "  vec4 offset;\n"
-  "  \n"
-  "  offset = vec4(x*ShadowPixSize,y*ShadowPixSize,0.0f,0.0f);\n"
-  "  return shadow2DProj(ShadowTex,ShadowCoord+offset).x;\n"
-  "}\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "in vec4 ShadowCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatAmbient;\n"
-  "uniform vec4 MatDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool UseShadows;\n"
-  "uniform float ShadowPixSize;\n"
-  "uniform sampler2DShadow ShadowTex;\n"
-  "\n"
-  "float SampleShadowPCF(int x, int y)\n"
-  "{\n"
-  "  vec4 offset;\n"
-  "  \n"
-  "  offset = vec4(float(x)*ShadowPixSize,float(y)*ShadowPixSize,0.0f,0.0f);\n"
-  "  return textureProj(ShadowTex,ShadowCoord+offset);\n"
-  "}\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  "void main (void)\n"
-  "{\n"
-  "  vec3 normalDirection;\n"
-  "  vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "  vec4 ambientLighting, diffuseReflection, specularReflection, color;\n"
-  "  float ndotl, ndoth, pf, shadowPCF;\n"
-  "  int i, j;\n"
-  "  \n"
-  "  if (gl_FrontFacing)\n"
-  "    normalDirection = normalize(Normal);\n"
-  "  else\n"
-  "    normalDirection = -normalize(Normal);\n"
-  "  sceneColor = Color*MatAmbient*LtGlblAmbient;\n"
-  "  ambientColor = Color*MatAmbient;\n"
-  "  diffuseColor = Color*MatDiffuse;\n"
-  "  \n"
-  "  if (UseShadows)\n"
-  "  {\n"
-  "    shadowPCF = 0.0f;\n"
-  "    for (i=-1; i<=1; i++)\n"
-  "      for (j=-1; j<=1; j++)\n"
-  "        shadowPCF += SampleShadowPCF(i,j);\n"
-  "    shadowPCF *= 1.0f/9.0f;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    shadowPCF = 1.0f;\n"
-  "  }\n"
-  "  \n"
-  "  ndotl = max(0.0f,dot(normalDirection,LtDirection));\n"
-  "  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));\n"
-  "  if (ndotl == 0.0f)\n"
-  "    pf = 0.0f;\n"
-  "  else\n"
-  "    pf = pow(ndoth,MatShininess);\n"
-  "  ambientLighting = ambientColor*LtAmbient;\n"
-  "  diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "  specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "  color = sceneColor+ambientLighting;\n"
-  "  color += shadowPCF*(diffuseReflection+specularReflection);\n"
-  "  color.a = diffuseColor.a;\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "  gl_FragColor = clamp(color,0.0f,1.0f);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "  FragColor = clamp(color,0.0f,1.0f);\n"
-  "}\n";
-
-
-/* The shadow vertex shader code is composed of code fragments that depend
-   on the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *shadow_vertex_shader_attribs_2_1 =
-  "attribute vec4 VertexPosition;\n"
-  "\n";
-static const GLchar *shadow_vertex_shader_attribs_3_0 =
-  "in vec4 VertexPosition;\n"
-  "\n";
-static const GLchar *shadow_vertex_shader_main =
-  "uniform mat4 MatLightMVP;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  gl_Position = MatLightMVP*VertexPosition;\n"
-  "}\n";
-
-/* The shadow fragment shader code is composed of a single code fragment
-   that does not depend on the OpenGL version. */
-static const GLchar *shadow_fragment_shader_main =
-  "void main (void)\n"
-  "{\n"
-  "  // Nothing to do since depth is handled automatically by OpenGL.\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2DShadow;                                         \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+attribute vec3 VertexNormal;                                             \n\
+attribute vec4 VertexColor;                                              \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 ShadowCoord;                                                \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+in vec3 VertexNormal;                                                    \n\
+in vec4 VertexColor;                                                     \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+out vec4 ShadowCoord;                                                    \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform mat4 MatLightMVP;                                                \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  Color = VertexColor;                                                   \n\
+  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;          \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+  ShadowCoord = 0.5f*MatLightMVP*vec4(VertexPosition,1.0f)+0.5f;         \n\
+}                                                                        \n";
+
+/* The fragment shader code. */
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2DShadow;                                         \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 ShadowCoord;                                                \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+in vec4 ShadowCoord;                                                     \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatAmbient;                                                 \n\
+uniform vec4 MatDiffuse;                                                 \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool UseShadows;                                                 \n\
+uniform float ShadowPixSize;                                             \n\
+uniform sampler2DShadow ShadowTex;                                       \n\
+                                                                         \n\
+float SampleShadowPCF(int x, int y)                                      \n\
+{                                                                        \n\
+  vec4 offset;                                                           \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+  offset = vec4(x*ShadowPixSize,y*ShadowPixSize,0.0f,0.0f);              \n\
+  return shadow2DProj(ShadowTex,ShadowCoord+offset).x;                   \n\
+#else                                                                    \n\
+  offset = vec4(float(x)*ShadowPixSize,float(y)*ShadowPixSize,           \n\
+                0.0f,0.0f);                                              \n\
+  return textureProj(ShadowTex,ShadowCoord+offset);                      \n\
+#endif                                                                   \n\
+}                                                                        \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec3 normalDirection;                                                  \n\
+  vec4 ambientColor, diffuseColor, sceneColor;                           \n\
+  vec4 ambientLighting, diffuseReflection, specularReflection, color;    \n\
+  float ndotl, ndoth, pf, shadowPCF;                                     \n\
+  int i, j;                                                              \n\
+                                                                         \n\
+  if (gl_FrontFacing)                                                    \n\
+    normalDirection = normalize(Normal);                                 \n\
+  else                                                                   \n\
+    normalDirection = -normalize(Normal);                                \n\
+  sceneColor = Color*MatAmbient*LtGlblAmbient;                           \n\
+  ambientColor = Color*MatAmbient;                                       \n\
+  diffuseColor = Color*MatDiffuse;                                       \n\
+                                                                         \n\
+  if (UseShadows)                                                        \n\
+  {                                                                      \n\
+    shadowPCF = 0.0f;                                                    \n\
+    for (i=-1; i<=1; i++)                                                \n\
+      for (j=-1; j<=1; j++)                                              \n\
+        shadowPCF += SampleShadowPCF(i,j);                               \n\
+    shadowPCF *= 1.0f/9.0f;                                              \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    shadowPCF = 1.0f;                                                    \n\
+  }                                                                      \n\
+                                                                         \n\
+  ndotl = max(0.0f,dot(normalDirection,LtDirection));                    \n\
+  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));                   \n\
+  if (ndotl == 0.0f)                                                     \n\
+    pf = 0.0f;                                                           \n\
+  else                                                                   \n\
+    pf = pow(ndoth,MatShininess);                                        \n\
+  ambientLighting = ambientColor*LtAmbient;                              \n\
+  diffuseReflection = LtDiffuse*diffuseColor*ndotl;                      \n\
+  specularReflection = LtSpecular*MatSpecular*pf;                        \n\
+  color = sceneColor+ambientLighting;                                    \n\
+  color += shadowPCF*(diffuseReflection+specularReflection);             \n\
+  color.a = diffuseColor.a;                                              \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0f,1.0f);                                 \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0f,1.0f);                                    \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+
+/* The shadow vertex shader code. */
+static const GLchar *shadow_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2DShadow;                                         \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec4 VertexPosition;                                           \n\
+#else                                                                    \n\
+in vec4 VertexPosition;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatLightMVP;                                                \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  gl_Position = MatLightMVP*VertexPosition;                              \n\
+}                                                                        \n";
+
+/* The shadow fragment shader code. */
+static const GLchar *shadow_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2DShadow;                                         \n\
+#endif                                                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  // Nothing to do since depth is handled automatically by OpenGL.       \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -2156,6 +2147,9 @@ static int draw_hopf_circles_pf(ModeInfo *mi)
 
   hf->num_poly = 0;
 
+  if (hf->use_vao)
+    glBindVertexArray(hf->vertex_array_object);
+
   len = norm(light_pos);
   light_direction[0] = light_pos[0]/len;
   light_direction[1] = light_pos[1]/len;
@@ -2490,6 +2484,9 @@ static int draw_hopf_circles_pf(ModeInfo *mi)
 
   glBindTexture(GL_TEXTURE_2D,0);
 
+  if (hf->use_vao)
+    glBindVertexArray(0);
+
   return hf->num_poly;
 }
 
@@ -3041,8 +3038,8 @@ static void init_glsl(ModeInfo *mi)
   hopffibrationstruct *hf = &hopffibration[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
   GLint samples, sample_buffers;
   const char *gl_ext;
   static float one = 1.0f;
@@ -3052,56 +3049,18 @@ static void init_glsl(ModeInfo *mi)
   hf->use_shadow_fbo = False;
   hf->shader_program = 0;
   hf->shadow_program = 0;
+  hf->use_vao = False;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
 
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &hf->shader_program))
     return;
 
@@ -3168,44 +3127,11 @@ static void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = shadow_vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = shadow_vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = shadow_fragment_shader_main;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = shadow_vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = shadow_vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = shadow_fragment_shader_main;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = shadow_vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = shadow_vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = shadow_fragment_shader_main;
-  }
-
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = shadow_vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = shadow_fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
                                   2,fragment_shader_source,
                                   &hf->shadow_program))
   {
@@ -3311,6 +3237,10 @@ static void init_glsl(ModeInfo *mi)
   hf->norm = calloc(3*MAX_CIRCLE_PNT*hf->num_tube,sizeof(*hf->norm));
   hf->tri = calloc(2*3*MAX_CIRCLE_PNT*hf->num_tube,sizeof(*hf->tri));
 
+  hf->use_vao = glsl_IsCoreProfile();
+  if (hf->use_vao)
+    glGenVertexArrays(1,&hf->vertex_array_object);
+
   hf->use_shaders = True;
 }
 
@@ -3628,6 +3558,8 @@ ENTRYPOINT void free_hopffibration(ModeInfo *mi)
     glDeleteBuffers(hf->max_base_points,hf->fiber_normal_buffer);
     glDeleteBuffers(hf->max_base_points,hf->fiber_indices_buffer);
     glDeleteTextures(1,&hf->shadow_dummy_tex);
+    if (hf->use_vao)
+      glDeleteVertexArrays(1,&hf->vertex_array_object);
     delete_msaa_fbo(mi);
     delete_shadow_fbo(mi);
     free(hf->fiber_pos_buffer);
index a4faa34de7de4a5488fdd2aacfd2d0d6dbc8eccc..5e90228d375dac1631b4cac2f13c168bbc59f346 100644 (file)
@@ -4,7 +4,7 @@
 static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
 #endif
 
-/* Copyright (c) 2003-2021 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2003-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -31,6 +31,7 @@ static const char sccsid[] = "@(#)hypertorus.c  1.2 05/09/28 xlockmore";
  * C. Steger - 20/11/19: Remove all unnecessary global variables
  * C. Steger - 20/12/06: Moved all GLSL support code into glsl-utils.[hc]
  * C. Steger - 20/12/30: Make the shader code work under iOS
+ * C. Steger - 25/12/31: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -243,7 +244,7 @@ typedef struct {
   GLfloat uv[(NUMU+1)*(NUMV+1)][2];
   GLfloat col[(NUMU+1)*(NUMV+1)][4];
   GLuint indices[4*NUMU*NUMV];
-  Bool use_shaders, buffers_initialized;
+  Bool use_shaders, buffers_initialized, use_vao;
   GLuint shader_program;
   GLint vertex_uv_index, color_index;
   GLint mat_rot_index, mat_p_index, bool_persp_index;
@@ -256,6 +257,7 @@ typedef struct {
   GLint specular_index, shininess_index;
   GLuint vertex_uv_buffer;
   GLuint color_buffer, indices_buffer;
+  GLuint vertex_array_object;
   GLint ni, ne, nt;
 #endif /* HAVE_GLSL */
 } hypertorusstruct;
@@ -266,146 +268,138 @@ static hypertorusstruct *hyper = (hypertorusstruct *) NULL;
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec2 VertexUV;\n"
-  "attribute vec4 VertexColor;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec2 VertexUV;\n"
-  "in vec4 VertexColor;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  "uniform mat4 MatRot4D;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolPersp;\n"
-  "uniform vec4 Offset4D;\n"
-  "uniform vec4 Offset3D;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec3 p, pu, pv;\n"
-  "  float su = sin(VertexUV.x)\n;"
-  "  float cu = cos(VertexUV.x)\n;"
-  "  float sv = sin(VertexUV.y)\n;"
-  "  float cv = cos(VertexUV.y)\n;"
-  "  vec4 xx = vec4(cu,su,cv,sv);"
-  "  vec4 xxu = vec4(-su,cu,0.0,0.0);"
-  "  vec4 xxv = vec4(0.0,0.0,-sv,cv);"
-  "  vec4 x = MatRot4D*xx+Offset4D;\n"
-  "  vec4 xu = MatRot4D*xxu;\n"
-  "  vec4 xv = MatRot4D*xxv;\n"
-  "  if (BoolPersp)\n"
-  "  {\n"
-  "    vec3 r = x.xyz;\n"
-  "    float s = x.w;\n"
-  "    float t = s*s;\n"
-  "    p = r/s+Offset3D.xyz;\n"
-  "    pu = (s*xu.xyz-r*xu.w)/t;\n"
-  "    pv = (s*xv.xyz-r*xv.w)/t;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    p = x.xyz/1.5f+Offset3D.xyz;\n"
-  "    pu = xu.xyz;\n"
-  "    pv = xv.xyz;\n"
-  "  }\n"
-  "  vec4 Position = vec4(p,1.0);\n"
-  "  Normal = normalize(cross(pu,pv));\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  Color = VertexColor;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  "uniform bool DrawLines;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 color;\n"
-  "  if (DrawLines)\n"
-  "  {\n"
-  "    color = Color;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 normalDirection;\n"
-  "    vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "    vec4 ambientLighting, diffuseReflection, specularReflection;\n"
-  "    float ndotl, ndoth, pf;\n"
-  "    \n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatFrontAmbient;\n"
-  "      diffuseColor = Color*MatFrontDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = Color*MatBackAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatBackAmbient;\n"
-  "      diffuseColor = Color*MatBackDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0)\n"
-  "      pf = 0.0;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = (sceneColor+ambientLighting+diffuseReflection+\n"
-  "             specularReflection);\n"
-  "  }\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "  gl_FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "  FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec2 VertexUV;                                                 \n\
+attribute vec4 VertexColor;                                              \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+#else                                                                    \n\
+in vec2 VertexUV;                                                        \n\
+in vec4 VertexColor;                                                     \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatRot4D;                                                   \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolPersp;                                                  \n\
+uniform vec4 Offset4D;                                                   \n\
+uniform vec4 Offset3D;                                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec3 p, pu, pv;                                                        \n\
+  float su = sin(VertexUV.x);                                            \n\
+  float cu = cos(VertexUV.x);                                            \n\
+  float sv = sin(VertexUV.y);                                            \n\
+  float cv = cos(VertexUV.y);                                            \n\
+  vec4 xx = vec4(cu,su,cv,sv);                                           \n\
+  vec4 xxu = vec4(-su,cu,0.0,0.0);                                       \n\
+  vec4 xxv = vec4(0.0,0.0,-sv,cv);                                       \n\
+  vec4 x = MatRot4D*xx+Offset4D;                                         \n\
+  vec4 xu = MatRot4D*xxu;                                                \n\
+  vec4 xv = MatRot4D*xxv;                                                \n\
+  if (BoolPersp)                                                         \n\
+  {                                                                      \n\
+    vec3 r = x.xyz;                                                      \n\
+    float s = x.w;                                                       \n\
+    float t = s*s;                                                       \n\
+    p = r/s+Offset3D.xyz;                                                \n\
+    pu = (s*xu.xyz-r*xu.w)/t;                                            \n\
+    pv = (s*xv.xyz-r*xv.w)/t;                                            \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    p = x.xyz/1.5f+Offset3D.xyz;                                         \n\
+    pu = xu.xyz;                                                         \n\
+    pv = xv.xyz;                                                         \n\
+  }                                                                      \n\
+  vec4 Position = vec4(p,1.0);                                           \n\
+  Normal = normalize(cross(pu,pv));                                      \n\
+  gl_Position = MatProj*Position;                                        \n\
+  Color = VertexColor;                                                   \n\
+}                                                                        \n";
+
+/* The fragment shader code. */
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform bool DrawLines;                                                  \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 color;                                                            \n\
+  if (DrawLines)                                                         \n\
+  {                                                                      \n\
+    color = Color;                                                       \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    vec3 normalDirection;                                                \n\
+    vec4 ambientColor, diffuseColor, sceneColor;                         \n\
+    vec4 ambientLighting, diffuseReflection, specularReflection;         \n\
+    float ndotl, ndoth, pf;                                              \n\
+                                                                         \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;                  \n\
+      ambientColor = Color*MatFrontAmbient;                              \n\
+      diffuseColor = Color*MatFrontDiffuse;                              \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = Color*MatBackAmbient*LtGlblAmbient;                   \n\
+      ambientColor = Color*MatBackAmbient;                               \n\
+      diffuseColor = Color*MatBackDiffuse;                               \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0,dot(normalDirection,LtDirection));                   \n\
+    ndoth = max(0.0,dot(normalDirection,LtHalfVector));                  \n\
+    if (ndotl == 0.0)                                                    \n\
+      pf = 0.0;                                                          \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = (sceneColor+ambientLighting+diffuseReflection+               \n\
+             specularReflection);                                        \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0,1.0);                                   \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0,1.0);                                      \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -1417,6 +1411,9 @@ static int hypertorus_pf(ModeInfo *mi, double umin, double umax, double vmin,
     }
   }
 
+  if (hp->use_vao)
+    glBindVertexArray(hp->vertex_array_object);
+
   glEnableVertexAttribArray(hp->vertex_uv_index);
   glBindBuffer(GL_ARRAY_BUFFER,hp->vertex_uv_buffer);
   glVertexAttribPointer(hp->vertex_uv_index,2,GL_FLOAT,GL_FALSE,0,0);
@@ -1471,6 +1468,9 @@ static int hypertorus_pf(ModeInfo *mi, double umin, double umax, double vmin,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (hp->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   polys = 2*numu*numv;
@@ -1485,8 +1485,8 @@ static void init_glsl(ModeInfo *mi)
   hypertorusstruct *hp = &hyper[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   /* Determine whether to use shaders to render the hypertorus. */
   hp->use_shaders = False;
@@ -1495,54 +1495,18 @@ static void init_glsl(ModeInfo *mi)
   hp->ni = 0;
   hp->ne = 0;
   hp->nt = 0;
+  hp->use_vao = False;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &hp->shader_program))
     return;
   hp->vertex_uv_index = glGetAttribLocation(hp->shader_program,"VertexUV");
@@ -1606,6 +1570,10 @@ static void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&hp->color_buffer);
   glGenBuffers(1,&hp->indices_buffer);
 
+  hp->use_vao = glsl_IsCoreProfile();
+  if (hp->use_vao)
+    glGenVertexArrays(1,&hp->vertex_array_object);
+
   hp->use_shaders = True;
 }
 
@@ -1970,6 +1938,8 @@ ENTRYPOINT void free_hypertorus(ModeInfo *mi)
     glDeleteBuffers(1,&hp->vertex_uv_buffer);
     glDeleteBuffers(1,&hp->color_buffer);
     glDeleteBuffers(1,&hp->indices_buffer);
+    if (hp->use_vao)
+      glDeleteVertexArrays(1,&hp->vertex_array_object);
     if (hp->shader_program != 0)
     {
       glUseProgram(0);
index 9a051e1fce7a5838044d3624f1da963d6d834d68..7cf2395e00da36144c08ab8280e0ceda20189587 100644 (file)
@@ -5,7 +5,7 @@
 static const char sccsid[] = "@(#)klein.c  1.1 04/10/08 xlockmore";
 #endif
 
-/* Copyright (c) 2005-2021 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2005-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -28,6 +28,7 @@ static const char sccsid[] = "@(#)klein.c  1.1 04/10/08 xlockmore";
  * C. Steger - 20/01/11: Added the changing colors mode
  * C. Steger - 20/12/12: Added per-fragment shading
  * C. Steger - 20/12/30: Make the shader code work under macOS and iOS
+ * C. Steger - 26/01/01: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -348,7 +349,7 @@ typedef struct {
 #ifdef HAVE_GLSL
   GLfloat uv[(NUMU+1)*(NUMV+1)][2];
   GLuint indices[4*(NUMU+1)*(NUMV+1)];
-  Bool use_shaders, buffers_initialized;
+  Bool use_shaders, buffers_initialized, use_vao;
   GLuint shader_program;
   GLint vertex_uv_index, vertex_t_index, color_index;
   GLint mat_rot_index, mat_p_index, bool_persp_index;
@@ -363,6 +364,7 @@ typedef struct {
   GLint texture_sampler_index;
   GLuint vertex_uv_buffer, vertex_t_buffer;
   GLuint color_buffer, indices_buffer;
+  GLuint vertex_array_object;
   GLint ni, ne, nt;
 #endif /* HAVE_GLSL */
 } kleinstruct;
@@ -375,238 +377,232 @@ static kleinstruct *klein = (kleinstruct *) NULL;
 #define STRH(x) #x
 #define STR(x) STRH(x)
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec2 VertexUV;\n"
-  "attribute vec4 VertexT;\n"
-  "attribute vec4 VertexColor;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec2 VertexUV;\n"
-  "in vec4 VertexT;\n"
-  "in vec4 VertexColor;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "out vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  "#define KLEIN_BOTTLE_FIGURE_8      "STR(KLEIN_BOTTLE_FIGURE_8)"\n"
-  "#define KLEIN_BOTTLE_PINCHED_TORUS "STR(KLEIN_BOTTLE_PINCHED_TORUS)"\n"
-  "#define KLEIN_BOTTLE_LAWSON        "STR(KLEIN_BOTTLE_LAWSON)"\n"
-  "#define FIGURE_8_RADIUS            "STR(FIGURE_8_RADIUS)"f\n"
-  "#define PINCHED_TORUS_RADIUS       "STR(PINCHED_TORUS_RADIUS)"f\n"
-  "#define RADIUS_INCR                "STR(RADIUS_INCR)"f\n"
-  "\n"
-  "uniform mat4 MatRot4D;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolPersp;\n"
-  "uniform vec4 Offset4D;\n"
-  "uniform vec4 Offset3D;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform int BottleType;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  float u, v;\n"
-  "  vec4 x, xu, xv, xx, xxu, xxv;\n"
-  "  vec3 p, pu, pv;\n"
-  "  u = VertexUV.x;\n"
-  "  v = VertexUV.y;\n"
-  "  if (BottleType == KLEIN_BOTTLE_FIGURE_8)\n"
-  "  {\n"
-  "    float su, cu, sv, cv, s2u, c2u, sv2, cv2;\n"
-  "    cu = cos(u);\n"
-  "    su = sin(u);\n"
-  "    cv = cos(v);\n"
-  "    sv = sin(v);\n"
-  "    cv2 = cos(0.5f*v);\n"
-  "    sv2 = sin(0.5f*v);\n"
-  "    c2u = cos(2.0f*u);\n"
-  "    s2u = sin(2.0f*u);\n"
-  "    xx = vec4((su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv,\n"
-  "              (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv,\n"
-  "               su*sv2+s2u*cv2,\n"
-  "               cu)/(FIGURE_8_RADIUS+RADIUS_INCR);\n"
-  "    xxu = vec4((cu*cv2-2.0f*c2u*sv2)*cv,\n"
-  "               (cu*cv2-2.0f*c2u*sv2)*sv,\n"
-  "               cu*sv2+2.0f*c2u*cv2,\n"
-  "               -su)/(FIGURE_8_RADIUS+RADIUS_INCR);\n"
-  "    xxv = vec4(((-0.5f*su*sv2-0.5f*s2u*cv2)*cv-\n"
-  "                (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv),\n"
-  "               ((-0.5f*su*sv2-0.5f*s2u*cv2)*sv+\n"
-  "                (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv),\n"
-  "               0.5f*su*cv2-0.5f*s2u*sv2,\n"
-  "               0.0f)/(FIGURE_8_RADIUS+RADIUS_INCR);\n"
-  "  }\n"
-  "  else if (BottleType == KLEIN_BOTTLE_PINCHED_TORUS)\n"
-  "  {\n"
-  "    float cu, su, cv, sv, cv2, sv2;\n"
-  "    cu = cos(u);\n"
-  "    su = sin(u);\n"
-  "    cv = cos(v);\n"
-  "    sv = sin(v);\n"
-  "    cv2 = cos(0.5f*v);\n"
-  "    sv2 = sin(0.5f*v);\n"
-  "    xx = vec4((PINCHED_TORUS_RADIUS+cu)*cv,\n"
-  "              (PINCHED_TORUS_RADIUS+cu)*sv,\n"
-  "              su*cv2,\n"
-  "              su*sv2)/(PINCHED_TORUS_RADIUS+RADIUS_INCR)\n;"
-  "    xxu = vec4(-su*cv,\n"
-  "               -su*sv,\n"
-  "               cu*cv2,\n"
-  "               cu*sv2)/(PINCHED_TORUS_RADIUS+RADIUS_INCR)\n;"
-  "    xxv = vec4(-(PINCHED_TORUS_RADIUS+cu)*sv,\n"
-  "               (PINCHED_TORUS_RADIUS+cu)*cv,\n"
-  "               -0.5f*su*sv2,\n"
-  "               0.5f*su*cv2)/(PINCHED_TORUS_RADIUS+RADIUS_INCR)\n;"
-  "  }\n"
-  "  else // BottleType == KLEIN_BOTTLE_LAWSON\n"
-  "  {\n"
-  "    float cu, su, cv, sv, cv2, sv2;\n"
-  "    cu = cos(u);\n"
-  "    su = sin(u);\n"
-  "    cv = cos(v);\n"
-  "    sv = sin(v);\n"
-  "    cv2 = cos(0.5f*v);\n"
-  "    sv2 = sin(0.5f*v);\n"
-  "    xx = vec4(cu*cv,\n"
-  "              cu*sv,\n"
-  "              su*sv2,\n"
-  "              su*cv2)\n;"
-  "    xxu = vec4(-su*cv,\n"
-  "               -su*sv,\n"
-  "               cu*sv2,\n"
-  "               cu*cv2)\n;"
-  "    xxv = vec4(-cu*sv,\n"
-  "               cu*cv,\n"
-  "               0.5f*su*cv2,\n"
-  "               -0.5f*su*sv2)\n;"
-  "  }\n"
-  "  x = MatRot4D*xx+Offset4D;\n"
-  "  xu = MatRot4D*xxu;\n"
-  "  xv = MatRot4D*xxv;\n"
-  "  if (BoolPersp)\n"
-  "  {\n"
-  "    vec3 r = x.xyz;\n"
-  "    float s = x.w;\n"
-  "    float t = s*s;\n"
-  "    p = r/s+Offset3D.xyz;\n"
-  "    pu = (s*xu.xyz-r*xu.w)/t;\n"
-  "    pv = (s*xv.xyz-r*xv.w)/t;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    p = x.xyz+Offset3D.xyz;\n"
-  "    pu = xu.xyz;\n"
-  "    pv = xv.xyz;\n"
-  "  }\n"
-  "  vec4 Position = vec4(p,1.0);\n"
-  "  Normal = normalize(cross(pu,pv));\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  Color = VertexColor;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexT;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "in vec4 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  "uniform bool DrawLines;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSampler;"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 color;\n"
-  "  if (DrawLines)\n"
-  "  {\n"
-  "    color = Color;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 normalDirection;\n"
-  "    vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "    vec4 ambientLighting, diffuseReflection, specularReflection;\n"
-  "    float ndotl, ndoth, pf;\n"
-  "    \n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatFrontAmbient;\n"
-  "      diffuseColor = Color*MatFrontDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = Color*MatBackAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatBackAmbient;\n"
-  "      diffuseColor = Color*MatBackDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0)\n"
-  "      pf = 0.0;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "    if (BoolTextures)\n"
-  "      color *= texture2D(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  gl_FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "    if (BoolTextures)\n"
-  "      color *= texture(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec2 VertexUV;                                                 \n\
+attribute vec4 VertexT;                                                  \n\
+attribute vec4 VertexColor;                                              \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec2 VertexUV;                                                        \n\
+in vec4 VertexT;                                                         \n\
+in vec4 VertexColor;                                                     \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+out vec4 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+#define KLEIN_BOTTLE_FIGURE_8      "STR(KLEIN_BOTTLE_FIGURE_8)"          \n\
+#define KLEIN_BOTTLE_PINCHED_TORUS "STR(KLEIN_BOTTLE_PINCHED_TORUS)"     \n\
+#define KLEIN_BOTTLE_LAWSON        "STR(KLEIN_BOTTLE_LAWSON)"            \n\
+#define FIGURE_8_RADIUS            "STR(FIGURE_8_RADIUS)"f               \n\
+#define PINCHED_TORUS_RADIUS       "STR(PINCHED_TORUS_RADIUS)"f          \n\
+#define RADIUS_INCR                "STR(RADIUS_INCR)"f                   \n\
+                                                                         \n\
+uniform mat4 MatRot4D;                                                   \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolPersp;                                                  \n\
+uniform vec4 Offset4D;                                                   \n\
+uniform vec4 Offset3D;                                                   \n\
+uniform bool BoolTextures;                                               \n\
+uniform int BottleType;                                                  \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  float u, v;                                                            \n\
+  vec4 x, xu, xv, xx, xxu, xxv;                                          \n\
+  vec3 p, pu, pv;                                                        \n\
+  u = VertexUV.x;                                                        \n\
+  v = VertexUV.y;                                                        \n\
+  if (BottleType == KLEIN_BOTTLE_FIGURE_8)                               \n\
+  {                                                                      \n\
+    float su, cu, sv, cv, s2u, c2u, sv2, cv2;                            \n\
+    cu = cos(u);                                                         \n\
+    su = sin(u);                                                         \n\
+    cv = cos(v);                                                         \n\
+    sv = sin(v);                                                         \n\
+    cv2 = cos(0.5f*v);                                                   \n\
+    sv2 = sin(0.5f*v);                                                   \n\
+    c2u = cos(2.0f*u);                                                   \n\
+    s2u = sin(2.0f*u);                                                   \n\
+    xx = vec4((su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv,                       \n\
+              (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv,                       \n\
+              su*sv2+s2u*cv2,                                            \n\
+              cu)/(FIGURE_8_RADIUS+RADIUS_INCR);                         \n\
+    xxu = vec4((cu*cv2-2.0f*c2u*sv2)*cv,                                 \n\
+               (cu*cv2-2.0f*c2u*sv2)*sv,                                 \n\
+               cu*sv2+2.0f*c2u*cv2,                                      \n\
+               -su)/(FIGURE_8_RADIUS+RADIUS_INCR);                       \n\
+    xxv = vec4(((-0.5f*su*sv2-0.5f*s2u*cv2)*cv-                          \n\
+                (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*sv),                    \n\
+               ((-0.5f*su*sv2-0.5f*s2u*cv2)*sv+                          \n\
+                (su*cv2-s2u*sv2+FIGURE_8_RADIUS)*cv),                    \n\
+               0.5f*su*cv2-0.5f*s2u*sv2,                                 \n\
+               0.0f)/(FIGURE_8_RADIUS+RADIUS_INCR);                      \n\
+  }                                                                      \n\
+  else if (BottleType == KLEIN_BOTTLE_PINCHED_TORUS)                     \n\
+  {                                                                      \n\
+    float cu, su, cv, sv, cv2, sv2;                                      \n\
+    cu = cos(u);                                                         \n\
+    su = sin(u);                                                         \n\
+    cv = cos(v);                                                         \n\
+    sv = sin(v);                                                         \n\
+    cv2 = cos(0.5f*v);                                                   \n\
+    sv2 = sin(0.5f*v);                                                   \n\
+    xx = vec4((PINCHED_TORUS_RADIUS+cu)*cv,                              \n\
+              (PINCHED_TORUS_RADIUS+cu)*sv,                              \n\
+              su*cv2,                                                    \n\
+              su*sv2)/(PINCHED_TORUS_RADIUS+RADIUS_INCR);                \n\
+    xxu = vec4(-su*cv,                                                   \n\
+               -su*sv,                                                   \n\
+               cu*cv2,                                                   \n\
+               cu*sv2)/(PINCHED_TORUS_RADIUS+RADIUS_INCR);               \n\
+    xxv = vec4(-(PINCHED_TORUS_RADIUS+cu)*sv,                            \n\
+               (PINCHED_TORUS_RADIUS+cu)*cv,                             \n\
+                -0.5f*su*sv2,                                            \n\
+                0.5f*su*cv2)/(PINCHED_TORUS_RADIUS+RADIUS_INCR);         \n\
+  }                                                                      \n\
+  else // BottleType == KLEIN_BOTTLE_LAWSON                              \n\
+  {                                                                      \n\
+    float cu, su, cv, sv, cv2, sv2;                                      \n\
+    cu = cos(u);                                                         \n\
+    su = sin(u);                                                         \n\
+    cv = cos(v);                                                         \n\
+    sv = sin(v);                                                         \n\
+    cv2 = cos(0.5f*v);                                                   \n\
+    sv2 = sin(0.5f*v);                                                   \n\
+    xx = vec4(cu*cv,                                                     \n\
+              cu*sv,                                                     \n\
+              su*sv2,                                                    \n\
+              su*cv2);                                                   \n\
+    xxu = vec4(-su*cv,                                                   \n\
+               -su*sv,                                                   \n\
+               cu*sv2,                                                   \n\
+               cu*cv2);                                                  \n\
+    xxv = vec4(-cu*sv,                                                   \n\
+               cu*cv,                                                    \n\
+               0.5f*su*cv2,                                              \n\
+               -0.5f*su*sv2);                                            \n\
+  }                                                                      \n\
+  x = MatRot4D*xx+Offset4D;                                              \n\
+  xu = MatRot4D*xxu;                                                     \n\
+  xv = MatRot4D*xxv;                                                     \n\
+  if (BoolPersp)                                                         \n\
+  {                                                                      \n\
+    vec3 r = x.xyz;                                                      \n\
+    float s = x.w;                                                       \n\
+    float t = s*s;                                                       \n\
+    p = r/s+Offset3D.xyz;                                                \n\
+    pu = (s*xu.xyz-r*xu.w)/t;                                            \n\
+    pv = (s*xv.xyz-r*xv.w)/t;                                            \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    p = x.xyz+Offset3D.xyz;                                              \n\
+    pu = xu.xyz;                                                         \n\
+    pv = xv.xyz;                                                         \n\
+  }                                                                      \n\
+  vec4 Position = vec4(p,1.0);                                           \n\
+  Normal = normalize(cross(pu,pv));                                      \n\
+  gl_Position = MatProj*Position;                                        \n\
+  Color = VertexColor;                                                   \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexT;                                                  \n\
+}                                                                        \n";
+
+/* The fragment shader code. */
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+in vec4 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform bool DrawLines;                                                  \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSampler;                                        \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 color;                                                            \n\
+  if (DrawLines)                                                         \n\
+  {                                                                      \n\
+    color = Color;                                                       \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    vec3 normalDirection;                                                \n\
+    vec4 ambientColor, diffuseColor, sceneColor;                         \n\
+    vec4 ambientLighting, diffuseReflection, specularReflection;         \n\
+    float ndotl, ndoth, pf;                                              \n\
+                                                                         \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;                  \n\
+      ambientColor = Color*MatFrontAmbient;                              \n\
+      diffuseColor = Color*MatFrontDiffuse;                              \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = Color*MatBackAmbient*LtGlblAmbient;                   \n\
+      ambientColor = Color*MatBackAmbient;                               \n\
+      diffuseColor = Color*MatBackDiffuse;                               \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0,dot(normalDirection,LtDirection));                   \n\
+    ndoth = max(0.0,dot(normalDirection,LtHalfVector));                  \n\
+    if (ndotl == 0.0)                                                    \n\
+      pf = 0.0;                                                          \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = sceneColor+ambientLighting+diffuseReflection;                \n\
+    if (BoolTextures)                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSampler,TexCoord.st).rrra;               \n\
+#else                                                                    \n\
+      color *= texture(TextureSampler,TexCoord.st).rrra;                 \n\
+#endif                                                                   \n\
+    color += specularReflection;                                         \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0,1.0);                                   \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0,1.0);                                      \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -1519,6 +1515,7 @@ static void set_opengl_state_ff(ModeInfo *mi, float matc[3][3])
   if (marks)
   {
     glEnable(GL_TEXTURE_2D);
+    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 #ifndef HAVE_JWZGLES
     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
 #endif
@@ -2088,6 +2085,9 @@ static int figure8_pf(ModeInfo *mi, double umin, double umax, double vmin,
 
   glUseProgram(kb->shader_program);
 
+  if (kb->use_vao)
+    glBindVertexArray(kb->vertex_array_object);
+
   set_opengl_state_pf(mi,mat,matc);
 
   glEnableVertexAttribArray(kb->vertex_uv_index);
@@ -2135,6 +2135,9 @@ static int figure8_pf(ModeInfo *mi, double umin, double umax, double vmin,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (kb->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   polys = 2*NUMU*NUMV;
@@ -2439,6 +2442,9 @@ static int pinched_torus_pf(ModeInfo *mi, double umin, double umax,
 
   glUseProgram(kb->shader_program);
 
+  if (kb->use_vao)
+    glBindVertexArray(kb->vertex_array_object);
+
   set_opengl_state_pf(mi,mat,matc);
 
   glEnableVertexAttribArray(kb->vertex_uv_index);
@@ -2486,6 +2492,9 @@ static int pinched_torus_pf(ModeInfo *mi, double umin, double umax,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (kb->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   polys = 2*NUMU*NUMV;
@@ -2793,6 +2802,9 @@ static int lawson_pf(ModeInfo *mi, double umin, double umax, double vmin,
 
   glUseProgram(kb->shader_program);
 
+  if (kb->use_vao)
+    glBindVertexArray(kb->vertex_array_object);
+
   set_opengl_state_pf(mi,mat,matc);
 
   glEnableVertexAttribArray(kb->vertex_uv_index);
@@ -2840,6 +2852,9 @@ static int lawson_pf(ModeInfo *mi, double umin, double umax, double vmin,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (kb->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   polys = 2*NUMU*NUMV;
@@ -2863,9 +2878,14 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
-               GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
+#ifdef HAVE_GLSL
+  if (kb->use_shaders)
+    glTexImage2D(GL_TEXTURE_2D,0,GL_R8,TEX_DIMENSION,TEX_DIMENSION,0,
+                  GL_RED,GL_UNSIGNED_BYTE,texture);
+  else
+#endif /* HAVE_GLSL */
+    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
 
@@ -2876,8 +2896,8 @@ static void init_glsl(ModeInfo *mi)
   kleinstruct *kb = &klein[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   /* Determine whether to use shaders to render the Klein bottle. */
   kb->use_shaders = False;
@@ -2886,54 +2906,18 @@ static void init_glsl(ModeInfo *mi)
   kb->ni = 0;
   kb->ne = 0;
   kb->nt = 0;
+  kb->use_vao = False;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &kb->shader_program))
     return;
   kb->vertex_uv_index = glGetAttribLocation(kb->shader_program,"VertexUV");
@@ -3008,6 +2992,10 @@ static void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&kb->color_buffer);
   glGenBuffers(1,&kb->indices_buffer);
 
+  kb->use_vao = glsl_IsCoreProfile();
+  if (kb->use_vao)
+    glGenVertexArrays(1,&kb->vertex_array_object);
+
   kb->use_shaders = True;
 }
 
@@ -3094,6 +3082,10 @@ static void init(ModeInfo *mi)
     kb->offset3d[3] = 0.0;
   }
 
+#ifdef HAVE_GLSL
+  init_glsl(mi);
+#endif /* HAVE_GLSL */
+
   gen_texture(mi);
   if (kb->bottle_type == KLEIN_BOTTLE_FIGURE_8)
     setup_figure8(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
@@ -3102,10 +3094,6 @@ static void init(ModeInfo *mi)
   else /* kb->bottle_type == KLEIN_BOTTLE_LAWSON */
     setup_lawson(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
 
-#ifdef HAVE_GLSL
-  init_glsl(mi);
-#endif /* HAVE_GLSL */
-
 #ifdef HAVE_ANDROID
   /* glPolygonMode(...,GL_LINE) is not supported for an OpenGL ES 1.1
      context. */
@@ -3568,6 +3556,8 @@ ENTRYPOINT void free_klein(ModeInfo *mi)
     glDeleteBuffers(1,&kb->vertex_t_buffer);
     glDeleteBuffers(1,&kb->color_buffer);
     glDeleteBuffers(1,&kb->indices_buffer);
+    if (kb->use_vao)
+      glDeleteVertexArrays(1,&kb->vertex_array_object);
     if (kb->shader_program != 0)
     {
       glUseProgram(0);
diff --git a/hacks/glx/logarithmiccircles.man b/hacks/glx/logarithmiccircles.man
new file mode 100644 (file)
index 0000000..ac63227
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+logarithmiccircles \- screen saver.
+.SH SYNOPSIS
+.B logarithmiccircles
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Zooming black and white circles. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/mljcWR
+.SH COPYRIGHT
+Copyright \(co 2023 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
index 4f417c3991132b0dac4cde24743ac796314e4f4c..07cbcbb314daebb36bedefcd130cd9ca7719962e 100755 (executable)
@@ -1,12 +1,12 @@
 #!/bin/sh
 
-TARGET=$1
+TARGET="$1"
 shift
 SRCS=$*
 
-TMP=molecules.h.$$
-rm -f $TMP
-trap "rm -f $TMP" 1 2 3 15 EXIT
+TMP="molecules.h.$$"
+rm -f "$TMP"
+trap 'rm -f $TMP' 1 2 3 15 EXIT
 
 if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../../utils"; fi
 
@@ -16,8 +16,8 @@ for f in $SRCS ; do
   echo ',' >> $TMP
 done
 
-if cmp -s $TMP $TARGET ; then
-  rm $TMP
+if cmp -s "$TMP" "$TARGET" ; then
+  rm "$TMP"
 else
-  mv $TMP $TARGET
+  mv "$TMP" "$TARGET"
 fi
diff --git a/hacks/glx/neongravity.man b/hacks/glx/neongravity.man
new file mode 100644 (file)
index 0000000..8be215a
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+neongravity \- screen saver.
+.SH SYNOPSIS
+.B neongravity
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+The stylish interior of a torus. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/43G3Wc
+.SH COPYRIGHT
+Copyright \(co 2023 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
diff --git a/hacks/glx/neontriangulator.man b/hacks/glx/neontriangulator.man
new file mode 100644 (file)
index 0000000..8af6338
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+neontriangulator \- screen saver.
+.SH SYNOPSIS
+.B neontriangulator
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Neon triangles zoom. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/tXGGRD
+.SH COPYRIGHT
+Copyright \(co 2021 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
index 6f5303856ca086dcf61e2a9e8459973215712889..7b7a154b23f7477c98edf2ee9a8c9643cdfd4f49 100644 (file)
@@ -1,5 +1,4 @@
-/* photopile, Copyright © 2008-2018 Jens Kilian <jjk@acm.org>
- * Based on carousel, Copyright © 2005-2008 Jamie Zawinski <jwz@jwz.org>
+/* photopile, Copyright © 2008-2025 Jamie Zawinski <jwz@jwz.org>
  * Loads a sequence of images and shuffles them into a pile.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -38,6 +37,7 @@
 #include "grab-ximage.h"
 #include "texfont.h"
 #include "dropshadow.h"
+#include "xftwrap.h"
 
 #ifdef USE_GL
 
@@ -547,9 +547,9 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z)
         }
       else
         {
-          GLfloat scale = minSize / maxSize;
-          w *= scale;
-          h *= scale;
+          GLfloat s2 = minSize / maxSize;
+          w *= s2;
+          h *= s2;
         }
 
       w1 = minSize * 1.16;      /* enlarge frame border */
@@ -651,74 +651,89 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z)
     {
       int sw = 0, sh = 0;
       int ascent, descent;
-      GLfloat tw = w * 2;
-      GLfloat th = h1 - h;
-      GLfloat scale = 1;
-      const char *title = frame->title ? frame->title : "(untitled)";
+      char *title = frame->title ? frame->title : strdup ("(untitled)");
+      char *token, *line;
+      int lineno = 0;
       XCharStruct e;
+      GLfloat tpad = w * 0.05;
+      GLfloat tboxh = h1 - h - tpad * 2;
+      GLfloat tscale;
+      int nlines = 1;
 
       texture_string_metrics (ss->texfont, title, &e, &ascent, &descent);
       sw = e.width;
-      sh = ascent; /* + descent; */
+      sh = ascent + descent;
 
-      /* Scale the text to match the pixel size of the photo */
-      scale *= w / 150.0;
+      if (!polaroid_p)
+        tboxh = sh * 3;
 
-# if defined(HAVE_COCOA)
-      scale /= 2;
-      if (MI_WIDTH(mi) > 2560) scale /= 2;  /* Retina displays */
-# endif
+      glTranslatef (0, -(h + tpad), 0);
 
-# if defined(HAVE_MOBILE)
-      scale /= 2;
-# endif
+      /* Set the text height to fit 3 lines in the available space. */
+      tscale = tboxh / (sh * 3);
 
-      /* Clip characters off the left end of the string until it fits. */
-      if (clip_p || polaroid_p)
-        while (sw * scale > tw && strlen (title) > 10)
-          {
-            title++;
-            texture_string_metrics (ss->texfont, title, &e, &ascent, &descent);
-            sw = e.width;
-          }
+      if (wire || !polaroid_p)
+        glColor3f (1, 1, 1);
+      else
+        glColor3f (0.5, 0.5, 0.5);
 
-      if (th <= 0)  /* Non-polaroid */
-        th = -sh * 1.2;
+      title = xft_word_wrap (MI_DISPLAY(mi), texfont_xft (ss->texfont),
+                             title, (w * 2) / tscale);
+      token = title;
 
-      glTranslatef (-w, -h1, 0);
-      glTranslatef ((tw - sw*scale) / 2, (th - sh*scale) / 2, 0);
+      glScalef (tscale, tscale, 1);
+      glTranslatef (0, -ascent, 0);
 
-      glScalef (scale, scale, 1);
+      for (line = token; *line; line++)
+        if (*line == '\n') nlines++;
 
-      if (wire || !polaroid_p)
-        {
-          glColor3f (1, 1, 1);
-        }
-      else
-        {
-          glColor3f (0.5, 0.5, 0.5);
-        }
+      if (nlines == 1)
+        glTranslatef (0, -sh, 0);
+      else if (nlines == 2)
+        glTranslatef (0, -sh * 0.5, 0);
 
       if (!wire)
         {
           glEnable (GL_TEXTURE_2D);
           glEnable (GL_BLEND);
           glDisable (GL_DEPTH_TEST);
-# ifndef HAVE_ANDROID   /* Doesn't work -- photo displays as static */
-          print_texture_string (ss->texfont, title);
-# endif
-          glEnable (GL_DEPTH_TEST);
         }
-      else
+
+      /* print_texture_string() does flushleft for newlines,
+         but we want the lines centered. */
+      while ((line = strtok (token, "\n")))
         {
-          glBegin (GL_LINE_LOOP);
-          glVertex3f (0,  0,  0);
-          glVertex3f (sw, 0,  0);
-          glVertex3f (sw, sh, 0);
-          glVertex3f (0,  sh, 0);
-          glEnd();
+          token = 0;
+          texture_string_metrics (ss->texfont, line, &e, 0, 0);
+          sw = e.width;
+
+          glPushMatrix();
+          glTranslatef (-sw/2, -sh * lineno, 0);
+
+          if (!wire)
+            {
+# ifndef HAVE_ANDROID   /* Doesn't work -- photo displays as static */
+              print_texture_string (ss->texfont, line);
+# endif
+            }
+          else
+            {
+              glBegin (GL_LINE_LOOP);
+              glVertex3f (0,  0,  0);
+              glVertex3f (sw, 0,  0);
+              glVertex3f (sw, sh, 0);
+              glVertex3f (0,  sh, 0);
+              glEnd();
+            }
+          glPopMatrix();
+          lineno++;
+
+          if (polaroid_p &&
+              (sh * (lineno + 1) - descent) * tscale > tboxh)
+            break;  /* Ran out of room for lines */
         }
 
+      free (title);
     }
 
   glPopMatrix();
index 2b19cc9fc16eb80efd1d82a11d47ee6a17c5e799..63081cc4b7ec5414231e5e332764adaaa4c1b15f 100644 (file)
@@ -5,7 +5,7 @@
 static const char sccsid[] = "@(#)platonicfolding.c  1.1 25/03/18 xlockmore";
 #endif
 
-/* Copyright (c) 2025 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2025-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -22,6 +22,7 @@ static const char sccsid[] = "@(#)platonicfolding.c  1.1 25/03/18 xlockmore";
  *
  * REVISION HISTORY:
  * C. Steger - 25/03/18: Initial version
+ * C. Steger - 26/01/02: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -630,7 +631,7 @@ typedef struct {
   texcoord tex[NUM_VERTEX];
   int num[NUM_VERTEX];
 #ifdef HAVE_GLSL
-  bool use_shaders, use_mipmaps;
+  bool use_shaders, use_mipmaps, use_vao;
   GLuint shader_program;
   GLint pos_index, normal_index, color_index, tex_index;
   GLint mv_index, proj_index;
@@ -642,6 +643,7 @@ typedef struct {
   GLint bool_textures_index, north_up_index, magma_offs_index;
   GLint samp_mgm_index, samp_day_index, samp_ngt_index, samp_wtr_index;
   GLuint vertex_buffer, normal_buffer, color_buffer, tex_buffer;
+  GLuint vertex_array_object;
   GLuint magma_tex, earth_tex[3];
   GLubyte *magma_tex_rg;
   GLfloat magma_tex_offset[3];
@@ -970,237 +972,202 @@ static inline void get_sun_direction(double jd, float sun[4])
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n"
-  "precision highp sampler2D;\n"
-  "precision highp sampler3D;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec4 VertexPosition;\n"
-  "attribute vec4 VertexNormal;\n"
-  "attribute vec4 VertexColor;\n"
-  "attribute vec3 VertexTexCoord;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec3 EarthTexCoord;\n"
-  "varying vec3 LightTexCoord;\n"
-  "varying vec3 MagmaTexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec4 VertexPosition;\n"
-  "in vec4 VertexNormal;\n"
-  "in vec4 VertexColor;\n"
-  "in vec3 VertexTexCoord;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "out vec3 EarthTexCoord;\n"
-  "out vec3 LightTexCoord;\n"
-  "out vec3 MagmaTexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform vec3 TexOffsetMagma;\n"
-  "uniform bool NorthUp;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  Color = VertexColor;\n"
-  "  Normal = normalize(MatModelView*VertexNormal).xyz;\n"
-  "  vec4 Position = MatModelView*VertexPosition;\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  if (NorthUp)\n"
-  "    EarthTexCoord = VertexTexCoord;\n"
-  "  else\n"
-  "    EarthTexCoord = vec3(-1.0f,1.0f,-1.0f)*VertexTexCoord;\n"
-  "  LightTexCoord = (MatModelView*vec4(VertexTexCoord,0.0f)).xyz;\n"
-  "  MagmaTexCoord = 0.4f*(VertexTexCoord+1.0f)+TexOffsetMagma;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec3 EarthTexCoord;\n"
-  "varying vec3 LightTexCoord;\n"
-  "varying vec3 MagmaTexCoord;\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "in vec3 EarthTexCoord;\n"
-  "in vec3 LightTexCoord;\n"
-  "in vec3 MagmaTexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  "const float I_M_PI_F = 0.318309886184f;\n"
-  "const float I_M_2PI_F = 0.159154943092f;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatAmbient;\n"
-  "uniform vec4 MatDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler3D TextureSamplerMagma;\n"
-  "uniform sampler2D TextureSamplerDay;\n"
-  "uniform sampler2D TextureSamplerNight;\n"
-  "uniform sampler2D TextureSamplerWater;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec3 normalDirection;\n"
-  "  vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "  vec4 ambientLighting, diffuseReflection, specularReflection;\n"
-  "  vec4 color, colord, colorn, specd, specn;\n"
-  "  vec3 normTexCoord, normLightCoord\n;"
-  "  vec2 texCoor;\n"
-  "  float ndotl, ldotls, ndoth, attd, attn, pf, lat, lon;\n"
-  "  \n"
-  "  if (!BoolTextures)\n"
-  "  {\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = Color*MatAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatAmbient;\n"
-  "      diffuseColor = Color*MatDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = Color*MatAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatAmbient;\n"
-  "      diffuseColor = Color*MatDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0f,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0f,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0f)\n"
-  "      pf = 0.0f;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection+\n"
-  "            specularReflection;\n"
-  "    color.a = diffuseColor.a;\n"
-  "  }\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "  else\n"
-  "  {\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color = texture3D(TextureSamplerMagma,MagmaTexCoord);\n"
-  "      sceneColor = color*MatAmbient*LtGlblAmbient;\n"
-  "      ambientColor = color*MatAmbient;\n"
-  "      diffuseColor = color*MatDiffuse;\n"
-  "      specularReflection = vec4(0.0f,0.0f,0.0f,0.0f);\n"
-  "      diffuseReflection = LtDiffuse*diffuseColor;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normTexCoord = normalize(EarthTexCoord);\n"
-  "      normLightCoord = normalize(LightTexCoord);\n"
-  "      lat = asin(normTexCoord.z);\n"
-  "      lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "      texCoor = vec2(0.5f+lon*I_M_2PI_F,0.5f+lat*I_M_PI_F);\n"
-  "      ndotl = max(0.0f,dot(normLightCoord,LtDirection));\n"
-  "      ndoth = max(0.0f,dot(normLightCoord,LtHalfVector));\n"
-  "      if (ndotl == 0.0f)\n"
-  "        pf = 0.0f;\n"
-  "      else\n"
-  "        pf = pow(ndoth,MatShininess);\n"
-  "      specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "      ldotls = dot(normLightCoord,LtDirection);\n"
-  "      colord = texture2D(TextureSamplerDay,texCoor);\n"
-  "      attd = smoothstep(-0.2f,0.2f,ldotls);\n"
-  "      colorn = texture2D(TextureSamplerNight,texCoor);\n"
-  "      attn = smoothstep(-0.2f,0.2f,-ldotls);\n"
-  "      color = attd*colord+attn*colorn;\n"
-  "      specd = texture2D(TextureSamplerWater,texCoor);\n"
-  "      specn = vec4(0.0f,0.0f,0.0f,1.0f);\n"
-  "      specularReflection *= attd*specd+attn*specn;\n"
-  "      sceneColor = color*MatAmbient*LtGlblAmbient;\n"
-  "      ambientColor = color*MatAmbient;\n"
-  "      diffuseColor = color*MatDiffuse;\n"
-  "      diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    }\n"
-  "    \n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection+\n"
-  "            specularReflection;\n"
-  "    color.a = diffuseColor.a;\n"
-  "  }\n"
-  "  gl_FragColor = clamp(color,0.0f,1.0f);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "  else\n"
-  "  {\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color = texture(TextureSamplerMagma,MagmaTexCoord);\n"
-  "      sceneColor = color*MatAmbient*LtGlblAmbient;\n"
-  "      ambientColor = color*MatAmbient;\n"
-  "      diffuseColor = color*MatDiffuse;\n"
-  "      specularReflection = vec4(0.0f,0.0f,0.0f,0.0f);\n"
-  "      diffuseReflection = LtDiffuse*diffuseColor;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normTexCoord = normalize(EarthTexCoord);\n"
-  "      normLightCoord = normalize(LightTexCoord);\n"
-  "      lat = asin(normTexCoord.z);\n"
-  "      lon = atan(normTexCoord.y,normTexCoord.x);\n"
-  "      texCoor = vec2(0.5f+lon*I_M_2PI_F,0.5f+lat*I_M_PI_F);\n"
-  "      ndotl = max(0.0f,dot(normLightCoord,LtDirection));\n"
-  "      ndoth = max(0.0f,dot(normLightCoord,LtHalfVector));\n"
-  "      if (ndotl == 0.0f)\n"
-  "        pf = 0.0f;\n"
-  "      else\n"
-  "        pf = pow(ndoth,MatShininess);\n"
-  "      specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "      ldotls = dot(normLightCoord,LtDirection);\n"
-  "      colord = texture(TextureSamplerDay,texCoor);\n"
-  "      attd = smoothstep(-0.2f,0.2f,ldotls);\n"
-  "      colorn = texture(TextureSamplerNight,texCoor);\n"
-  "      attn = smoothstep(-0.2f,0.2f,-ldotls);\n"
-  "      color = attd*colord+attn*colorn;\n"
-  "      specd = texture(TextureSamplerWater,texCoor);\n"
-  "      specn = vec4(0.0f,0.0f,0.0f,1.0f);\n"
-  "      specularReflection *= attd*specd+attn*specn;\n"
-  "      sceneColor = color*MatAmbient*LtGlblAmbient;\n"
-  "      ambientColor = color*MatAmbient;\n"
-  "      diffuseColor = color*MatDiffuse;\n"
-  "      diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    }\n"
-  "    \n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection+\n"
-  "            specularReflection;\n"
-  "    color.a = diffuseColor.a;\n"
-  "  }\n"
-  "  FragColor = clamp(color,0.0f,1.0f);\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+precision highp sampler3D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec4 VertexPosition;                                           \n\
+attribute vec4 VertexNormal;                                             \n\
+attribute vec4 VertexColor;                                              \n\
+attribute vec3 VertexTexCoord;                                           \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec3 EarthTexCoord;                                              \n\
+varying vec3 LightTexCoord;                                              \n\
+varying vec3 MagmaTexCoord;                                              \n\
+#else                                                                    \n\
+in vec4 VertexPosition;                                                  \n\
+in vec4 VertexNormal;                                                    \n\
+in vec4 VertexColor;                                                     \n\
+in vec3 VertexTexCoord;                                                  \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+out vec3 EarthTexCoord;                                                  \n\
+out vec3 LightTexCoord;                                                  \n\
+out vec3 MagmaTexCoord;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform vec3 TexOffsetMagma;                                             \n\
+uniform bool NorthUp;                                                    \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  Color = VertexColor;                                                   \n\
+  Normal = normalize(MatModelView*VertexNormal).xyz;                     \n\
+  vec4 Position = MatModelView*VertexPosition;                           \n\
+  gl_Position = MatProj*Position;                                        \n\
+  if (NorthUp)                                                           \n\
+    EarthTexCoord = VertexTexCoord;                                      \n\
+  else                                                                   \n\
+    EarthTexCoord = vec3(-1.0f,1.0f,-1.0f)*VertexTexCoord;               \n\
+  LightTexCoord = (MatModelView*vec4(VertexTexCoord,0.0f)).xyz;          \n\
+  MagmaTexCoord = 0.4f*(VertexTexCoord+1.0f)+TexOffsetMagma;             \n\
+}                                                                        \n";
+
+/* The fragment shader code. */
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+precision highp sampler3D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec3 EarthTexCoord;                                              \n\
+varying vec3 LightTexCoord;                                              \n\
+varying vec3 MagmaTexCoord;                                              \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+in vec3 EarthTexCoord;                                                   \n\
+in vec3 LightTexCoord;                                                   \n\
+in vec3 MagmaTexCoord;                                                   \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+const float I_M_PI_F = 0.318309886184f;                                  \n\
+const float I_M_2PI_F = 0.159154943092f;                                 \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatAmbient;                                                 \n\
+uniform vec4 MatDiffuse;                                                 \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler3D TextureSamplerMagma;                                   \n\
+uniform sampler2D TextureSamplerDay;                                     \n\
+uniform sampler2D TextureSamplerNight;                                   \n\
+uniform sampler2D TextureSamplerWater;                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec3 normalDirection;                                                  \n\
+  vec4 ambientColor, diffuseColor, sceneColor;                           \n\
+  vec4 ambientLighting, diffuseReflection, specularReflection;           \n\
+  vec4 color, colord, colorn, specd, specn;                              \n\
+  vec3 normTexCoord, normLightCoord;                                     \n\
+  vec2 texCoor;                                                          \n\
+  float ndotl, ldotls, ndoth, attd, attn, pf, lat, lon;                  \n\
+                                                                         \n\
+  if (!BoolTextures)                                                     \n\
+  {                                                                      \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = Color*MatAmbient*LtGlblAmbient;                       \n\
+      ambientColor = Color*MatAmbient;                                   \n\
+      diffuseColor = Color*MatDiffuse;                                   \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = Color*MatAmbient*LtGlblAmbient;                       \n\
+      ambientColor = Color*MatAmbient;                                   \n\
+      diffuseColor = Color*MatDiffuse;                                   \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0f,dot(normalDirection,LtDirection));                  \n\
+    ndoth = max(0.0f,dot(normalDirection,LtHalfVector));                 \n\
+    if (ndotl == 0.0f)                                                   \n\
+      pf = 0.0f;                                                         \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = sceneColor+ambientLighting+diffuseReflection+                \n\
+            specularReflection;                                          \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color = texture3D(TextureSamplerMagma,MagmaTexCoord);              \n\
+#else                                                                    \n\
+      color = texture(TextureSamplerMagma,MagmaTexCoord);                \n\
+#endif                                                                   \n\
+      sceneColor = color*MatAmbient*LtGlblAmbient;                       \n\
+      ambientColor = color*MatAmbient;                                   \n\
+      diffuseColor = color*MatDiffuse;                                   \n\
+      specularReflection = vec4(0.0f,0.0f,0.0f,0.0f);                    \n\
+      diffuseReflection = LtDiffuse*diffuseColor;                        \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normTexCoord = normalize(EarthTexCoord);                           \n\
+      normLightCoord = normalize(LightTexCoord);                         \n\
+      lat = asin(normTexCoord.z);                                        \n\
+      lon = atan(normTexCoord.y,normTexCoord.x);                         \n\
+      texCoor = vec2(0.5f+lon*I_M_2PI_F,0.5f+lat*I_M_PI_F);              \n\
+      ndotl = max(0.0f,dot(normLightCoord,LtDirection));                 \n\
+      ndoth = max(0.0f,dot(normLightCoord,LtHalfVector));                \n\
+      if (ndotl == 0.0f)                                                 \n\
+        pf = 0.0f;                                                       \n\
+      else                                                               \n\
+        pf = pow(ndoth,MatShininess);                                    \n\
+      specularReflection = LtSpecular*MatSpecular*pf;                    \n\
+      ldotls = dot(normLightCoord,LtDirection);                          \n\
+#if __VERSION__ <= 120                                                   \n\
+      colord = texture2D(TextureSamplerDay,texCoor);                     \n\
+#else                                                                    \n\
+      colord = texture(TextureSamplerDay,texCoor);                       \n\
+#endif                                                                   \n\
+      attd = smoothstep(-0.2f,0.2f,ldotls);                              \n\
+#if __VERSION__ <= 120                                                   \n\
+      colorn = texture2D(TextureSamplerNight,texCoor);                   \n\
+#else                                                                    \n\
+      colorn = texture(TextureSamplerNight,texCoor);                     \n\
+#endif                                                                   \n\
+      attn = smoothstep(-0.2f,0.2f,-ldotls);                             \n\
+      color = attd*colord+attn*colorn;                                   \n\
+#if __VERSION__ <= 120                                                   \n\
+      specd = texture2D(TextureSamplerWater,texCoor);                    \n\
+#else                                                                    \n\
+      specd = texture(TextureSamplerWater,texCoor);                      \n\
+#endif                                                                   \n\
+      specn = vec4(0.0f,0.0f,0.0f,1.0f);                                 \n\
+      specularReflection *= attd*specd+attn*specn;                       \n\
+      sceneColor = color*MatAmbient*LtGlblAmbient;                       \n\
+      ambientColor = color*MatAmbient;                                   \n\
+      diffuseColor = color*MatDiffuse;                                   \n\
+      diffuseReflection = LtDiffuse*diffuseColor*ndotl;                  \n\
+    }                                                                    \n\
+                                                                         \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    color = sceneColor+ambientLighting+diffuseReflection+                \n\
+            specularReflection;                                          \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0f,1.0f);                                 \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0f,1.0f);                                    \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -2478,6 +2445,9 @@ static int polygon_folding_pf(ModeInfo *mi)
   for (i=0; i<num_poly; i++)
     n += pf->num[i];
 
+  if (pf->use_vao)
+    glBindVertexArray(pf->vertex_array_object);
+
   /* Copy the collected polygon data to the respective buffer. */
   glBindBuffer(GL_ARRAY_BUFFER,pf->vertex_buffer);
   glBufferData(GL_ARRAY_BUFFER,4*n*sizeof(GLfloat),pf->vtx,GL_STREAM_DRAW);
@@ -2634,6 +2604,9 @@ static int polygon_folding_pf(ModeInfo *mi)
   glDisableVertexAttribArray(pf->tex_index);
   glBindBuffer(GL_ARRAY_BUFFER,0);
 
+  if (pf->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   return num_poly;
@@ -3031,11 +3004,12 @@ static void init_glsl(ModeInfo *mi)
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
   const char *gl_ext;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   pf->use_textures = false;
   pf->use_mipmaps = false;
+  pf->use_vao = False;
 
   pf->magma_tex_offset[0] = 0.0f;
   pf->magma_tex_offset[1] = 0.0f;
@@ -3050,51 +3024,12 @@ static void init_glsl(ModeInfo *mi)
                                  &gl_gles3))
     return;
 
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &pf->shader_program))
     return;
 
@@ -3220,6 +3155,10 @@ static void init_glsl(ModeInfo *mi)
     gen_earth_textures(mi);
   }
 
+  pf->use_vao = glsl_IsCoreProfile();
+  if (pf->use_vao)
+    glGenVertexArrays(1,&pf->vertex_array_object);
+
   pf->use_shaders = true;
 #if 0
   fprintf(stderr,"Use shaders = %d\n",pf->use_shaders);
@@ -3506,6 +3445,8 @@ ENTRYPOINT void free_platonicfolding(ModeInfo *mi)
     glDeleteBuffers(1,&pf->normal_buffer);
     glDeleteBuffers(1,&pf->color_buffer);
     glDeleteBuffers(1,&pf->tex_buffer);
+    if (pf->use_vao)
+      glDeleteVertexArrays(1,&pf->vertex_array_object);
     if (pf->textures_supported)
     {
       glDeleteTextures(1,&pf->magma_tex);
index a73c0601c0139e1ed6eb75b2a7d3e76224d2dc6e..a16e35cefa3e5afdd5c413f39e1d8fdcf53eed91 100644 (file)
@@ -5,7 +5,7 @@
 static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/03 xlockmore";
 #endif
 
-/* Copyright (c) 2013-2021 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2013-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -27,6 +27,7 @@ static const char sccsid[] = "@(#)projectiveplane.c  1.1 14/01/03 xlockmore";
  * C. Steger - 20/12/05: Added per-fragment shading
  * C. Steger - 20/12/06: Moved all GLSL support code into glsl-utils.[hc]
  * C. Steger - 20/12/30: Make the shader code work under macOS and iOS
+ * C. Steger - 26/01/01: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -414,7 +415,7 @@ typedef struct {
 #ifdef HAVE_GLSL
   GLfloat uv[(NUMU+1)*(NUMV+1)][2];
   GLuint indices[4*(NUMU+1)*(NUMV+1)];
-  Bool use_shaders, buffers_initialized;
+  Bool use_shaders, buffers_initialized, use_vao;
   GLuint shader_program;
   GLint vertex_uv_index, vertex_t_index, color_index;
   GLint mat_rot_index, mat_p_index, bool_persp_index;
@@ -429,6 +430,7 @@ typedef struct {
   GLint texture_sampler_index;
   GLuint vertex_uv_buffer, vertex_t_buffer;
   GLuint color_buffer, indices_buffer;
+  GLuint vertex_array_object;
   GLint ni, ne, nt;
 #endif /* HAVE_GLSL */
 } projectiveplanestruct;
@@ -438,189 +440,181 @@ static projectiveplanestruct *projectiveplane = (projectiveplanestruct *) NULL;
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec2 VertexUV;\n"
-  "attribute vec4 VertexT;\n"
-  "attribute vec4 VertexColor;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec2 VertexUV;\n"
-  "in vec4 VertexT;\n"
-  "in vec4 VertexColor;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "out vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  __extension__
-  "uniform mat4 MatRot4D;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolPersp;\n"
-  "uniform vec4 Offset4D;\n"
-  "uniform vec4 Offset3D;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  const float EPSILON = 1.0e-7f;\n"
-  "  float u, v, su, cu, s2u, c2u, sv2, cv2, sv4, cv4;\n"
-  "  vec3 p, pu, pv;\n"
-  "  u = VertexUV.x;\n"
-  "  v = VertexUV.y;\n"
-  "  su = sin(u)\n;"
-  "  cu = cos(u)\n;"
-  "  s2u = sin(2.0f*u)\n;"
-  "  c2u = cos(2.0f*u)\n;"
-  "  sv2 = sin(0.5f*v)\n;"
-  "  cv2 = cos(0.5f*v)\n;"
-  "  sv4 = sin(0.25f*v)\n;"
-  "  cv4 = cos(0.25f*v)\n;"
-  "  vec4 xx = vec4(0.5f*s2u*sv4*sv4,\n"
-  "                 0.5f*su*sv2,\n"
-  "                 0.5f*cu*sv2,\n"
-  "                 0.5f*(su*su*sv4*sv4-cv4*cv4));\n"
-  "  if (v < EPSILON)\n"
-  "  {\n"
-  "    v = EPSILON;\n"
-  "    sv2 = sin(0.5f*v)\n;"
-  "    cv2 = cos(0.5f*v)\n;"
-  "    sv4 = sin(0.25f*v)\n;"
-  "  }\n"
-  "  vec4 xxu = vec4(c2u*sv4*sv4,\n"
-  "                  0.5f*cu*sv2,\n"
-  "                  -0.5f*su*sv2,\n"
-  "                  0.5f*s2u*sv4*sv4);\n"
-  "  vec4 xxv = vec4(0.125f*s2u*sv2,\n"
-  "                  0.25f*su*cv2,\n"
-  "                  0.25f*cu*cv2,\n"
-  "                  0.125f*(su*su+1.0f)*sv2);\n"
-  "  vec4 x = MatRot4D*xx+Offset4D;\n"
-  "  vec4 xu = MatRot4D*xxu;\n"
-  "  vec4 xv = MatRot4D*xxv;\n"
-  "  if (BoolPersp)\n"
-  "  {\n"
-  "    vec3 r = x.xyz;\n"
-  "    float s = x.w;\n"
-  "    float t = s*s;\n"
-  "    p = r/s+Offset3D.xyz;\n"
-  "    pu = (s*xu.xyz-r*xu.w)/t;\n"
-  "    pv = (s*xv.xyz-r*xv.w)/t;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    p = x.xyz+Offset3D.xyz;\n"
-  "    pu = xu.xyz;\n"
-  "    pv = xv.xyz;\n"
-  "  }\n"
-  "  vec4 Position = vec4(p,1.0);\n"
-  "  Normal = normalize(cross(pu,pv));\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  Color = VertexColor;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexT;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "in vec4 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  __extension__
-  "uniform bool DrawLines;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSampler;"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 color;\n"
-  "  if (DrawLines)\n"
-  "  {\n"
-  "    color = Color;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 normalDirection;\n"
-  "    vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "    vec4 ambientLighting, diffuseReflection, specularReflection;\n"
-  "    float ndotl, ndoth, pf;\n"
-  "    \n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatFrontAmbient;\n"
-  "      diffuseColor = Color*MatFrontDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = Color*MatBackAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatBackAmbient;\n"
-  "      diffuseColor = Color*MatBackDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0)\n"
-  "      pf = 0.0;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "    if (BoolTextures)\n"
-  "      color *= texture2D(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  gl_FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "    if (BoolTextures)\n"
-  "      color *= texture(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec2 VertexUV;                                                 \n\
+attribute vec4 VertexT;                                                  \n\
+attribute vec4 VertexColor;                                              \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec2 VertexUV;                                                        \n\
+in vec4 VertexT;                                                         \n\
+in vec4 VertexColor;                                                     \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+out vec4 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatRot4D;                                                   \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolPersp;                                                  \n\
+uniform vec4 Offset4D;                                                   \n\
+uniform vec4 Offset3D;                                                   \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  const float EPSILON = 1.0e-7f;                                         \n\
+  float u, v, su, cu, s2u, c2u, sv2, cv2, sv4, cv4;                      \n\
+  vec3 p, pu, pv;                                                        \n\
+  u = VertexUV.x;                                                        \n\
+  v = VertexUV.y;                                                        \n\
+  su = sin(u);                                                           \n\
+  cu = cos(u);                                                           \n\
+  s2u = sin(2.0f*u);                                                     \n\
+  c2u = cos(2.0f*u);                                                     \n\
+  sv2 = sin(0.5f*v);                                                     \n\
+  cv2 = cos(0.5f*v);                                                     \n\
+  sv4 = sin(0.25f*v);                                                    \n\
+  cv4 = cos(0.25f*v);                                                    \n\
+  vec4 xx = vec4(0.5f*s2u*sv4*sv4,                                       \n\
+                 0.5f*su*sv2,                                            \n\
+                 0.5f*cu*sv2,                                            \n\
+                 0.5f*(su*su*sv4*sv4-cv4*cv4));                          \n\
+  if (v < EPSILON)                                                       \n\
+  {                                                                      \n\
+    v = EPSILON;                                                         \n\
+    sv2 = sin(0.5f*v);                                                   \n\
+    cv2 = cos(0.5f*v);                                                   \n\
+    sv4 = sin(0.25f*v);                                                  \n\
+  }                                                                      \n\
+  vec4 xxu = vec4(c2u*sv4*sv4,                                           \n\
+                  0.5f*cu*sv2,                                           \n\
+                  -0.5f*su*sv2,                                          \n\
+                  0.5f*s2u*sv4*sv4);                                     \n\
+  vec4 xxv = vec4(0.125f*s2u*sv2,                                        \n\
+                  0.25f*su*cv2,                                          \n\
+                  0.25f*cu*cv2,                                          \n\
+                  0.125f*(su*su+1.0f)*sv2);                              \n\
+  vec4 x = MatRot4D*xx+Offset4D;                                         \n\
+  vec4 xu = MatRot4D*xxu;                                                \n\
+  vec4 xv = MatRot4D*xxv;                                                \n\
+  if (BoolPersp)                                                         \n\
+  {                                                                      \n\
+    vec3 r = x.xyz;                                                      \n\
+    float s = x.w;                                                       \n\
+    float t = s*s;                                                       \n\
+    p = r/s+Offset3D.xyz;                                                \n\
+    pu = (s*xu.xyz-r*xu.w)/t;                                            \n\
+    pv = (s*xv.xyz-r*xv.w)/t;                                            \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    p = x.xyz+Offset3D.xyz;                                              \n\
+    pu = xu.xyz;                                                         \n\
+    pv = xv.xyz;                                                         \n\
+  }                                                                      \n\
+  vec4 Position = vec4(p,1.0);                                           \n\
+  Normal = normalize(cross(pu,pv));                                      \n\
+  gl_Position = MatProj*Position;                                        \n\
+  Color = VertexColor;                                                   \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexT;                                                  \n\
+}                                                                        \n";
+
+/* The fragment shader code. */
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+in vec4 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform bool DrawLines;                                                  \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSampler;                                        \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 color;                                                            \n\
+  if (DrawLines)                                                         \n\
+  {                                                                      \n\
+    color = Color;                                                       \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    vec3 normalDirection;                                                \n\
+    vec4 ambientColor, diffuseColor, sceneColor;                         \n\
+    vec4 ambientLighting, diffuseReflection, specularReflection;         \n\
+    float ndotl, ndoth, pf;                                              \n\
+                                                                         \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;                  \n\
+      ambientColor = Color*MatFrontAmbient;                              \n\
+      diffuseColor = Color*MatFrontDiffuse;                              \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = Color*MatBackAmbient*LtGlblAmbient;                   \n\
+      ambientColor = Color*MatBackAmbient;                               \n\
+      diffuseColor = Color*MatBackDiffuse;                               \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0,dot(normalDirection,LtDirection));                   \n\
+    ndoth = max(0.0,dot(normalDirection,LtHalfVector));                  \n\
+    if (ndotl == 0.0)                                                    \n\
+      pf = 0.0;                                                          \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = sceneColor+ambientLighting+diffuseReflection;                \n\
+    if (BoolTextures)                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSampler,TexCoord.st).rrra;               \n\
+#else                                                                    \n\
+      color *= texture(TextureSampler,TexCoord.st).rrra;                 \n\
+#endif                                                                   \n\
+    color += specularReflection;                                         \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0,1.0);                                   \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0,1.0);                                      \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -1280,6 +1274,7 @@ static int projective_plane_ff(ModeInfo *mi, double umin, double umax,
   if (pp->marks)
   {
     glEnable(GL_TEXTURE_2D);
+    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 #ifndef HAVE_JWZGLES
     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
 #endif
@@ -1936,6 +1931,9 @@ static int projective_plane_pf(ModeInfo *mi, double umin, double umax,
     }
   }
 
+  if (pp->use_vao)
+    glBindVertexArray(pp->vertex_array_object);
+
   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D,pp->tex_name);
   glUniform1i(pp->texture_sampler_index,0);
@@ -1985,6 +1983,9 @@ static int projective_plane_pf(ModeInfo *mi, double umin, double umax,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (pp->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   polys = 2*NUMU*NUMV;
@@ -2008,9 +2009,14 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
-               GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
+#ifdef HAVE_GLSL
+  if (pp->use_shaders)
+    glTexImage2D(GL_TEXTURE_2D,0,GL_R8,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_RED,GL_UNSIGNED_BYTE,texture);
+  else
+#endif /* HAVE_GLSL */
+    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
 
@@ -2021,8 +2027,8 @@ static void init_glsl(ModeInfo *mi)
   projectiveplanestruct *pp = &projectiveplane[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   /* Determine whether to use shaders to render the projective plane. */
   pp->use_shaders = False;
@@ -2031,54 +2037,18 @@ static void init_glsl(ModeInfo *mi)
   pp->ni = 0;
   pp->ne = 0;
   pp->nt = 0;
+  pp->use_vao = False;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &pp->shader_program))
     return;
   pp->vertex_uv_index = glGetAttribLocation(pp->shader_program,"VertexUV");
@@ -2150,6 +2120,10 @@ static void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&pp->color_buffer);
   glGenBuffers(1,&pp->indices_buffer);
 
+  pp->use_vao = glsl_IsCoreProfile();
+  if (pp->use_vao)
+    glGenVertexArrays(1,&pp->vertex_array_object);
+
   pp->use_shaders = True;
 }
 
@@ -2204,13 +2178,13 @@ static void init(ModeInfo *mi)
   pp->offset3d[2] = -1.2;
   pp->offset3d[3] = 0.0;
 
-  gen_texture(mi);
-  setup_projective_plane(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
-
 #ifdef HAVE_GLSL
   init_glsl(mi);
 #endif /* HAVE_GLSL */
 
+  gen_texture(mi);
+  setup_projective_plane(mi,0.0,2.0*M_PI,0.0,2.0*M_PI);
+
 #ifdef HAVE_ANDROID
   /* glPolygonMode(...,GL_LINE) is not supported for an OpenGL ES 1.1
      context. */
@@ -2651,6 +2625,8 @@ ENTRYPOINT void free_projectiveplane(ModeInfo *mi)
     glDeleteBuffers(1,&pp->vertex_t_buffer);
     glDeleteBuffers(1,&pp->color_buffer);
     glDeleteBuffers(1,&pp->indices_buffer);
+    if (pp->use_vao)
+      glDeleteVertexArrays(1,&pp->vertex_array_object);
     if (pp->shader_program != 0)
     {
       glUseProgram(0);
diff --git a/hacks/glx/protophore.man b/hacks/glx/protophore.man
new file mode 100644 (file)
index 0000000..88e8567
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+protophore \- screen saver.
+.SH SYNOPSIS
+.B protophore
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+A reflective metal fractal. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/XljGDz
+.SH COPYRIGHT
+Copyright \(co 2015 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
index 3d2a5c0a80286cfb7569e807d0d58a804661d687..a52c313bf522b06b0b48c0578717adf3018d4f20 100644 (file)
@@ -6,7 +6,7 @@
 static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
 #endif
 
-/* Copyright (c) 2014-2021 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2014-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -26,6 +26,7 @@ static const char sccsid[] = "@(#)romanboy.c  1.1 14/10/03 xlockmore";
  * C. Steger - 20/01/06: Added the changing colors mode
  * C. Steger - 20/12/19: Added per-fragment shading
  * C. Steger - 20/12/30: Make the shader code work under macOS and iOS
+ * C. Steger - 26/01/02: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -388,7 +389,7 @@ typedef struct {
 #ifdef HAVE_GLSL
   GLfloat *uv;
   GLuint *indices;
-  Bool use_shaders, buffers_initialized;
+  Bool use_shaders, buffers_initialized, use_vao;
   GLuint shader_program;
   GLint vertex_uv_index, vertex_t_index, color_index;
   GLint mat_mv_index, mat_p_index, g_index, d_index;
@@ -402,6 +403,7 @@ typedef struct {
   GLint texture_sampler_index;
   GLuint vertex_uv_buffer,  vertex_t_buffer;
   GLuint color_buffer, indices_buffer;
+  GLuint vertex_array_object;
   GLint ni, ne, nt;
 #endif /* HAVE_GLSL */
 } romanboystruct;
@@ -411,197 +413,189 @@ static romanboystruct *romanboy = (romanboystruct *) NULL;
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *vertex_shader_attribs_2_1 =
-  "attribute vec2 VertexUV;\n"
-  "attribute vec4 VertexT;\n"
-  "attribute vec4 VertexColor;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_attribs_3_0 =
-  "in vec2 VertexUV;\n"
-  "in vec4 VertexT;\n"
-  "in vec4 VertexColor;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 Color;\n"
-  "out vec4 TexCoord;\n"
-  "\n";
-static const GLchar *vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform int G;\n"
-  "uniform float D;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  const float EPSILON = 1.19e-6f;\n"
-  "  const float M_PI = 3.14159265359f;\n"
-  "  const float M_SQRT2 = 1.41421356237f;\n"
-  "  float g = float(G);\n"
-  "  float u = VertexUV.x;\n"
-  "  float v = VertexUV.y;\n"
-  "  float sqrt2og = M_SQRT2/g;\n"
-  "  float h1m1og = 0.5f*(1.0f-1.0f/g);\n"
-  "  float gm1 = g-1.0f;\n"
-  "  float cu = cos(u);\n"
-  "  float su = sin(u);\n"
-  "  float cgu = cos(g*u);\n"
-  "  float sgu = sin(g*u);\n"
-  "  float cgm1u = cos(gm1*u);\n"
-  "  float sgm1u = sin(gm1*u);\n"
-  "  float cv = cos(v);\n"
-  "  float c2v = cos(2.0f*v);\n"
-  "  float s2v = sin(2.0f*v);\n"
-  "  float cv2 = cv*cv;\n"
-  "  float nomx = sqrt2og*cv2*cgm1u+h1m1og*s2v*cu;\n"
-  "  float nomy = sqrt2og*cv2*sgm1u-h1m1og*s2v*su;\n"
-  "  float nomux = -sqrt2og*cv2*gm1*sgm1u-h1m1og*s2v*su;\n"
-  "  float nomuy = sqrt2og*cv2*gm1*cgm1u-h1m1og*s2v*cu;\n"
-  "  float nomvx = -sqrt2og*s2v*cgm1u+2.0f*h1m1og*c2v*cu;\n"
-  "  float nomvy = -sqrt2og*s2v*sgm1u-2.0f*h1m1og*c2v*su;\n"
-  "  float den = 1.0f/(1.0f-0.5f*M_SQRT2*D*s2v*sgu);\n"
-  "  float den2 = den*den;\n"
-  "  float denu = 0.5f*M_SQRT2*D*g*cgu*s2v;\n"
-  "  float denv = M_SQRT2*D*sgu*c2v;\n"
-  "  vec3 x = vec3(nomx*den,\n"
-  "                nomy*den,\n"
-  "                cv2*den);\n"
-  "  if (0.5f*M_PI-abs(v) < EPSILON)\n"
-  "  {\n"
-  "    if (0.5f*M_PI-v < EPSILON)\n"
-  "      v = 0.5f*M_PI-EPSILON;\n"
-  "    else\n"
-  "      v = -0.5f*M_PI+EPSILON;\n"
-  "    cv = cos(v);\n"
-  "    c2v = cos(2.0f*v);\n"
-  "    s2v = sin(2.0f*v);\n"
-  "    cv2 = cv*cv;\n"
-  "    nomx = sqrt2og*cv2*cgm1u+h1m1og*s2v*cu;\n"
-  "    nomy = sqrt2og*cv2*sgm1u-h1m1og*s2v*su;\n"
-  "    nomux = -sqrt2og*cv2*gm1*sgm1u-h1m1og*s2v*su;\n"
-  "    nomuy = sqrt2og*cv2*gm1*cgm1u-h1m1og*s2v*cu;\n"
-  "    nomvx = -sqrt2og*s2v*cgm1u+2.0f*h1m1og*c2v*cu;\n"
-  "    nomvy = -sqrt2og*s2v*sgm1u-2.0f*h1m1og*c2v*su;\n"
-  "    den = 1.0f/(1.0f-0.5f*M_SQRT2*D*s2v*sgu);\n"
-  "    den2 = den*den;\n"
-  "    denu = 0.5f*M_SQRT2*D*g*cgu*s2v;\n"
-  "    denv = M_SQRT2*D*sgu*c2v;\n"
-  "  }\n"
-  "  vec3 xu = vec3(nomux*den+nomx*denu*den2,\n"
-  "                 nomuy*den+nomy*denu*den2,\n"
-  "                 cv2*denu*den2);\n"
-  "  vec3 xv = vec3(nomvx*den+nomx*denv*den2,\n"
-  "                 nomvy*den+nomy*denv*den2,\n"
-  "                 -s2v*den+cv2*denv*den2);\n"
-  "  vec4 Position = MatModelView*vec4(x,1.0f);\n"
-  "  vec4 pu = MatModelView*vec4(xu,0.0f);\n"
-  "  vec4 pv = MatModelView*vec4(xv,0.0f);\n"
-  "  Normal = normalize(cross(pu.xyz,pv.xyz));\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  Color = VertexColor;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexT;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 Color;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 Color;\n"
-  "in vec4 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *fragment_shader_main =
-  "uniform bool DrawLines;\n"
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSampler;"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 color;\n"
-  "  if (DrawLines)\n"
-  "  {\n"
-  "    color = Color;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    vec3 normalDirection;\n"
-  "    vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "    vec4 ambientLighting, diffuseReflection, specularReflection;\n"
-  "    float ndotl, ndoth, pf;\n"
-  "    \n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      normalDirection = normalize(Normal);\n"
-  "      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatFrontAmbient;\n"
-  "      diffuseColor = Color*MatFrontDiffuse;\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      normalDirection = -normalize(Normal);\n"
-  "      sceneColor = Color*MatBackAmbient*LtGlblAmbient;\n"
-  "      ambientColor = Color*MatBackAmbient;\n"
-  "      diffuseColor = Color*MatBackDiffuse;\n"
-  "    }\n"
-  "    \n"
-  "    ndotl = max(0.0,dot(normalDirection,LtDirection));\n"
-  "    ndoth = max(0.0,dot(normalDirection,LtHalfVector));\n"
-  "    if (ndotl == 0.0)\n"
-  "      pf = 0.0;\n"
-  "    else\n"
-  "      pf = pow(ndoth,MatShininess);\n"
-  "    ambientLighting = ambientColor*LtAmbient;\n"
-  "    diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "    specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "    color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *fragment_shader_out_2_1 =
-  "    if (BoolTextures)\n"
-  "      color *= texture2D(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  gl_FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
-static const GLchar *fragment_shader_out_3_0 =
-  "    if (BoolTextures)\n"
-  "      color *= texture(TextureSampler,TexCoord.st);"
-  "    color += specularReflection;\n"
-  "  }\n"
-  "  FragColor = clamp(color,0.0,1.0);\n"
-  "}\n";
+/* The vertex shader code. */
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec2 VertexUV;                                                 \n\
+attribute vec4 VertexT;                                                  \n\
+attribute vec4 VertexColor;                                              \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec2 VertexUV;                                                        \n\
+in vec4 VertexT;                                                         \n\
+in vec4 VertexColor;                                                     \n\
+out vec3 Normal;                                                         \n\
+out vec4 Color;                                                          \n\
+out vec4 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform int G;                                                           \n\
+uniform float D;                                                         \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  const float EPSILON = 1.19e-6f;                                        \n\
+  const float M_PI = 3.14159265359f;                                     \n\
+  const float M_SQRT2 = 1.41421356237f;                                  \n\
+  float g = float(G);                                                    \n\
+  float u = VertexUV.x;                                                  \n\
+  float v = VertexUV.y;                                                  \n\
+  float sqrt2og = M_SQRT2/g;                                             \n\
+  float h1m1og = 0.5f*(1.0f-1.0f/g);                                     \n\
+  float gm1 = g-1.0f;                                                    \n\
+  float cu = cos(u);                                                     \n\
+  float su = sin(u);                                                     \n\
+  float cgu = cos(g*u);                                                  \n\
+  float sgu = sin(g*u);                                                  \n\
+  float cgm1u = cos(gm1*u);                                              \n\
+  float sgm1u = sin(gm1*u);                                              \n\
+  float cv = cos(v);                                                     \n\
+  float c2v = cos(2.0f*v);                                               \n\
+  float s2v = sin(2.0f*v);                                               \n\
+  float cv2 = cv*cv;                                                     \n\
+  float nomx = sqrt2og*cv2*cgm1u+h1m1og*s2v*cu;                          \n\
+  float nomy = sqrt2og*cv2*sgm1u-h1m1og*s2v*su;                          \n\
+  float nomux = -sqrt2og*cv2*gm1*sgm1u-h1m1og*s2v*su;                    \n\
+  float nomuy = sqrt2og*cv2*gm1*cgm1u-h1m1og*s2v*cu;                     \n\
+  float nomvx = -sqrt2og*s2v*cgm1u+2.0f*h1m1og*c2v*cu;                   \n\
+  float nomvy = -sqrt2og*s2v*sgm1u-2.0f*h1m1og*c2v*su;                   \n\
+  float den = 1.0f/(1.0f-0.5f*M_SQRT2*D*s2v*sgu);                        \n\
+  float den2 = den*den;                                                  \n\
+  float denu = 0.5f*M_SQRT2*D*g*cgu*s2v;                                 \n\
+  float denv = M_SQRT2*D*sgu*c2v;                                        \n\
+  vec3 x = vec3(nomx*den,nomy*den,cv2*den);                              \n\
+  if (0.5f*M_PI-abs(v) < EPSILON)                                        \n\
+  {                                                                      \n\
+    if (0.5f*M_PI-v < EPSILON)                                           \n\
+      v = 0.5f*M_PI-EPSILON;                                             \n\
+    else                                                                 \n\
+      v = -0.5f*M_PI+EPSILON;                                            \n\
+    cv = cos(v);                                                         \n\
+    c2v = cos(2.0f*v);                                                   \n\
+    s2v = sin(2.0f*v);                                                   \n\
+    cv2 = cv*cv;                                                         \n\
+    nomx = sqrt2og*cv2*cgm1u+h1m1og*s2v*cu;                              \n\
+    nomy = sqrt2og*cv2*sgm1u-h1m1og*s2v*su;                              \n\
+    nomux = -sqrt2og*cv2*gm1*sgm1u-h1m1og*s2v*su;                        \n\
+    nomuy = sqrt2og*cv2*gm1*cgm1u-h1m1og*s2v*cu;                         \n\
+    nomvx = -sqrt2og*s2v*cgm1u+2.0f*h1m1og*c2v*cu;                       \n\
+    nomvy = -sqrt2og*s2v*sgm1u-2.0f*h1m1og*c2v*su;                       \n\
+    den = 1.0f/(1.0f-0.5f*M_SQRT2*D*s2v*sgu);                            \n\
+    den2 = den*den;                                                      \n\
+    denu = 0.5f*M_SQRT2*D*g*cgu*s2v;                                     \n\
+    denv = M_SQRT2*D*sgu*c2v;                                            \n\
+  }                                                                      \n\
+  vec3 xu = vec3(nomux*den+nomx*denu*den2,                               \n\
+                 nomuy*den+nomy*denu*den2,                               \n\
+                 cv2*denu*den2);                                         \n\
+  vec3 xv = vec3(nomvx*den+nomx*denv*den2,                               \n\
+                 nomvy*den+nomy*denv*den2,                               \n\
+                 -s2v*den+cv2*denv*den2);                                \n\
+  vec4 Position = MatModelView*vec4(x,1.0f);                             \n\
+  vec4 pu = MatModelView*vec4(xu,0.0f);                                  \n\
+  vec4 pv = MatModelView*vec4(xv,0.0f);                                  \n\
+  Normal = normalize(cross(pu.xyz,pv.xyz));                              \n\
+  gl_Position = MatProj*Position;                                        \n\
+  Color = VertexColor;                                                   \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexT;                                                  \n\
+}                                                                        \n";
+
+/* The fragment shader code. */
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 Color;                                                      \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 Color;                                                           \n\
+in vec4 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform bool DrawLines;                                                  \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSampler;                                        \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 color;                                                            \n\
+  if (DrawLines)                                                         \n\
+  {                                                                      \n\
+    color = Color;                                                       \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    vec3 normalDirection;                                                \n\
+    vec4 ambientColor, diffuseColor, sceneColor;                         \n\
+    vec4 ambientLighting, diffuseReflection, specularReflection;         \n\
+    float ndotl, ndoth, pf;                                              \n\
+                                                                         \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+      normalDirection = normalize(Normal);                               \n\
+      sceneColor = Color*MatFrontAmbient*LtGlblAmbient;                  \n\
+      ambientColor = Color*MatFrontAmbient;                              \n\
+      diffuseColor = Color*MatFrontDiffuse;                              \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+      normalDirection = -normalize(Normal);                              \n\
+      sceneColor = Color*MatBackAmbient*LtGlblAmbient;                   \n\
+      ambientColor = Color*MatBackAmbient;                               \n\
+      diffuseColor = Color*MatBackDiffuse;                               \n\
+    }                                                                    \n\
+                                                                         \n\
+    ndotl = max(0.0,dot(normalDirection,LtDirection));                   \n\
+    ndoth = max(0.0,dot(normalDirection,LtHalfVector));                  \n\
+    if (ndotl == 0.0)                                                    \n\
+      pf = 0.0;                                                          \n\
+    else                                                                 \n\
+      pf = pow(ndoth,MatShininess);                                      \n\
+    ambientLighting = ambientColor*LtAmbient;                            \n\
+    diffuseReflection = LtDiffuse*diffuseColor*ndotl;                    \n\
+    specularReflection = LtSpecular*MatSpecular*pf;                      \n\
+    color = sceneColor+ambientLighting+diffuseReflection;                \n\
+    if (BoolTextures)                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSampler,TexCoord.st).rrra;               \n\
+#else                                                                    \n\
+      color *= texture(TextureSampler,TexCoord.st).rrra;                 \n\
+#endif                                                                   \n\
+    color += specularReflection;                                         \n\
+    color.a = diffuseColor.a;                                            \n\
+  }                                                                      \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0,1.0);                                   \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0,1.0);                                      \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -1088,6 +1082,7 @@ static int roman_boy_ff(ModeInfo *mi, double umin, double umax,
   if (pp->marks)
   {
     glEnable(GL_TEXTURE_2D);
+    glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
 #ifndef HAVE_JWZGLES
     glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
 #endif
@@ -1905,6 +1900,9 @@ static int roman_boy_pf(ModeInfo *mi, double umin, double umax,
     }
   }
 
+  if (pp->use_vao)
+    glBindVertexArray(pp->vertex_array_object);
+
   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D,pp->tex_name);
   glUniform1i(pp->texture_sampler_index,0);
@@ -1954,6 +1952,9 @@ static int roman_boy_pf(ModeInfo *mi, double umin, double umax,
   glBindBuffer(GL_ARRAY_BUFFER,0);
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+  if (pp->use_vao)
+    glBindVertexArray(0);
+
   glUseProgram(0);
 
   if (pp->appearance != APPEARANCE_DIRECTION_BANDS)
@@ -1985,9 +1986,14 @@ static void gen_texture(ModeInfo *mi)
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
-  glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
-  glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
-               GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
+#ifdef HAVE_GLSL
+  if (pp->use_shaders)
+    glTexImage2D(GL_TEXTURE_2D,0,GL_R8,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_RED,GL_UNSIGNED_BYTE,texture);
+  else
+#endif /* HAVE_GLSL */
+    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,TEX_DIMENSION,TEX_DIMENSION,0,
+                 GL_LUMINANCE,GL_UNSIGNED_BYTE,texture);
 }
 
 
@@ -1998,8 +2004,8 @@ static void init_glsl(ModeInfo *mi)
   romanboystruct *pp = &romanboy[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   pp->uv = calloc(2*pp->g*(NUMU+1)*(NUMV+1),sizeof(float));
   pp->indices = calloc(4*pp->g*(NUMU+1)*(NUMV+1),sizeof(float));
@@ -2011,54 +2017,18 @@ static void init_glsl(ModeInfo *mi)
   pp->ni = 0;
   pp->ne = 0;
   pp->nt = 0;
+  pp->use_vao = False;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      vertex_shader_source[0] = shader_version_2_1;
-      vertex_shader_source[1] = vertex_shader_attribs_2_1;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_2_1;
-      fragment_shader_source[1] = fragment_shader_attribs_2_1;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      vertex_shader_source[0] = shader_version_3_0;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    vertex_shader_source[0] = shader_version_3_0_es;
-    vertex_shader_source[1] = vertex_shader_attribs_3_0;
-    vertex_shader_source[2] = vertex_shader_main;
-    fragment_shader_source[0] = shader_version_3_0_es;
-    fragment_shader_source[1] = fragment_shader_attribs_3_0;
-    fragment_shader_source[2] = fragment_shader_main;
-    fragment_shader_source[3] = fragment_shader_out_3_0;
-  }
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &pp->shader_program))
     return;
   pp->vertex_uv_index = glGetAttribLocation(pp->shader_program,"VertexUV");
@@ -2128,6 +2098,10 @@ static void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&pp->color_buffer);
   glGenBuffers(1,&pp->indices_buffer);
 
+  pp->use_vao = glsl_IsCoreProfile();
+  if (pp->use_vao)
+    glGenVertexArrays(1,&pp->vertex_array_object);
+
   pp->use_shaders = True;
 }
 
@@ -2187,13 +2161,13 @@ static void init(ModeInfo *mi)
   pp->col = calloc(4*pp->g*(NUMU+1)*(NUMV+1),sizeof(float));
   pp->tex = calloc(2*pp->g*(NUMU+1)*(NUMV+1),sizeof(float));
 
-  gen_texture(mi);
-  setup_roman_boy_color_texture(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,pp->g*NUMU,NUMV);
-
 #ifdef HAVE_GLSL
   init_glsl(mi);
 #endif /* HAVE_GLSL */
 
+  gen_texture(mi);
+  setup_roman_boy_color_texture(mi,0.0,2.0*M_PI,0.0,2.0*M_PI,pp->g*NUMU,NUMV);
+
 #ifdef HAVE_ANDROID
   /* glPolygonMode(...,GL_LINE) is not supported for an OpenGL ES 1.1
      context. */
@@ -2573,6 +2547,8 @@ ENTRYPOINT void free_romanboy(ModeInfo *mi)
     glDeleteBuffers(1,&pp->vertex_t_buffer);
     glDeleteBuffers(1,&pp->color_buffer);
     glDeleteBuffers(1,&pp->indices_buffer);
+    if (pp->use_vao)
+      glDeleteVertexArrays(1,&pp->vertex_array_object);
     if (pp->shader_program != 0)
     {
       glUseProgram(0);
diff --git a/hacks/glx/selfreflect.man b/hacks/glx/selfreflect.man
new file mode 100644 (file)
index 0000000..b62fcf4
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+selfreflect \- screen saver.
+.SH SYNOPSIS
+.B selfreflect
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Platonic solids with inner mirrors. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/XfyXRV
+.SH COPYRIGHT
+Copyright \(co 2024 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
diff --git a/hacks/glx/skyline.man b/hacks/glx/skyline.man
new file mode 100644 (file)
index 0000000..f09cca4
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+skyline \- screen saver.
+.SH SYNOPSIS
+.B skyline
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+A procedurally-generated cityscape. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/XtsSWs
+.SH COPYRIGHT
+Copyright \(co 2015 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
index 68d683f14020c27d783157418b7ebd2ef14c9d83..61c98a1578b697eac8e7406cc9d4b08fc4ed6ec4 100644 (file)
@@ -4,7 +4,7 @@
    transversally.  However, no creases or pinch points are allowed to
    occur. */
 
-/* Copyright (c) 2020-2022 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2020-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -21,6 +21,8 @@
  *
  * REVISION HISTORY:
  * C. Steger - 22/02/25: Moved the analytic sphere eversion code to this file
+ * C. Steger - 26/01/03: Make the code work in an OpenGL core profile
+ * C. Steger - 26/01/11: Use framebuffer objects for blending if possible
  */
 
 /*
@@ -1192,7 +1194,7 @@ static int bednorz_sphere_eversion_ff(ModeInfo *mi, float phi_min,
   numb_dir_min = numb_dir/4;
   numb_dir_max = 3*numb_dir/4;
 
-  glClearColor(0.0f,0.0f,0.0f,1.0f);
+  glClearColor(0.0f,0.0f,0.0f,0.0f);
   glClearDepth(1.0f);
   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
 
@@ -1464,6 +1466,11 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
     { { -1.0, -1.0 }, { 1.0, -1.0 }, { 1.0, 1.0 }, { -1.0, 1.0 } };
   static const GLfloat blend_t[4][2] =
     { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } };
+  static const GLenum draw_buffers[2] =
+  {
+    GL_COLOR_ATTACHMENT0,
+    GL_BACK
+  };
   GLfloat light_direction[3], half_vector[3], len;
   GLfloat p_mat[16], mv_mat[16], rot_mat[16];
   float mat[3][3];
@@ -1596,6 +1603,19 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
                  se->line_indices,GL_STATIC_DRAW);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_pos_buffer);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(blend_p),blend_p,GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER,0);
+
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_tex_coord_buffer);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(blend_t),blend_t,GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER,0);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,se->blend_indices_buffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(blend_indices),
+                 blend_indices,GL_STATIC_DRAW);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
     se->buffers_initialized = True;
   }
 
@@ -1760,21 +1780,20 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
 
   for (pass=0; pass<num_passes; pass++)
   {
-    glUseProgram(se->poly_shader_program);
-
-    glClearColor(0.0f,0.0f,0.0f,1.0f);
-    glClearDepth(1.0f);
-    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-
-    glUniformMatrix4fv(se->poly_mv_index,1,GL_FALSE,mv_mat);
-    glUniformMatrix4fv(se->poly_proj_index,1,GL_FALSE,p_mat);
-
-    glUniform4fv(se->poly_front_ambient_index,1,mat_diff_white);
-    glUniform4fv(se->poly_front_diffuse_index,1,mat_diff_white);
-    glUniform4fv(se->poly_back_ambient_index,1,mat_diff_white);
-    glUniform4fv(se->poly_back_diffuse_index,1,mat_diff_white);
-    glVertexAttrib4f(se->poly_colorf_index,1.0f,1.0f,1.0f,1.0f);
-    glVertexAttrib4f(se->poly_colorb_index,1.0f,1.0f,1.0f,1.0f);
+    if (se->use_fbo)
+    {
+      if (num_passes == 2)
+      {
+        glBindFramebuffer(GL_FRAMEBUFFER,se->blend_fbo[pass]);
+        glDrawBuffers(1,&draw_buffers[0]);
+      }
+      else
+      {
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER,se->default_draw_fbo);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER,se->default_read_fbo);
+        glDrawBuffers(1,&draw_buffers[1]);
+      }
+    }
 
     if (se->display_mode[pass] == DISP_SURFACE)
     {
@@ -1783,17 +1802,6 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
       glDepthFunc(GL_LESS);
       glDepthMask(GL_TRUE);
       glDisable(GL_BLEND);
-      glUniform4fv(se->poly_glbl_ambient_index,1,light_model_ambient);
-      if (se->colors[pass] != COLORS_EARTH)
-        glUniform4fv(se->poly_lt_ambient_index,1,light_ambient);
-      else
-        glUniform4fv(se->poly_lt_ambient_index,1,light_ambient_earth);
-      glUniform4fv(se->poly_lt_diffuse_index,1,light_diffuse);
-      glUniform4fv(se->poly_lt_specular_index,1,light_specular);
-      glUniform3fv(se->poly_lt_direction_index,1,light_direction);
-      glUniform3fv(se->poly_lt_halfvect_index,1,half_vector);
-      glUniform4fv(se->poly_specular_index,1,mat_specular);
-      glUniform1f(se->poly_shininess_index,50.0f);
     }
     else /* se->display_mode[pass] == DISP_TRANSPARENT */
     {
@@ -1802,19 +1810,39 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
       glDepthMask(GL_FALSE);
       glEnable(GL_BLEND);
       glBlendFunc(GL_SRC_ALPHA,GL_ONE);
-      glUniform4fv(se->poly_glbl_ambient_index,1,light_model_ambient);
-      if (se->colors[pass] != COLORS_EARTH)
-        glUniform4fv(se->poly_lt_ambient_index,1,light_ambient);
-      else
-        glUniform4fv(se->poly_lt_ambient_index,1,light_ambient_earth);
-      glUniform4fv(se->poly_lt_diffuse_index,1,light_diffuse);
-      glUniform4fv(se->poly_lt_specular_index,1,light_specular);
-      glUniform3fv(se->poly_lt_direction_index,1,light_direction);
-      glUniform3fv(se->poly_lt_halfvect_index,1,half_vector);
-      glUniform4fv(se->poly_specular_index,1,mat_specular);
-      glUniform1f(se->poly_shininess_index,50.0f);
     }
 
+    glUseProgram(se->poly_shader_program);
+
+    if (se->use_vao)
+      glBindVertexArray(se->vertex_array_object);
+
+    glClearColor(0.0f,0.0f,0.0f,0.0f);
+    glClearDepth(1.0f);
+    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
+
+    glUniformMatrix4fv(se->poly_mv_index,1,GL_FALSE,mv_mat);
+    glUniformMatrix4fv(se->poly_proj_index,1,GL_FALSE,p_mat);
+
+    glUniform4fv(se->poly_front_ambient_index,1,mat_diff_white);
+    glUniform4fv(se->poly_front_diffuse_index,1,mat_diff_white);
+    glUniform4fv(se->poly_back_ambient_index,1,mat_diff_white);
+    glUniform4fv(se->poly_back_diffuse_index,1,mat_diff_white);
+    glVertexAttrib4f(se->poly_colorf_index,1.0f,1.0f,1.0f,1.0f);
+    glVertexAttrib4f(se->poly_colorb_index,1.0f,1.0f,1.0f,1.0f);
+
+    glUniform4fv(se->poly_glbl_ambient_index,1,light_model_ambient);
+    if (se->colors[pass] != COLORS_EARTH)
+      glUniform4fv(se->poly_lt_ambient_index,1,light_ambient);
+    else
+      glUniform4fv(se->poly_lt_ambient_index,1,light_ambient_earth);
+    glUniform4fv(se->poly_lt_diffuse_index,1,light_diffuse);
+    glUniform4fv(se->poly_lt_specular_index,1,light_specular);
+    glUniform3fv(se->poly_lt_direction_index,1,light_direction);
+    glUniform3fv(se->poly_lt_halfvect_index,1,half_vector);
+    glUniform4fv(se->poly_specular_index,1,mat_specular);
+    glUniform1f(se->poly_shininess_index,50.0f);
+
     if (se->colors[pass] == COLORS_TWOSIDED)
     {
       if (se->display_mode[pass] == DISP_TRANSPARENT)
@@ -1850,15 +1878,15 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
       }
     }
 
-    glActiveTexture(GL_TEXTURE0);
+    glActiveTexture(GL_TEXTURE2);
     glBindTexture(GL_TEXTURE_2D,se->tex_names[0]);
-    glUniform1i(se->poly_tex_samp_f_index,0);
-    glActiveTexture(GL_TEXTURE1);
+    glUniform1i(se->poly_tex_samp_f_index,2);
+    glActiveTexture(GL_TEXTURE3);
     glBindTexture(GL_TEXTURE_2D,se->tex_names[1]);
-    glUniform1i(se->poly_tex_samp_b_index,1);
-    glActiveTexture(GL_TEXTURE2);
+    glUniform1i(se->poly_tex_samp_b_index,3);
+    glActiveTexture(GL_TEXTURE4);
     glBindTexture(GL_TEXTURE_2D,se->tex_names[2]);
-    glUniform1i(se->poly_tex_samp_w_index,2);
+    glUniform1i(se->poly_tex_samp_w_index,4);
     glUniform1i(se->poly_bool_textures_index,se->colors[pass] == COLORS_EARTH);
 
     glEnable(GL_POLYGON_OFFSET_FILL);
@@ -1957,12 +1985,18 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
     glDisable(GL_POLYGON_OFFSET_FILL);
     glPolygonOffset(0.0f,0.0f);
 
+    if (se->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
     if (se->graticule[pass])
     {
       glUseProgram(se->line_shader_program);
 
+      if (se->use_vao)
+        glBindVertexArray(se->vertex_array_object);
+
       glUniformMatrix4fv(se->line_mv_index,1,GL_FALSE,mv_mat);
       glUniformMatrix4fv(se->line_proj_index,1,GL_FALSE,p_mat);
       glUniform4f(se->line_color_index,1.0f,1.0f,1.0f,1.0f);
@@ -1983,23 +2017,36 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
       glBindBuffer(GL_ARRAY_BUFFER,0);
       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+      if (se->use_vao)
+        glBindVertexArray(0);
+
       glUseProgram(0);
     }
  
-    if (num_passes == 2)
+    if (!se->use_fbo)
     {
-      /* Copy the rendered image to a texture. */
-      glGetIntegerv(GL_DRAW_BUFFER0,&draw_buf);
-      glGetIntegerv(GL_READ_BUFFER,&read_buf);
-      glReadBuffer(draw_buf);
-      glBindTexture(GL_TEXTURE_2D,se->color_textures[pass]);
-      glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,se->WindW,se->WindH);
-      glReadBuffer(read_buf);
+      if (num_passes == 2)
+      {
+        /* Copy the rendered image to a texture. */
+        glGetIntegerv(GL_DRAW_BUFFER0,&draw_buf);
+        glGetIntegerv(GL_READ_BUFFER,&read_buf);
+        glReadBuffer(draw_buf);
+        glBindTexture(GL_TEXTURE_2D,se->color_textures[pass]);
+        glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,se->WindW,se->WindH);
+        glReadBuffer(read_buf);
+      }
     }
   }
 
   if (num_passes == 2)
   {
+    if (se->use_fbo)
+    {
+      glBindFramebuffer(GL_DRAW_FRAMEBUFFER,se->default_draw_fbo);
+      glBindFramebuffer(GL_READ_FRAMEBUFFER,se->default_read_fbo);
+      glDrawBuffers(1,&draw_buffers[1]);
+    }
+
     t = (float)se->turn_step/(float)se->num_turn;
     /* Apply an easing function to t. */
     t = (3.0-2.0*t)*t*t;
@@ -2016,26 +2063,45 @@ static int bednorz_sphere_eversion_pf(ModeInfo *mi, float phi_min,
 
     glUniform1f(se->blend_t_index,t);
 
+    if (se->use_vao)
+      glBindVertexArray(se->vertex_array_object);
+
     glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D,se->color_textures[0]);
+    if (se->use_fbo)
+      glBindTexture(GL_TEXTURE_2D,se->blend_color_tex[0]);
+    else
+      glBindTexture(GL_TEXTURE_2D,se->color_textures[0]);
     glUniform1i(se->blend_sampler0_index,0);
 
     glActiveTexture(GL_TEXTURE1);
-    glBindTexture(GL_TEXTURE_2D,se->color_textures[1]);
+    if (se->use_fbo)
+      glBindTexture(GL_TEXTURE_2D,se->blend_color_tex[1]);
+    else
+      glBindTexture(GL_TEXTURE_2D,se->color_textures[1]);
     glUniform1i(se->blend_sampler1_index,1);
 
     glEnableVertexAttribArray(se->blend_vertex_p_index);
-    glVertexAttribPointer(se->blend_vertex_p_index,2,GL_FLOAT,GL_FALSE,
-                          2*sizeof(GLfloat),blend_p);
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_pos_buffer);
+    glVertexAttribPointer(se->blend_vertex_p_index,2,GL_FLOAT,GL_FALSE,0,0);
 
     glEnableVertexAttribArray(se->blend_vertex_t_index);
-    glVertexAttribPointer(se->blend_vertex_t_index,2,GL_FLOAT,GL_FALSE,
-                          2*sizeof(GLfloat),blend_t);
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_tex_coord_buffer);
+    glVertexAttribPointer(se->blend_vertex_t_index,2,GL_FLOAT,GL_FALSE,0,0);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,se->blend_indices_buffer);
 
-    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,blend_indices);
+    index_offset = 0;
+    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,
+                   (const void *)index_offset);
 
     glActiveTexture(GL_TEXTURE0);
 
+    glBindBuffer(GL_ARRAY_BUFFER,0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
+    if (se->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
   }
 
index df458735ea8dd837376525aeeae8c649eead9e0c..9550883c7486f20179fb4493752e2cdc2d16018c 100644 (file)
@@ -4,7 +4,7 @@
    itself transversally.  However, no creases or pinch points are
    allowed to occur. */
 
-/* Copyright (c) 2021-2022 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2021-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -21,6 +21,8 @@
  *
  * REVISION HISTORY:
  * C. Steger - 22/02/25: Initial version
+ * C. Steger - 26/01/03: Make the code work in an OpenGL core profile
+ * C. Steger - 26/01/11: Use framebuffer objects for blending if possible
  */
 
 /*
@@ -1683,6 +1685,11 @@ static int outside_in_pf(ModeInfo *mi)
     { { -1.0, -1.0 }, { 1.0, -1.0 }, { 1.0, 1.0 }, { -1.0, 1.0 } };
   static const GLfloat blend_t[4][2] =
     { { 0.0, 0.0 }, { 1.0, 0.0 }, { 1.0, 1.0 }, { 0.0, 1.0 } };
+  static const GLenum draw_buffers[2] =
+  {
+    GL_COLOR_ATTACHMENT0,
+    GL_BACK
+  };
   sphereeversionstruct *se = &sphereeversion[MI_SCREEN(mi)];
   int i, j, k, l, hemisphere, strip, pass, num_passes, ni;
   float angle, t;
@@ -1771,6 +1778,19 @@ static int outside_in_pf(ModeInfo *mi)
                  se->meridian_indices,GL_STATIC_DRAW);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_pos_buffer);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(blend_p),blend_p,GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER,0);
+
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_tex_coord_buffer);
+    glBufferData(GL_ARRAY_BUFFER,sizeof(blend_t),blend_t,GL_STATIC_DRAW);
+    glBindBuffer(GL_ARRAY_BUFFER,0);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,se->blend_indices_buffer);
+    glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(blend_indices),
+                 blend_indices,GL_STATIC_DRAW);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
     se->buffers_initialized = GL_TRUE;
   }
 
@@ -1832,8 +1852,43 @@ static int outside_in_pf(ModeInfo *mi)
 
   for (pass=0; pass<num_passes; pass++)
   {
+    if (se->use_fbo)
+    {
+      if (num_passes == 2)
+      {
+        glBindFramebuffer(GL_FRAMEBUFFER,se->blend_fbo[pass]);
+        glDrawBuffers(1,&draw_buffers[0]);
+      }
+      else
+      {
+        glBindFramebuffer(GL_DRAW_FRAMEBUFFER,se->default_draw_fbo);
+        glBindFramebuffer(GL_READ_FRAMEBUFFER,se->default_read_fbo);
+        glDrawBuffers(1,&draw_buffers[1]);
+      }
+    }
+
+    if (se->display_mode[pass] == DISP_SURFACE)
+    {
+      glDisable(GL_CULL_FACE);
+      glEnable(GL_DEPTH_TEST);
+      glDepthFunc(GL_LESS);
+      glDepthMask(GL_TRUE);
+      glDisable(GL_BLEND);
+    }
+    else
+    {
+      glDisable(GL_CULL_FACE);
+      glDisable(GL_DEPTH_TEST);
+      glDepthMask(GL_FALSE);
+      glEnable(GL_BLEND);
+      glBlendFunc(GL_SRC_ALPHA,GL_ONE);
+    }
+
     glUseProgram(se->poly_shader_program);
 
+    if (se->use_vao)
+      glBindVertexArray(se->vertex_array_object);
+
     glClearColor(0.0f,0.0f,0.0f,0.0f);
     glClearDepth(1.0f);
     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -1866,23 +1921,6 @@ static int outside_in_pf(ModeInfo *mi)
     glUniform4fv(se->poly_specular_index,1,mat_specular);
     glUniform1f(se->poly_shininess_index,50.0f);
 
-    if (se->display_mode[pass] == DISP_SURFACE)
-    {
-      glDisable(GL_CULL_FACE);
-      glEnable(GL_DEPTH_TEST);
-      glDepthFunc(GL_LESS);
-      glDepthMask(GL_TRUE);
-      glDisable(GL_BLEND);
-    }
-    else
-    {
-      glDisable(GL_CULL_FACE);
-      glDisable(GL_DEPTH_TEST);
-      glDepthMask(GL_FALSE);
-      glEnable(GL_BLEND);
-      glBlendFunc(GL_SRC_ALPHA,GL_ONE);
-    }
-
     if (se->colors[pass] == COLORS_TWOSIDED)
     {
       if (se->display_mode[pass] == DISP_SURFACE)
@@ -1918,15 +1956,15 @@ static int outside_in_pf(ModeInfo *mi)
       }
     }
 
-    glActiveTexture(GL_TEXTURE0);
+    glActiveTexture(GL_TEXTURE2);
     glBindTexture(GL_TEXTURE_2D,se->tex_names[0]);
-    glUniform1i(se->poly_tex_samp_f_index,0);
-    glActiveTexture(GL_TEXTURE1);
+    glUniform1i(se->poly_tex_samp_f_index,2);
+    glActiveTexture(GL_TEXTURE3);
     glBindTexture(GL_TEXTURE_2D,se->tex_names[1]);
-    glUniform1i(se->poly_tex_samp_b_index,1);
-    glActiveTexture(GL_TEXTURE2);
+    glUniform1i(se->poly_tex_samp_b_index,3);
+    glActiveTexture(GL_TEXTURE4);
     glBindTexture(GL_TEXTURE_2D,se->tex_names[2]);
-    glUniform1i(se->poly_tex_samp_w_index,2);
+    glUniform1i(se->poly_tex_samp_w_index,4);
     glUniform1i(se->poly_bool_textures_index,se->colors[pass] == COLORS_EARTH);
 
     glEnableVertexAttribArray(se->poly_pos_index);
@@ -2049,28 +2087,44 @@ static int outside_in_pf(ModeInfo *mi)
     glBindBuffer(GL_ARRAY_BUFFER,0);
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
 
+    if (se->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
 
-    if (num_passes == 2)
+    if (!se->use_fbo)
     {
-      /* Copy the rendered image to a texture. */
-      glGetIntegerv(GL_DRAW_BUFFER0,&draw_buf);
-      glGetIntegerv(GL_READ_BUFFER,&read_buf);
-      glReadBuffer(draw_buf);
-      glBindTexture(GL_TEXTURE_2D,se->color_textures[pass]);
-      glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,se->WindW,se->WindH);
-      glReadBuffer(read_buf);
+      if (num_passes == 2)
+      {
+        /* Copy the rendered image to a texture. */
+        glGetIntegerv(GL_DRAW_BUFFER0,&draw_buf);
+        glGetIntegerv(GL_READ_BUFFER,&read_buf);
+        glReadBuffer(draw_buf);
+        glBindTexture(GL_TEXTURE_2D,se->color_textures[pass]);
+        glCopyTexSubImage2D(GL_TEXTURE_2D,0,0,0,0,0,se->WindW,se->WindH);
+        glReadBuffer(read_buf);
+      }
     }
   }
 
   if (num_passes == 2)
   {
+    if (se->use_fbo)
+    {
+      glBindFramebuffer(GL_DRAW_FRAMEBUFFER,se->default_draw_fbo);
+      glBindFramebuffer(GL_READ_FRAMEBUFFER,se->default_read_fbo);
+      glDrawBuffers(1,&draw_buffers[1]);
+    }
+
     t = (float)se->turn_step/(float)se->num_turn;
     /* Apply an easing function to t. */
     t = (3.0-2.0*t)*t*t;
 
     glUseProgram(se->blend_shader_program);
 
+    if (se->use_vao)
+      glBindVertexArray(se->vertex_array_object);
+
     glClearColor(0.0f,0.0f,0.0f,1.0f);
     glClearDepth(1.0f);
     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
@@ -2082,25 +2136,49 @@ static int outside_in_pf(ModeInfo *mi)
     glUniform1f(se->blend_t_index,t);
 
     glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D,se->color_textures[0]);
+    if (se->use_fbo)
+      glBindTexture(GL_TEXTURE_2D,se->blend_color_tex[0]);
+    else
+      glBindTexture(GL_TEXTURE_2D,se->color_textures[0]);
     glUniform1i(se->blend_sampler0_index,0);
 
     glActiveTexture(GL_TEXTURE1);
-    glBindTexture(GL_TEXTURE_2D,se->color_textures[1]);
+    if (se->use_fbo)
+      glBindTexture(GL_TEXTURE_2D,se->blend_color_tex[1]);
+    else
+      glBindTexture(GL_TEXTURE_2D,se->color_textures[1]);
     glUniform1i(se->blend_sampler1_index,1);
 
     glEnableVertexAttribArray(se->blend_vertex_p_index);
-    glVertexAttribPointer(se->blend_vertex_p_index,2,GL_FLOAT,GL_FALSE,
-                          2*sizeof(GLfloat),blend_p);
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_pos_buffer);
+    glVertexAttribPointer(se->blend_vertex_p_index,2,GL_FLOAT,GL_FALSE,0,0);
 
     glEnableVertexAttribArray(se->blend_vertex_t_index);
-    glVertexAttribPointer(se->blend_vertex_t_index,2,GL_FLOAT,GL_FALSE,
-                          2*sizeof(GLfloat),blend_t);
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_tex_coord_buffer);
+    glVertexAttribPointer(se->blend_vertex_t_index,2,GL_FLOAT,GL_FALSE,0,0);
 
-    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,blend_indices);
+    glEnableVertexAttribArray(se->blend_vertex_p_index);
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_pos_buffer);
+    glVertexAttribPointer(se->blend_vertex_p_index,2,GL_FLOAT,GL_FALSE,0,0);
+
+    glEnableVertexAttribArray(se->blend_vertex_t_index);
+    glBindBuffer(GL_ARRAY_BUFFER,se->blend_tex_coord_buffer);
+    glVertexAttribPointer(se->blend_vertex_t_index,2,GL_FLOAT,GL_FALSE,0,0);
+
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,se->blend_indices_buffer);
+
+    index_offset = 0;
+    glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,
+                   (const void *)index_offset);
 
     glActiveTexture(GL_TEXTURE0);
 
+    glBindBuffer(GL_ARRAY_BUFFER,0);
+    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
+
+    if (se->use_vao)
+      glBindVertexArray(0);
+
     glUseProgram(0);
   }
 
index c159e16356c39ae182d7425606de3b075f7fdbee..9000ced3127acd07e93dd3a8fa7a76eafa49de60 100644 (file)
@@ -7,7 +7,7 @@
 static const char sccsid[] = "@(#)sphereeversion.c  1.1 20/03/22 xlockmore";
 #endif
 
-/* Copyright (c) 2020-2022 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2020-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
@@ -35,6 +35,7 @@ static const char sccsid[] = "@(#)sphereeversion.c  1.1 20/03/22 xlockmore";
  *                       multiple render passes
  * C. Steger - 21/12/23: Added the earth color mode
  * C. Steger - 22/02/25: Added the corrugations sphere eversion
+ * C. Steger - 26/01/03: Make the code work in an OpenGL core profile
  */
 
 /*
@@ -187,250 +188,247 @@ sphereeversionstruct *sphereeversion = (sphereeversionstruct *) NULL;
 
 #ifdef HAVE_GLSL
 
-/* The GLSL versions that correspond to different versions of OpenGL. */
-static const GLchar *shader_version_2_1 =
-  "#version 120\n";
-static const GLchar *shader_version_3_0 =
-  "#version 130\n";
-static const GLchar *shader_version_3_0_es =
-  "#version 300 es\n"
-  "precision highp float;\n"
-  "precision highp int;\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glShaderSource in the function init_glsl(). */
-static const GLchar *poly_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "attribute vec3 VertexNormal;\n"
-  "attribute vec4 VertexColorF;\n"
-  "attribute vec4 VertexColorB;\n"
-  "attribute vec4 VertexTexCoord;\n"
-  "\n"
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *poly_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "in vec3 VertexNormal;\n"
-  "in vec4 VertexColorF;\n"
-  "in vec4 VertexColorB;\n"
-  "in vec4 VertexTexCoord;\n"
-  "\n"
-  "out vec3 Normal;\n"
-  "out vec4 ColorF;\n"
-  "out vec4 ColorB;\n"
-  "out vec4 TexCoord;\n"
-  "\n";
-static const GLchar *poly_vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "uniform bool BoolTextures;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  ColorF = VertexColorF;\n"
-  "  ColorB = VertexColorB;\n"
-  "  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "  if (BoolTextures)\n"
-  "    TexCoord = VertexTexCoord;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *poly_fragment_shader_attribs_2_1 =
-  "varying vec3 Normal;\n"
-  "varying vec4 ColorF;\n"
-  "varying vec4 ColorB;\n"
-  "varying vec4 TexCoord;\n"
-  "\n";
-static const GLchar *poly_fragment_shader_attribs_3_0 =
-  "in vec3 Normal;\n"
-  "in vec4 ColorF;\n"
-  "in vec4 ColorB;\n"
-  "in vec4 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *poly_fragment_shader_main =
-  "uniform vec4 LtGlblAmbient;\n"
-  "uniform vec4 LtAmbient, LtDiffuse, LtSpecular;\n"
-  "uniform vec3 LtDirection, LtHalfVector;\n"
-  "uniform vec4 MatFrontAmbient, MatBackAmbient;\n"
-  "uniform vec4 MatFrontDiffuse, MatBackDiffuse;\n"
-  "uniform vec4 MatSpecular;\n"
-  "uniform float MatShininess;\n"
-  "uniform bool BoolTextures;\n"
-  "uniform sampler2D TextureSamplerFront;"
-  "uniform sampler2D TextureSamplerBack;"
-  "uniform sampler2D TextureSamplerWater;"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec3 normalDirection;\n"
-  "  vec4 ambientColor, diffuseColor, sceneColor;\n"
-  "  vec4 ambientLighting, diffuseReflection, specularReflection, color;\n"
-  "  float ndotl, ndoth, pf;\n"
-  "  \n"
-  "  if (gl_FrontFacing)\n"
-  "  {\n"
-  "    normalDirection = normalize(Normal);\n"
-  "    sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;\n"
-  "    ambientColor = ColorF*MatFrontAmbient;\n"
-  "    diffuseColor = ColorF*MatFrontDiffuse;\n"
-  "  }\n"
-  "  else\n"
-  "  {\n"
-  "    normalDirection = -normalize(Normal);\n"
-  "    sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;\n"
-  "    ambientColor = ColorB*MatBackAmbient;\n"
-  "    diffuseColor = ColorB*MatBackDiffuse;\n"
-  "  }\n"
-  "  \n"
-  "  ndotl = max(0.0f,dot(normalDirection,LtDirection));\n"
-  "  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));\n"
-  "  if (ndotl == 0.0f)\n"
-  "    pf = 0.0f;\n"
-  "  else\n"
-  "    pf = pow(ndoth,MatShininess);\n"
-  "  ambientLighting = ambientColor*LtAmbient;\n"
-  "  diffuseReflection = LtDiffuse*diffuseColor*ndotl;\n"
-  "  specularReflection = LtSpecular*MatSpecular*pf;\n"
-  "  color = sceneColor+ambientLighting+diffuseReflection;\n";
-static const GLchar *poly_fragment_shader_out_2_1 =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture2D(TextureSamplerFront,TexCoord.st);\n"
-  "      specularReflection *= texture2D(TextureSamplerWater,TexCoord.st);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture2D(TextureSamplerBack,TexCoord.st);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  gl_FragColor = clamp(color,0.0f,1.0f);\n"
-  "}\n";
-static const GLchar *poly_fragment_shader_out_3_0 =
-  "  if (BoolTextures)\n"
-  "  {\n"
-  "    if (gl_FrontFacing)\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerFront,TexCoord.st);\n"
-  "      specularReflection *= texture(TextureSamplerWater,TexCoord.st);\n"
-  "    }\n"
-  "    else\n"
-  "    {\n"
-  "      color *= texture(TextureSamplerBack,TexCoord.st);\n"
-  "      specularReflection *= 0.0f;\n"
-  "    }\n"
-  "  }\n"
-  "  color += specularReflection;\n"
-  "  FragColor = clamp(color,0.0f,1.0f);\n"
-  "}\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *line_vertex_shader_attribs_2_1 =
-  "attribute vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *line_vertex_shader_attribs_3_0 =
-  "in vec3 VertexPosition;\n"
-  "\n";
-static const GLchar *line_vertex_shader_main =
-  "uniform mat4 MatModelView;\n"
-  "uniform mat4 MatProj;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n"
-  "  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);\n"
-  "  gl_Position = MatProj*Position;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *line_fragment_shader_attribs_2_1 =
-  "";
-static const GLchar *line_fragment_shader_attribs_3_0 =
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *line_fragment_shader_main =
-  "uniform vec4 LineColor;\n"
-  "\n"
-  "void main (void)\n"
-  "{\n";
-static const GLchar *line_fragment_shader_out_2_1 =
-  "  gl_FragColor = LineColor;\n"
-  "}\n";
-static const GLchar *line_fragment_shader_out_3_0 =
-  "  FragColor = LineColor;\n"
-  "}\n";
-
-/* The vertex shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *blend_vertex_shader_attribs_2_1 =
-  "attribute vec2 VertexP;\n"
-  "attribute vec2 VertexT;\n"
-  "\n"
-  "varying vec2 TexCoord;\n"
-  "\n";
-static const GLchar *blend_vertex_shader_attribs_3_0 =
-  "in vec2 VertexP;\n"
-  "in vec2 VertexT;\n"
-  "\n"
-  "out vec2 TexCoord;\n"
-  "\n";
-static const GLchar *blend_vertex_shader_main =
-  "void main (void)\n"
-  "{\n"
-  "  gl_Position = vec4(VertexP,0.0f,1.0f);\n"
-  "  TexCoord = VertexT;\n"
-  "}\n";
-
-/* The fragment shader code is composed of code fragments that depend on
-   the OpenGL version and code fragments that are version-independent.
-   They are concatenated by glsl_CompileAndLinkShaders in the function
-   init_glsl(). */
-static const GLchar *blend_fragment_shader_attribs_2_1 =
-  "varying vec2 TexCoord;\n"
-  "\n";
-static const GLchar *blend_fragment_shader_attribs_3_0 =
-  "in vec2 TexCoord;\n"
-  "\n"
-  "out vec4 FragColor;\n"
-  "\n";
-static const GLchar *blend_fragment_shader_main =
-  "uniform sampler2D TextureSampler0;"
-  "uniform sampler2D TextureSampler1;"
-  "uniform float T;"
-  "\n"
-  "void main (void)\n"
-  "{\n";
-static const GLchar *blend_fragment_shader_out_2_1 =
-  "  vec3 Color0 = texture2D(TextureSampler0,TexCoord.st).rgb;\n"
-  "  vec3 Color1 = texture2D(TextureSampler1,TexCoord.st).rgb;\n"
-  "  gl_FragColor = vec4(T*Color0+(1.0f-T)*Color1,1.0f);\n"
-  "}\n";
-static const GLchar *blend_fragment_shader_out_3_0 =
-  "  vec3 Color0 = texture(TextureSampler0,TexCoord.st).rgb;\n"
-  "  vec3 Color1 = texture(TextureSampler1,TexCoord.st).rgb;\n"
-  "  FragColor = vec4(T*Color0+(1.0f-T)*Color1,1.0f);\n"
-  "}\n";
+/* The polygon vertex shader code. */
+static const GLchar *poly_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+attribute vec3 VertexNormal;                                             \n\
+attribute vec4 VertexColorF;                                             \n\
+attribute vec4 VertexColorB;                                             \n\
+attribute vec4 VertexTexCoord;                                           \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+in vec3 VertexNormal;                                                    \n\
+in vec4 VertexColorF;                                                    \n\
+in vec4 VertexColorB;                                                    \n\
+in vec4 VertexTexCoord;                                                  \n\
+out vec3 Normal;                                                         \n\
+out vec4 ColorF;                                                         \n\
+out vec4 ColorB;                                                         \n\
+out vec4 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+uniform bool BoolTextures;                                               \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  ColorF = VertexColorF;                                                 \n\
+  ColorB = VertexColorB;                                                 \n\
+  Normal = normalize(MatModelView*vec4(VertexNormal,0.0f)).xyz;          \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+  if (BoolTextures)                                                      \n\
+    TexCoord = VertexTexCoord;                                           \n\
+}                                                                        \n";
+
+/* The polygon fragment shader code. */
+static const GLchar *poly_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec3 Normal;                                                     \n\
+varying vec4 ColorF;                                                     \n\
+varying vec4 ColorB;                                                     \n\
+varying vec4 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec3 Normal;                                                          \n\
+in vec4 ColorF;                                                          \n\
+in vec4 ColorB;                                                          \n\
+in vec4 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform vec4 LtGlblAmbient;                                              \n\
+uniform vec4 LtAmbient, LtDiffuse, LtSpecular;                           \n\
+uniform vec3 LtDirection, LtHalfVector;                                  \n\
+uniform vec4 MatFrontAmbient, MatBackAmbient;                            \n\
+uniform vec4 MatFrontDiffuse, MatBackDiffuse;                            \n\
+uniform vec4 MatSpecular;                                                \n\
+uniform float MatShininess;                                              \n\
+uniform bool BoolTextures;                                               \n\
+uniform sampler2D TextureSamplerFront;                                   \n\
+uniform sampler2D TextureSamplerBack;                                    \n\
+uniform sampler2D TextureSamplerWater;                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec3 normalDirection;                                                  \n\
+  vec4 ambientColor, diffuseColor, sceneColor;                           \n\
+  vec4 ambientLighting, diffuseReflection, specularReflection, color;    \n\
+  float ndotl, ndoth, pf;                                                \n\
+                                                                         \n\
+  if (gl_FrontFacing)                                                    \n\
+  {                                                                      \n\
+    normalDirection = normalize(Normal);                                 \n\
+    sceneColor = ColorF*MatFrontAmbient*LtGlblAmbient;                   \n\
+    ambientColor = ColorF*MatFrontAmbient;                               \n\
+    diffuseColor = ColorF*MatFrontDiffuse;                               \n\
+  }                                                                      \n\
+  else                                                                   \n\
+  {                                                                      \n\
+    normalDirection = -normalize(Normal);                                \n\
+    sceneColor = ColorB*MatBackAmbient*LtGlblAmbient;                    \n\
+    ambientColor = ColorB*MatBackAmbient;                                \n\
+    diffuseColor = ColorB*MatBackDiffuse;                                \n\
+  }                                                                      \n\
+                                                                         \n\
+  ndotl = max(0.0f,dot(normalDirection,LtDirection));                    \n\
+  ndoth = max(0.0f,dot(normalDirection,LtHalfVector));                   \n\
+  if (ndotl == 0.0f)                                                     \n\
+    pf = 0.0f;                                                           \n\
+  else                                                                   \n\
+    pf = pow(ndoth,MatShininess);                                        \n\
+  ambientLighting = ambientColor*LtAmbient;                              \n\
+  diffuseReflection = LtDiffuse*diffuseColor*ndotl;                      \n\
+  specularReflection = LtSpecular*MatSpecular*pf;                        \n\
+  color = sceneColor+ambientLighting+diffuseReflection;                  \n\
+  if (BoolTextures)                                                      \n\
+  {                                                                      \n\
+    if (gl_FrontFacing)                                                  \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSamplerFront,TexCoord.st);               \n\
+      specularReflection *= texture2D(TextureSamplerWater,TexCoord.st);  \n\
+#else                                                                    \n\
+      color *= texture(TextureSamplerFront,TexCoord.st);                 \n\
+      specularReflection *= texture(TextureSamplerWater,TexCoord.st);    \n\
+#endif                                                                   \n\
+    }                                                                    \n\
+    else                                                                 \n\
+    {                                                                    \n\
+#if __VERSION__ <= 120                                                   \n\
+      color *= texture2D(TextureSamplerBack,TexCoord.st);                \n\
+#else                                                                    \n\
+      color *= texture(TextureSamplerBack,TexCoord.st);                  \n\
+#endif                                                                   \n\
+      specularReflection *= 0.0f;                                        \n\
+    }                                                                    \n\
+  }                                                                      \n\
+  color += specularReflection;                                           \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = clamp(color,0.0f,1.0f);                                 \n\
+  gl_FragColor.a = diffuseColor.a;                                       \n\
+#else                                                                    \n\
+  FragColor = clamp(color,0.0f,1.0f);                                    \n\
+  FragColor.a = diffuseColor.a;                                          \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+/* The line vertex shader code. */
+static const GLchar *line_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec3 VertexPosition;                                           \n\
+#else                                                                    \n\
+in vec3 VertexPosition;                                                  \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform mat4 MatModelView;                                               \n\
+uniform mat4 MatProj;                                                    \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  vec4 Position = MatModelView*vec4(VertexPosition,1.0f);                \n\
+  gl_Position = MatProj*Position;                                        \n\
+}                                                                        \n";
+
+/* The line fragment shader code. */
+static const GLchar *line_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ >= 130                                                   \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform vec4 LineColor;                                                  \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = LineColor;                                              \n\
+#else                                                                    \n\
+  FragColor = LineColor;                                                 \n\
+#endif                                                                   \n\
+}                                                                        \n";
+
+/* The blend vertex shader code. */
+static const GLchar *blend_vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec2 VertexP;                                                  \n\
+attribute vec2 VertexT;                                                  \n\
+varying vec2 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec2 VertexP;                                                         \n\
+in vec2 VertexT;                                                         \n\
+out vec2 TexCoord;                                                       \n\
+#endif                                                                   \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  gl_Position = vec4(VertexP,0.0f,1.0f);                                 \n\
+  TexCoord = VertexT;                                                    \n\
+}                                                                        \n";
+
+/* The blend fragment shader code. */
+static const GLchar *blend_fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec2 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec2 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+                                                                         \n\
+uniform sampler2D TextureSampler0;                                       \n\
+uniform sampler2D TextureSampler1;                                       \n\
+uniform float T;                                                         \n\
+                                                                         \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+#if __VERSION__ <= 120                                                   \n\
+  vec3 Color0 = texture2D(TextureSampler0,TexCoord.st).rgb;              \n\
+  vec3 Color1 = texture2D(TextureSampler1,TexCoord.st).rgb;              \n\
+  gl_FragColor = vec4(T*Color0+(1.0f-T)*Color1,1.0f);                    \n\
+#else                                                                    \n\
+  vec3 Color0 = texture(TextureSampler0,TexCoord.st).rgb;                \n\
+  vec3 Color1 = texture(TextureSampler1,TexCoord.st).rgb;                \n\
+  FragColor = vec4(T*Color0+(1.0f-T)*Color1,1.0f);                       \n\
+#endif                                                                   \n\
+}                                                                        \n";
 
 #endif /* HAVE_GLSL */
 
@@ -694,23 +692,95 @@ void gen_textures(ModeInfo *mi)
 }
 
 
+/* Delete the framebuffer objects that are used for blending. */
+static void delete_blend_framebuffer_objects(ModeInfo *mi)
+{
+  sphereeversionstruct *se = &sphereeversion[MI_SCREEN(mi)];
+
+  if (se->use_fbo)
+  {
+    glDeleteFramebuffers(2,se->blend_fbo);
+    glDeleteTextures(2,se->blend_depth_tex);
+    glDeleteTextures(2,se->blend_color_tex);
+  }
+}
+
+
+/* Initialize the framebuffer objects that are used for blending. */
+static void init_blend_framebuffer_objects(ModeInfo *mi)
+{
+  sphereeversionstruct *se = &sphereeversion[MI_SCREEN(mi)];
+  GLenum status;
+  Bool all_fbo_complete = True;
+  int i;
+
+  if (se->use_fbo)
+  {
+    glGenFramebuffers(2,se->blend_fbo);
+    glGenTextures(2,se->blend_depth_tex);
+    glGenTextures(2,se->blend_color_tex);
+
+    for (i=0; i<2; i++)
+    {
+      glBindTexture(GL_TEXTURE_2D,se->blend_depth_tex[i]);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+      glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT24,se->WindW,se->WindH,
+                   0,GL_DEPTH_COMPONENT,GL_UNSIGNED_INT,0);
+      
+      glBindTexture(GL_TEXTURE_2D,se->blend_color_tex[i]);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
+      glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
+      glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,se->WindW,se->WindH,0,GL_RGBA,
+                   GL_UNSIGNED_BYTE,0);
+      
+      glBindFramebuffer(GL_FRAMEBUFFER,se->blend_fbo[i]);
+      glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,
+                             GL_TEXTURE_2D,se->blend_depth_tex[i],0);
+      glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,
+                             GL_TEXTURE_2D,se->blend_color_tex[i],0);
+      status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+      if (status != GL_FRAMEBUFFER_COMPLETE)
+        all_fbo_complete = False;
+    }
+
+    glBindTexture(GL_TEXTURE_2D,0);
+    glBindFramebuffer(GL_DRAW_FRAMEBUFFER,se->default_draw_fbo);
+    glBindFramebuffer(GL_READ_FRAMEBUFFER,se->default_read_fbo);
+
+    if (!all_fbo_complete)
+    {
+      delete_blend_framebuffer_objects(mi);
+      se->use_fbo = False;
+    }
+  }
+}
+
+
 void init_glsl(ModeInfo *mi)
 {
   sphereeversionstruct *se = &sphereeversion[MI_SCREEN(mi)];
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
+  const char *gl_ext;
   int i, wt, ht;
-  const GLchar *poly_vertex_shader_source[3];
-  const GLchar *poly_fragment_shader_source[4];
-  const GLchar *line_vertex_shader_source[3];
-  const GLchar *line_fragment_shader_source[4];
-  const GLchar *blend_vertex_shader_source[3];
-  const GLchar *blend_fragment_shader_source[4];
+  const GLchar *poly_vertex_shader_source[2];
+  const GLchar *poly_fragment_shader_source[2];
+  const GLchar *line_vertex_shader_source[2];
+  const GLchar *line_fragment_shader_source[2];
+  const GLchar *blend_vertex_shader_source[2];
+  const GLchar *blend_fragment_shader_source[2];
 
   /* Determine whether to use shaders to render the sphere eversion. */
   se->use_shaders = False;
   se->use_mipmaps = False;
   se->buffers_initialized = False;
+  se->use_vao = False;
+  se->use_fbo = False;
   se->poly_shader_program = 0;
   se->line_shader_program = 0;
   se->blend_shader_program = 0;
@@ -719,99 +789,24 @@ void init_glsl(ModeInfo *mi)
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
     return;
-  if (!gl_gles3)
-  {
-    if (gl_major < 3 ||
-        (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-    {
-      if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-        return;
-      /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-      poly_vertex_shader_source[0] = shader_version_2_1;
-      poly_vertex_shader_source[1] = poly_vertex_shader_attribs_2_1;
-      poly_vertex_shader_source[2] = poly_vertex_shader_main;
-      poly_fragment_shader_source[0] = shader_version_2_1;
-      poly_fragment_shader_source[1] = poly_fragment_shader_attribs_2_1;
-      poly_fragment_shader_source[2] = poly_fragment_shader_main;
-      poly_fragment_shader_source[3] = poly_fragment_shader_out_2_1;
-
-      line_vertex_shader_source[0] = shader_version_2_1;
-      line_vertex_shader_source[1] = line_vertex_shader_attribs_2_1;
-      line_vertex_shader_source[2] = line_vertex_shader_main;
-      line_fragment_shader_source[0] = shader_version_2_1;
-      line_fragment_shader_source[1] = line_fragment_shader_attribs_2_1;
-      line_fragment_shader_source[2] = line_fragment_shader_main;
-      line_fragment_shader_source[3] = line_fragment_shader_out_2_1;
-
-      blend_vertex_shader_source[0] = shader_version_2_1;
-      blend_vertex_shader_source[1] = blend_vertex_shader_attribs_2_1;
-      blend_vertex_shader_source[2] = blend_vertex_shader_main;
-      blend_fragment_shader_source[0] = shader_version_2_1;
-      blend_fragment_shader_source[1] = blend_fragment_shader_attribs_2_1;
-      blend_fragment_shader_source[2] = blend_fragment_shader_main;
-      blend_fragment_shader_source[3] = blend_fragment_shader_out_2_1;
-    }
-    else
-    {
-      /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-      poly_vertex_shader_source[0] = shader_version_3_0;
-      poly_vertex_shader_source[1] = poly_vertex_shader_attribs_3_0;
-      poly_vertex_shader_source[2] = poly_vertex_shader_main;
-      poly_fragment_shader_source[0] = shader_version_3_0;
-      poly_fragment_shader_source[1] = poly_fragment_shader_attribs_3_0;
-      poly_fragment_shader_source[2] = poly_fragment_shader_main;
-      poly_fragment_shader_source[3] = poly_fragment_shader_out_3_0;
-
-      line_vertex_shader_source[0] = shader_version_3_0;
-      line_vertex_shader_source[1] = line_vertex_shader_attribs_3_0;
-      line_vertex_shader_source[2] = line_vertex_shader_main;
-      line_fragment_shader_source[0] = shader_version_3_0;
-      line_fragment_shader_source[1] = line_fragment_shader_attribs_3_0;
-      line_fragment_shader_source[2] = line_fragment_shader_main;
-      line_fragment_shader_source[3] = line_fragment_shader_out_3_0;
-
-      blend_vertex_shader_source[0] = shader_version_3_0;
-      blend_vertex_shader_source[1] = blend_vertex_shader_attribs_3_0;
-      blend_vertex_shader_source[2] = blend_vertex_shader_main;
-      blend_fragment_shader_source[0] = shader_version_3_0;
-      blend_fragment_shader_source[1] = blend_fragment_shader_attribs_3_0;
-      blend_fragment_shader_source[2] = blend_fragment_shader_main;
-      blend_fragment_shader_source[3] = blend_fragment_shader_out_3_0;
-    }
-  }
-  else /* gl_gles3 */
-  {
-    if (gl_major < 3 || glsl_major < 3)
-      return;
-    /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-    poly_vertex_shader_source[0] = shader_version_3_0_es;
-    poly_vertex_shader_source[1] = poly_vertex_shader_attribs_3_0;
-    poly_vertex_shader_source[2] = poly_vertex_shader_main;
-    poly_fragment_shader_source[0] = shader_version_3_0_es;
-    poly_fragment_shader_source[1] = poly_fragment_shader_attribs_3_0;
-    poly_fragment_shader_source[2] = poly_fragment_shader_main;
-    poly_fragment_shader_source[3] = poly_fragment_shader_out_3_0;
-
-    line_vertex_shader_source[0] = shader_version_3_0_es;
-    line_vertex_shader_source[1] = line_vertex_shader_attribs_3_0;
-    line_vertex_shader_source[2] = line_vertex_shader_main;
-    line_fragment_shader_source[0] = shader_version_3_0_es;
-    line_fragment_shader_source[1] = line_fragment_shader_attribs_3_0;
-    line_fragment_shader_source[2] = line_fragment_shader_main;
-    line_fragment_shader_source[3] = line_fragment_shader_out_3_0;
-
-    blend_vertex_shader_source[0] = shader_version_3_0_es;
-    blend_vertex_shader_source[1] = blend_vertex_shader_attribs_3_0;
-    blend_vertex_shader_source[2] = blend_vertex_shader_main;
-    blend_fragment_shader_source[0] = shader_version_3_0_es;
-    blend_fragment_shader_source[1] = blend_fragment_shader_attribs_3_0;
-    blend_fragment_shader_source[2] = blend_fragment_shader_main;
-    blend_fragment_shader_source[3] = blend_fragment_shader_out_3_0;
-  }
 
-  if (!glsl_CompileAndLinkShaders(3,poly_vertex_shader_source,
-                                  4,poly_fragment_shader_source,
+  poly_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  poly_vertex_shader_source[1] = poly_vertex_shader;
+  poly_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  poly_fragment_shader_source[1] = poly_fragment_shader;
+
+  line_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  line_vertex_shader_source[1] = line_vertex_shader;
+  line_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  line_fragment_shader_source[1] = line_fragment_shader;
+
+  blend_vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  blend_vertex_shader_source[1] = blend_vertex_shader;
+  blend_fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  blend_fragment_shader_source[1] = blend_fragment_shader;
+
+  if (!glsl_CompileAndLinkShaders(2,poly_vertex_shader_source,
+                                  2,poly_fragment_shader_source,
                                   &se->poly_shader_program))
     return;
   se->poly_pos_index = glGetAttribLocation(se->poly_shader_program,
@@ -888,8 +883,8 @@ void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!glsl_CompileAndLinkShaders(3,line_vertex_shader_source,
-                                  4,line_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,line_vertex_shader_source,
+                                  2,line_fragment_shader_source,
                                   &se->line_shader_program))
   {
     glDeleteProgram(se->poly_shader_program);
@@ -913,8 +908,8 @@ void init_glsl(ModeInfo *mi)
     return;
   }
 
-  if (!glsl_CompileAndLinkShaders(3,blend_vertex_shader_source,
-                                  4,blend_fragment_shader_source,
+  if (!glsl_CompileAndLinkShaders(2,blend_vertex_shader_source,
+                                  2,blend_fragment_shader_source,
                                   &se->blend_shader_program))
   {
     glDeleteProgram(se->poly_shader_program);
@@ -976,6 +971,33 @@ void init_glsl(ModeInfo *mi)
   glGenBuffers(1,&se->parallel_indices_buffer);
   glGenBuffers(1,&se->meridian_indices_buffer);
   glGenBuffers(1,&se->line_indices_buffer);
+  glGenBuffers(1,&se->blend_pos_buffer);
+  glGenBuffers(1,&se->blend_tex_coord_buffer);
+  glGenBuffers(1,&se->blend_indices_buffer);
+
+  se->use_vao = glsl_IsCoreProfile();
+  if (se->use_vao)
+    glGenVertexArrays(1,&se->vertex_array_object);
+
+  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING,(GLint *)&se->default_draw_fbo);
+  glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING,(GLint *)&se->default_read_fbo);
+
+  if (!gl_gles3 && gl_major < 3)
+  {
+    /* On OpenGL 2.1 systems, we need the GL_ARB_framebuffer_object
+       extension for the more efficient blending mode. */
+    gl_ext = (const char *)glGetString(GL_EXTENSIONS);
+    if (gl_ext != NULL)
+    {
+      if (strstr(gl_ext,"GL_ARB_framebuffer_object") != NULL)
+        se->use_fbo = True;
+    }
+  }
+  else
+  {
+    se->use_fbo = True;
+  }
+  init_blend_framebuffer_objects(mi);
 
   se->use_shaders = True;
   if ((!gl_gles3 && gl_major >= 3) || gl_gles3)
@@ -1031,6 +1053,9 @@ ENTRYPOINT void reshape_sphereeversion(ModeInfo *mi, int width, int height)
                    NULL);
     }
   }
+
+  delete_blend_framebuffer_objects(mi);
+  init_blend_framebuffer_objects(mi);
 #endif /* HAVE_GLSL */
 }
 
@@ -1380,6 +1405,12 @@ ENTRYPOINT void free_sphereeversion(ModeInfo *mi)
     glDeleteBuffers(1,&se->parallel_indices_buffer);
     glDeleteBuffers(1,&se->meridian_indices_buffer);
     glDeleteBuffers(1,&se->line_indices_buffer);
+    glDeleteBuffers(1,&se->blend_pos_buffer);
+    glDeleteBuffers(1,&se->blend_tex_coord_buffer);
+    glDeleteBuffers(1,&se->blend_indices_buffer);
+    if (se->use_vao)
+      glDeleteVertexArrays(1,&se->vertex_array_object);
+    delete_blend_framebuffer_objects(mi);
   }
 #endif /* HAVE_GLSL */
 }
index 8259d33034edc14a202988781265a87a08e42eeb..0141e2bd1860388b2b7c28ecb7f87c992d5927fd 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (c) 2021-2022 Carsten Steger <carsten@mirsanmir.org>. */
+/* Copyright (c) 2021-2026 Carsten Steger <carsten@mirsanmir.org>. */
 
 /*
  * Permission to use, copy, modify, and distribute this software and its
  * other special, indirect and consequential damages.
  */
 
-/* This header makes outsidein be a mode of sphereeversion rather than
-   a standalone hack, since they are so similar in effect (if not
-   implementation).
- */
-
 #ifndef __SPHEREEVERSION_H__
 #define __SPHEREEVERSION_H__
 
@@ -62,7 +57,7 @@
 #define ANIM_TURN   1
 
 /* Angle of a single turn step */
-#define TURN_STEP 1.0
+#define TURN_STEP 0.5
 
 
 #ifdef USE_GL
@@ -131,7 +126,7 @@ typedef struct {
   /* Indices for uniform variables and attributes */
   GLuint *solid_indices, *parallel_indices;
   GLuint *meridian_indices, *line_indices;
-  Bool use_shaders, use_mipmaps, buffers_initialized;
+  Bool use_shaders, use_mipmaps, buffers_initialized, use_vao, use_fbo;
   GLuint poly_shader_program;
   GLint poly_pos_index, poly_normal_index;
   GLint poly_colorf_index, poly_colorb_index, poly_vertex_tex_index;
@@ -157,6 +152,11 @@ typedef struct {
   GLuint vertex_tex_coord_buffer;
   GLuint solid_indices_buffer, parallel_indices_buffer;
   GLuint meridian_indices_buffer, line_indices_buffer;
+  GLuint blend_pos_buffer, blend_tex_coord_buffer;
+  GLuint blend_indices_buffer;
+  GLuint blend_fbo[2], blend_depth_tex[2], blend_color_tex[2];
+  GLuint default_draw_fbo, default_read_fbo;
+  GLuint vertex_array_object;
   GLint num_solid_strips, num_solid_triangles;
   GLint num_parallel_strips, num_parallel_triangles;
   GLint num_meridian_strips, num_meridian_triangles;
diff --git a/hacks/glx/stardome.man b/hacks/glx/stardome.man
new file mode 100644 (file)
index 0000000..0e8594b
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+stardome \- screen saver.
+.SH SYNOPSIS
+.B stardome
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Stars and a galaxy under a dome on a moon.
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/stBcW1
+.SH COPYRIGHT
+Copyright \(co 2022 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
diff --git a/hacks/glx/starnest.man b/hacks/glx/starnest.man
new file mode 100644 (file)
index 0000000..de3c5e7
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+starnest \- star field screen saver.
+.SH SYNOPSIS
+.B starnest
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+A star field via 3D kaliset fractal and volumetric rendering.
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/XlfGRj
+.SH COPYRIGHT
+Copyright \(co 2013 by Pablo Roman Andrioli.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Pablo Roman Andrioli.
diff --git a/hacks/glx/stripeytorus.man b/hacks/glx/stripeytorus.man
new file mode 100644 (file)
index 0000000..044b1b8
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+stripeytorus \- torus screen saver.
+.SH SYNOPSIS
+.B stripeytorus
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+The stylish interior of a torus. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/fd33zn
+.SH COPYRIGHT
+Copyright \(co 2021 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
diff --git a/hacks/glx/synthwavecity.man b/hacks/glx/synthwavecity.man
new file mode 100644 (file)
index 0000000..d4bf942
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+synthwavecity \- screen saver.
+.SH SYNOPSIS
+.B synthwavecity
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Let the neon wash over you. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/7lKyDD
+.SH COPYRIGHT
+Copyright \(co 2019 by Jan Mróz and 3w36zj6.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jan Mróz and 3w36zj6.
index 43a4d64aacd73bb4cc1ea94045f3e1b155f853ad..f0ffeb81d743fcd72bb72ce83eca9a6ed6267a34 100644 (file)
@@ -1,4 +1,4 @@
-/* texfont, Copyright © 2005-2025 Jamie Zawinski <jwz@jwz.org>
+/* texfont, Copyright © 2005-2026 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 # include "glsl-utils.h"
 #endif /* HAVE_GLSL */
 
+/* OpenGLES doesn't support GL_INTENSITY, so instead of using a
+   texture with 1 byte per pixel, the intensity value, we have
+   to use 2 bytes per pixel: solid white, and an alpha value.
+ */
+#ifdef HAVE_JWZGLES
+# undef GL_INTENSITY
+#endif
+
+
 #undef HAVE_XSHM_EXTENSION  /* doesn't actually do any good here */
 
 extern void clear_gl_error (void);             /* xlock-gl.c */
@@ -43,58 +52,64 @@ extern float jwxyz_font_scale (Window);             /* jwxyz-cocoa.m */
 /* Shader programs for rendering text textures when the caller is using
    GLSL and the GLES 3.x API rather than the OpenGL 3.1 or GLES 1.x APIs.
  */
-static const GLchar *shader_version_2_1 = "#version 120\n";
-static const GLchar *shader_version_3_0 = "#version 130\n";
-static const GLchar *shader_version_3_0_es = "#version 300 es          \n\
-   precision highp float;                                              \n\
-   precision highp int;                                                        \n\
-";
-static const GLchar *vertex_shader_attribs_2_1 = "\
-   attribute vec2 VertexCoord;                                         \n\
-   attribute vec2 VertexTex;                                           \n\
-   varying vec2 TexCoord;                                              \n\
-   varying vec4 Color;                                                 \n\
-";
-static const GLchar *vertex_shader_attribs_3_0 = "\
-   in vec2 VertexCoord;                                                        \n\
-   in vec2 VertexTex;                                                  \n\
-   out vec2 TexCoord;                                                  \n\
-   out vec4 Color;                                                     \n\
-";
-static const GLchar *vertex_shader_main = "\
-   uniform mat4 ProjMat;                                               \n\
-   uniform vec4 FontColor;                                             \n\
-   void main (void)                                                    \n\
-   {                                                                   \n\
-     gl_Position = ProjMat*vec4 (VertexCoord, 0, 1);                   \n\
-     TexCoord = VertexTex;                                             \n\
-     Color = FontColor;                                                        \n\
-   }                                                                   \n\
-";
-static const GLchar *fragment_shader_attribs_2_1 = "\
-   varying vec4 Color;                                                 \n\
-   varying vec2 TexCoord;                                              \n\
-";
-static const GLchar *fragment_shader_attribs_3_0 = "\
-   in vec4 Color;                                                      \n\
-   in vec2 TexCoord;                                                   \n\
-   out vec4 FragColor;                                                 \n\
-";
-static const GLchar *fragment_shader_main = "\
-   uniform sampler2D TexSampler;                                       \n\
-   void main (void)                                                    \n\
-   {                                                                   \n\
-     const float MinAlpha = 0.01;                                      \n\
-     const float LODBias = 0.25;                                       \n\
-     if (Color.a <= MinAlpha)                                          \n\
-       discard;                                                                \n\
-";
-static const GLchar *fragment_shader_out_2_1 = "\
-     gl_FragColor = Color*texture2D (TexSampler, TexCoord.st, LODBias); \n\
-   }\n";
-static const GLchar *fragment_shader_out_3_0 = "\
-     FragColor = Color*texture (TexSampler, TexCoord.st, LODBias);     \n\
-   }\n";
+static const GLchar *vertex_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+attribute vec2 VertexCoord;                                              \n\
+attribute vec2 VertexTex;                                                \n\
+varying vec2 TexCoord;                                                   \n\
+varying vec4 Color;                                                      \n\
+#else                                                                    \n\
+in vec2 VertexCoord;                                                     \n\
+in vec2 VertexTex;                                                       \n\
+out vec2 TexCoord;                                                       \n\
+out vec4 Color;                                                          \n\
+#endif                                                                   \n\
+uniform mat4 ProjMat;                                                    \n\
+uniform vec4 FontColor;                                                  \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  gl_Position = ProjMat*vec4(VertexCoord,0.0,1.0);                       \n\
+  TexCoord = VertexTex;                                                  \n\
+  Color = FontColor;                                                     \n\
+}                                                                        \n";
+static const GLchar *fragment_shader = "\
+#ifdef GL_ES                                                             \n\
+precision highp float;                                                   \n\
+precision highp int;                                                     \n\
+precision highp sampler2D;                                               \n\
+#endif                                                                   \n\
+                                                                         \n\
+#if __VERSION__ <= 120                                                   \n\
+varying vec4 Color;                                                      \n\
+varying vec2 TexCoord;                                                   \n\
+#else                                                                    \n\
+in vec4 Color;                                                           \n\
+in vec2 TexCoord;                                                        \n\
+out vec4 FragColor;                                                      \n\
+#endif                                                                   \n\
+uniform sampler2D TexSampler;                                            \n\
+void main(void)                                                          \n\
+{                                                                        \n\
+  const float MinAlpha = 0.01;                                           \n\
+  const float LODBias = 0.25;                                            \n\
+  if (Color.a <= MinAlpha)                                               \n\
+    discard;                                                             \n\
+#if __VERSION__ <= 120                                                   \n\
+  gl_FragColor = Color*texture2D(TexSampler,TexCoord.st,LODBias).rrrr;   \n\
+#else                                                                    \n\
+#ifdef GL_ES                                                             \n\
+  FragColor = Color*texture(TexSampler,TexCoord.st,LODBias).rrrg;        \n\
+#else                                                                    \n\
+  FragColor = Color*texture(TexSampler,TexCoord.st,LODBias).rrrr;        \n\
+#endif                                                                   \n\
+#endif                                                                   \n\
+}                                                                        \n";
 #endif /* HAVE_GLSL */
 
 
@@ -118,8 +133,11 @@ struct texture_font_data {
   Bool dropshadow_p;
   Bool mipmap_p;
 # ifdef HAVE_GLSL
-  Bool shaders_initialized, use_shaders;
+  Bool shaders_initialized, use_shaders, use_vao;
   GLuint shader_program;
+  GLuint vertex_array_object;
+  GLuint vertex_coord_buffer, vertex_tex_buffer;
+  GLuint indices_buffer;
   GLint vertex_coord_index, vertex_tex_index;
   GLint proj_mat_index, font_color_index, tex_sampler_index;
 # endif /* HAVE_GLSL */
@@ -152,14 +170,6 @@ bitmap_to_texture (const texture_font_data *tfdata, Pixmap p,
   GLint alignment = 0;
 # endif /* HAVE_IPHONE */
 
-  /* OpenGLES doesn't support GL_INTENSITY, so instead of using a
-     texture with 1 byte per pixel, the intensity value, we have
-     to use 2 bytes per pixel: solid white, and an alpha value.
-   */
-# ifdef HAVE_JWZGLES
-#  undef GL_INTENSITY
-# endif
-
 # ifdef HAVE_XSHM_EXTENSION
   Bool use_shm = get_boolean_resource (dpy, "useSHM", "Boolean");
   XShmSegmentInfo shm_info;
@@ -272,25 +282,34 @@ bitmap_to_texture (const texture_font_data *tfdata, Pixmap p,
 # endif /* HAVE_IPHONE */
 
   {
-# ifdef GL_INTENSITY
-    GLuint iformat = GL_INTENSITY;
-    GLuint format  = GL_LUMINANCE;
-# else
-    GLuint iformat = GL_LUMINANCE_ALPHA;
-    GLuint format  = GL_LUMINANCE_ALPHA;
-# endif
-    GLuint type    = GL_UNSIGNED_BYTE;
-
-#ifdef HAVE_GLSL
+# ifdef HAVE_GLSL
     if (tfdata->use_shaders)
       {
+#  ifdef GL_INTENSITY
+        GLuint iformat = GL_R8;
+        GLuint format  = GL_RED;
+#  else
+        GLuint iformat = GL_RG8;
+        GLuint format  = GL_RG;
+#  endif
+        GLuint type    = GL_UNSIGNED_BYTE;
+
         glTexImage2D (GL_TEXTURE_2D, 0, iformat, w2, h2, 0, format,
                       type, data);
         glGenerateMipmap (GL_TEXTURE_2D);
       }
     else
-#endif /* HAVE_GLSL */
+# endif /* HAVE_GLSL */
       {
+# ifdef GL_INTENSITY
+        GLuint iformat = GL_INTENSITY;
+        GLuint format  = GL_LUMINANCE;
+# else
+        GLuint iformat = GL_LUMINANCE_ALPHA;
+        GLuint format  = GL_LUMINANCE_ALPHA;
+# endif
+        GLuint type    = GL_UNSIGNED_BYTE;
+
         if (tfdata->mipmap_p)
           gluBuild2DMipmaps (GL_TEXTURE_2D, iformat, w2, h2, format, 
                              type, data);
@@ -415,7 +434,9 @@ load_texture_font (Display *dpy, char *res)
      first. */
   data->shaders_initialized = False;
   data->use_shaders = False;
+  data->use_vao = False;
   data->shader_program = 0;
+  data->vertex_array_object = 0;
   data->vertex_coord_index = -1;
   data->vertex_tex_index = -1;
   data->proj_mat_index = -1;
@@ -934,28 +955,42 @@ print_texture_string (texture_font_data *data, const char *string)
         v[2][0] = qx1; v[2][1] = qy1; t[2][0] = tx1; t[2][1] = ty1;
         v[3][0] = qx0; v[3][1] = qy1; t[3][0] = tx0; t[3][1] = ty1;
 
+        if (data->use_vao)
+          glBindVertexArray (data->vertex_array_object);
+
         glEnableVertexAttribArray (data->vertex_coord_index);
-        glVertexAttribPointer (data->vertex_coord_index, 2, GL_FLOAT, GL_FALSE,
-                               2 * sizeof(GLfloat), v);
+        glBindBuffer (GL_ARRAY_BUFFER, data->vertex_coord_buffer);
+        glBufferData (GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
+        glVertexAttribPointer (data->vertex_coord_index, 2, GL_FLOAT,
+                               GL_FALSE, 0, 0);
 
         glEnableVertexAttribArray (data->vertex_tex_index);
-        glVertexAttribPointer (data->vertex_tex_index, 2, GL_FLOAT, GL_FALSE,
-                               2 * sizeof(GLfloat), t);
+        glBindBuffer (GL_ARRAY_BUFFER, data->vertex_tex_buffer);
+        glBufferData (GL_ARRAY_BUFFER, sizeof(t), t, GL_STATIC_DRAW);
+        glVertexAttribPointer(data->vertex_tex_index, 2, GL_FLOAT,
+                              GL_FALSE, 0, 0);
+
+        glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, data->indices_buffer);
+        glBufferData (GL_ELEMENT_ARRAY_BUFFER, 6*sizeof(GLuint),
+                      indices, GL_STATIC_DRAW);
 
         glEnable (GL_CULL_FACE);
         glFrontFace (GL_CCW);
-        glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, indices);
+        glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
 
         if (draw_back_face_p)
           {
             glFrontFace (GL_CW);
-            glDrawElements (GL_TRIANGLE_STRIP, 2, GL_UNSIGNED_INT, indices);
+            glDrawElements (GL_TRIANGLE_STRIP, 2, GL_UNSIGNED_INT, 0);
           }
 
         glDisableVertexAttribArray (data->vertex_coord_index);
         glDisableVertexAttribArray (data->vertex_tex_index);
 
-        glDisable(GL_CULL_FACE);
+        if (data->use_vao)
+          glBindVertexArray (0);
+
+        glDisable (GL_CULL_FACE);
       }
     else
 # endif /* HAVE_GLSL */
@@ -1035,10 +1070,12 @@ initialize_textfont_shaders_glsl (texture_font_data *data)
 {
   GLint gl_major, gl_minor, glsl_major, glsl_minor;
   GLboolean gl_gles3;
-  const GLchar *vertex_shader_source[3];
-  const GLchar *fragment_shader_source[4];
+  const GLchar *vertex_shader_source[2];
+  const GLchar *fragment_shader_source[2];
 
   data->use_shaders = False;
+  data->use_vao = False;
+  data->vertex_array_object = 0;
 
   if (!glsl_GetGlAndGlslVersions(&gl_major,&gl_minor,&glsl_major,&glsl_minor,
                                  &gl_gles3))
@@ -1047,56 +1084,12 @@ initialize_textfont_shaders_glsl (texture_font_data *data)
       return;
     }
 
-  if (!gl_gles3)
-    {
-      if (gl_major < 3 ||
-          (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 30)))
-        {
-          if ((gl_major < 2 || (gl_major == 2 && gl_minor < 1)) ||
-              (glsl_major < 1 || (glsl_major == 1 && glsl_minor < 20)))
-            {
-              data->shaders_initialized = True;
-              return;
-            }
-          /* We have at least OpenGL 2.1 and at least GLSL 1.20. */
-          vertex_shader_source[0] = shader_version_2_1;
-          vertex_shader_source[1] = vertex_shader_attribs_2_1;
-          vertex_shader_source[2] = vertex_shader_main;
-          fragment_shader_source[0] = shader_version_2_1;
-          fragment_shader_source[1] = fragment_shader_attribs_2_1;
-          fragment_shader_source[2] = fragment_shader_main;
-          fragment_shader_source[3] = fragment_shader_out_2_1;
-        }
-      else
-        {
-          /* We have at least OpenGL 3.0 and at least GLSL 1.30. */
-          vertex_shader_source[0] = shader_version_3_0;
-          vertex_shader_source[1] = vertex_shader_attribs_3_0;
-          vertex_shader_source[2] = vertex_shader_main;
-          fragment_shader_source[0] = shader_version_3_0;
-          fragment_shader_source[1] = fragment_shader_attribs_3_0;
-          fragment_shader_source[2] = fragment_shader_main;
-          fragment_shader_source[3] = fragment_shader_out_3_0;
-        }
-    }
-  else /* gl_gles3 */
-    {
-      if (gl_major < 3 || glsl_major < 3)
-        {
-          data->shaders_initialized = True;
-          return;
-        }
-      /* We have at least OpenGL ES 3.0 and at least GLSL ES 3.0. */
-      vertex_shader_source[0] = shader_version_3_0_es;
-      vertex_shader_source[1] = vertex_shader_attribs_3_0;
-      vertex_shader_source[2] = vertex_shader_main;
-      fragment_shader_source[0] = shader_version_3_0_es;
-      fragment_shader_source[1] = fragment_shader_attribs_3_0;
-      fragment_shader_source[2] = fragment_shader_main;
-      fragment_shader_source[3] = fragment_shader_out_3_0;
-    }
-  if (!glsl_CompileAndLinkShaders(3,vertex_shader_source,
-                                  4,fragment_shader_source,
+  vertex_shader_source[0] = glsl_GetGLSLVersionString();
+  vertex_shader_source[1] = vertex_shader;
+  fragment_shader_source[0] = glsl_GetGLSLVersionString();
+  fragment_shader_source[1] = fragment_shader;
+  if (!glsl_CompileAndLinkShaders(2,vertex_shader_source,
+                                  2,fragment_shader_source,
                                   &data->shader_program))
     {
       data->shaders_initialized = True;
@@ -1126,6 +1119,14 @@ initialize_textfont_shaders_glsl (texture_font_data *data)
       data->shader_program = 0;
       data->shaders_initialized = True;
     }
+
+  glGenBuffers(1,&data->vertex_coord_buffer);
+  glGenBuffers(1,&data->vertex_tex_buffer);
+  glGenBuffers(1,&data->indices_buffer);
+
+  data->use_vao = glsl_IsCoreProfile();
+  if (data->use_vao)
+    glGenVertexArrays(1,&data->vertex_array_object);
 }
 #endif /* HAVE_GLSL */
 
@@ -1429,6 +1430,12 @@ texfont_unicode_character_name (texture_font_data *data, unsigned long uc)
 #endif /* HAVE_JWXYZ */
 
 
+XftFont *
+texfont_xft (texture_font_data *data)
+{
+  return data->xftfont;
+}
+
 
 /* Releases the font and texture.
  */
@@ -1453,6 +1460,11 @@ free_texture_font (texture_font_data *data)
     {
       glUseProgram (0);
       glDeleteProgram (data->shader_program);
+      glDeleteBuffers(1,&data->vertex_coord_buffer);
+      glDeleteBuffers(1,&data->vertex_tex_buffer);
+      glDeleteBuffers(1,&data->indices_buffer);
+      if (data->use_vao)
+        glDeleteVertexArrays(1,&data->vertex_array_object);
     }
 # endif /* HAVE_GLSL */
 
index 1d1f61cd1644e47dfcccc7bfbcce864bf8a7abbd..f8d1ede6d00c443b5e775bd9acc1777ee06e0341 100644 (file)
@@ -1,4 +1,4 @@
-/* texfonts, Copyright (c) 2005-2021 Jamie Zawinski <jwz@jwz.org>
+/* texfonts, Copyright © 2005-2025 Jamie Zawinski <jwz@jwz.org>
  * Loads X11 fonts into textures for use with OpenGL.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -80,5 +80,6 @@ extern char *texfont_unicode_character_name (texture_font_data *,
                                              unsigned long uc);
 #endif
 
+extern XftFont *texfont_xft (texture_font_data *);
 
 #endif /* __TEXTURE_FONT_H__ */
diff --git a/hacks/glx/topologica.man b/hacks/glx/topologica.man
new file mode 100644 (file)
index 0000000..4b3c3ce
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+topologica \- screen saver.
+.SH SYNOPSIS
+.B topologica
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Pulsing lines of light. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/4djXzz
+.SH COPYRIGHT
+Copyright \(co 2014 by Otavio Good.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Otavio Good.
diff --git a/hacks/glx/truchetzoom.man b/hacks/glx/truchetzoom.man
new file mode 100644 (file)
index 0000000..b24a9c5
--- /dev/null
@@ -0,0 +1,65 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+truchetzoom \- a truchet screen saver.
+.SH SYNOPSIS
+.B truchetzoom
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-fps]
+.SH DESCRIPTION
+A looping, distorting truchet chain with scanlines. 
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/view/4cBcDy
+.SH COPYRIGHT
+Copyright \(co 2024 by mrange.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+mrange.
diff --git a/hacks/glx/xshadertoy-compile.pl b/hacks/glx/xshadertoy-compile.pl
new file mode 100755 (executable)
index 0000000..c21bd69
--- /dev/null
@@ -0,0 +1,151 @@
+#!/usr/bin/perl -w
+# Copyright © 2025-2026 Jamie Zawinski <jwz@jwz.org>
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.  No representations are made about the suitability of this
+# software for any purpose.  It is provided "as is" without express or 
+# implied warranty.
+#
+# "Compile" a set of shadertoy GLSL scripts into a standalone XScreenSaver
+# module that runs "xshadertoy" with those scripts.
+#
+# Created: 26-Dec-2025.
+
+require 5;
+use diagnostics;
+use strict;
+use utf8;
+
+my $progname = $0; $progname =~ s@.*/@@g;
+my ($version) = ('$Revision: 1.02 $' =~ m/\s(\d[.\d]+)\s/s);
+
+my $verbose = 1;
+
+sub compile($@) {
+  my ($outfile, @files) = @_;
+  my ($common, @progs);
+  foreach my $f (@files) {
+    error ("$f: not a GLSL file") unless ($f =~ m/\.glsl$/s);
+    if ($f =~ m/-c(ommon)?\.glsl$/s) {
+      error ("multiple common files: $common, $f") if ($common);
+      $common = $f;
+    } else {
+      push @progs, $f;
+      error ("max of 5 programs: @progs") if (@progs > 5);
+    }
+  }
+
+  my $out = '';
+
+  my $comment = undef;
+  my $i = 0;
+  foreach my $f ($common, @progs) {
+    next unless defined ($f);
+    my $commonp = (defined($common) && $f eq $common);
+    my $body = '';
+    open (my $in, '<:utf8', $f) || error ("$f: $!");
+    local $/ = undef;  # read entire file
+    while (<$in>) { $body .= $_; }
+
+    # Extract the first comment from the first file.
+
+    ($comment) = ($body =~ m@^((\s*//[^\n]*\n|\s*/\*.*?\*/[ \t]*)+)@si)
+      unless ($comment);
+
+    # Omit the rest of the comments.
+
+    $body =~ s@//[^\n]*@@gs;   # It seems that // is parsed before /*
+    $body =~ s@/\*.*?\*/@@gs;
+    $body =~ s/^[ \t]+|[ \t]+$//gm;
+    $body =~ s/\n\n+/\n/gs;
+    $body =~ s/^\s+|\s+$//gs;
+
+    $out .= "\n.\n" if ($i);   # EOF marker between files.
+
+    if (@files > 1) {
+      my $j = defined($common) ? $i-1 : $i;
+      my $name = ($commonp ? 'Common' :
+                  $i == @files-1
+                  ? 'Image'
+                  : 'Buffer' . chr(ord('A') + $j));
+      $out .= "// $name\n\n";
+    }
+
+    $body =~ s/^/\t/gm;
+    $out .= $body . "\n";
+    $i++;
+  }
+
+  $out = "$comment\n\n$out" if ($comment);
+
+  my $title = $outfile;
+  $title =~ s@^.*/@@gs;
+
+  my $year = (localtime)[5] + 1900;
+  my $head = '#!/bin/bash
+# XScreenSaver, Copyright © ' . $year . ' Jamie Zawinski <jwz@jwz.org>
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.  No representations are made about the suitability of this
+# software for any purpose.  It is provided "as is" without express or 
+# implied warranty.
+
+PATH="$PATH":"$(dirname "$0")"
+exec -a "' . $title . '" \
+xshadertoy "$@" \
+';
+
+  $head .= " --program-common - \\\n" if (defined ($common));
+  $i = 0;
+  foreach my $p (@progs) {
+    $head .= " --program$i - \\\n";
+    $i++;
+  }
+  $head .= "<< \"_XSCREENSAVER_EOF_\"\n\n";
+  $out = "$head$out\n_XSCREENSAVER_EOF_\n";
+
+  open (my $of, '>:utf8', $outfile) || error ("$outfile: $!");
+  print $of $out;
+  chmod (oct("0755"), $of);
+  close $of;
+  print STDERR "$progname: wrote $outfile\n" if ($verbose);
+}
+
+
+sub error($) {
+  my ($err) = @_;
+  print STDERR "$progname: $err\n";
+  exit 1;
+}
+
+sub usage() {
+  print STDERR "usage: $progname [--verbose] [--quiet] --name NAME [ GLSL_FILES ...]\n";
+  exit 1;
+}
+
+sub main() {
+  my $name;
+  my @files = ();
+  while (@ARGV) {
+    $_ = shift @ARGV;
+    if (m/^--?verbose$/s) { $verbose++; }
+    elsif (m/^-v+$/s) { $verbose += length($_)-1; }
+    elsif (m/^--?q(uiet)?$/s) { $verbose = 0; }
+    elsif (m/^--?name$/s) { $name = shift @ARGV; }
+    elsif (m/^-./s) { usage; }
+    else { push @files, $_; }
+  }
+
+  usage unless ($name);
+  usage unless (@files);
+  compile ($name, @files);
+}
+
+main();
+exit 0;
diff --git a/hacks/glx/xshadertoy-download.pl b/hacks/glx/xshadertoy-download.pl
new file mode 100755 (executable)
index 0000000..06eda99
--- /dev/null
@@ -0,0 +1,313 @@
+#!/usr/bin/perl -w
+# Copyright © 2025 Jamie Zawinski <jwz@jwz.org>
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation.  No representations are made about the suitability of this
+# software for any purpose.  It is provided "as is" without express or 
+# implied warranty.
+#
+# Download source code from shadertoy.com.
+#
+# Usage: xshadertoy-download.pl --cookie 'XXX' URL
+#
+# It will write files like:
+#
+#   shadername-common.glsl
+#   shadername-0.glsl
+#   shadername-1.glsl
+#   shadername-2.glsl
+#
+# You need to pull the --cookie argument out of your web browser.
+# Also it only lasts an hour or so.  This sucks.
+#
+# Created: 19-Dec-2025.
+
+require 5;
+use diagnostics;
+use strict;
+
+my $progname = $0; $progname =~ s@.*/@@g;
+my ($version) = ('$Revision: 1.02 $' =~ m/\s(\d[.\d]+)\s/s);
+
+my $verbose = 1;
+my $debug_p = 0;
+
+use POSIX;
+use IPC::Open2;
+use LWP::UserAgent;
+use JSON::Any;
+
+
+sub url_quote($) {
+  my ($u) = @_;
+  $u =~ s|([^-a-zA-Z0-9.\@_\r\n])|sprintf("%%%02X", ord($1))|ge;
+  return $u;
+}
+
+sub cmdstr(@) {
+  my @cmd = @_;
+
+  # Quote the string with single quotes, which does not require backslashes
+  # for any special character; quote single quote as '\''
+  #
+  my $s = join(' ', map { if ($_ eq '' || m![^-._,:a-z\d/@+=]!s) {
+                                     s%\'%'\\''%gsi;
+                                     s/\n/\\n/gsi;
+                                     $_ = "\'$_\'";
+                                   }
+                                   $_;
+                                 } @cmd);
+
+  # Make multi-line commands more readable.
+  $s =~ s/('\(')/ \\\n  $1/gs;
+  $s =~ s/('\)')/$1 \\\n  /gs;
+  $s =~ s/(\\)(\n *\\)+/$1/gs;
+  $s =~ s/(\s-( i | vframes | t | c:v | acodec | max_muxing_queue_size |
+                loop | map | pass | b:v | c:s | passlogfile |
+                vf | af | filter_complex | movflags | metadata[^\s]* |
+                c:a ) \s )
+         / \\\n$1/gsx;
+  $s =~ s/( '[^ ]+$)/ \\\n$1/s;
+
+  return $s;
+}
+
+sub json_decode($) {
+  my ($s) = @_;
+  my $json = undef;
+  eval {
+    my $j = JSON::Any->new;
+    $json = $j->jsonToObj ($s);
+  };
+  return $json;
+}
+
+
+sub load($$$$) {
+  my ($id, $url, $post, $cookie) = @_;
+
+  $cookie =~ s/^Cookie: //si;
+
+  my $agent = ('User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)' .
+               ' AppleWebKit/605.1.15 (KHTML, like Gecko)' .
+               ' Version/18.6 Safari/605.1.15');
+  my $body = '';
+  if (0) {
+    # Somehow Clownflare is blocking both LWP and wget, but curl works...
+  
+    my $ua = LWP::UserAgent->new;
+    $ua->agent($agent);
+  
+    if ($verbose > 3) {
+      $ua->add_handler("request_send",  sub { shift->dump; return });
+      $ua->add_handler("response_done", sub { shift->dump; return });
+    }
+  
+    my $res = ($post
+               ? $ua->post ($url,
+                            Content_Type => 'application/x-www-form-urlencoded',
+                            Referer      => $url,
+                            Cookie       => $cookie,
+                            Content      => $post,
+                            )
+               : $ua->get ($url,
+                           Referer      => $url,
+                           Cookie       => $cookie,
+                          ));
+    my $ret = ($res && $res->code) || 'null';
+    if (!$res->is_success) {
+      my $err = "$id: status $ret";
+      # $err .= $find if ($ret == 403);
+      # error ($err);
+      return '';
+    }
+
+    $body = $res->decoded_content;
+  } else {
+    my @cmd = ('curl',
+               $url,
+               '--silent',
+               '--header', $agent,
+               '--header', "Referer: $url",
+               '--header', "Cookie: $cookie",
+               ($post
+                ? ('--request', 'POST',
+                   '--header',
+                     'Content-Type: application/x-www-form-urlencoded',
+                   '--data', $post)
+                : ()));
+
+    print STDERR "$progname: exec: " . cmdstr(@cmd) . "\n" if ($verbose > 1);
+    my ($in, $out);
+    my $pid = open2 ($out, $in, @cmd);
+    close ($in);
+    while (<$out>) { $body .= $_; }
+    waitpid ($pid, 0);
+    my $status = $? >> 8;
+    error ("$id: failed with status $status") if ($status);
+
+    close ($out);
+  }
+
+  return $body;
+}
+
+sub download($$) {
+  my ($url, $cookie) = @_;
+
+  my ($id) = ($url =~ m@/view/([^/?&]{4,})$@s);
+  error ("unparsable shadertoy URL: $url") unless $id;
+
+  my $url2 = 'https://www.shadertoy.com/shadertoy';
+
+  my $find = join("\n\t", "", "",
+                  "Re-invoke this script with the '--cookie' parameter.",
+                  "",
+                  "To find your cookie:",
+                  "",
+                  "  Open the URL in a browser; Show Web Inspector;" .
+                   " Sources tab;",
+                  "  Copy the value of the Cookie header on the right.");
+  my $post = join ('&',
+                   's=' . url_quote("{ \"shaders\" : [\"$id\"] }"),
+                   'nt=1',
+                   'nl=1',
+                   'np=1');
+
+  print STDERR "$progname: $id: loading $url\n" if ($verbose);
+  my $body = load ($id, $url2, $post, $cookie);
+
+  if (!$body || $body !~ m/^\[\{/s) {
+    error ("$id: unable to load JSON$find");
+  }
+
+  my $json = json_decode ($body);
+  error ("$id: unparsable JSON") unless $json;
+
+  $json = $json->[0]              || error ("$id: unparsable JSON");
+  my $info = $json->{info}        || error ("$id: JSON: no info");
+  my $name = $info->{name}        || error ("$id: JSON: no name");
+  my $user = $info->{username}    || error ("$id: JSON: no username");
+  my $desc = $info->{description} || error ("$id: JSON: no description");
+  my $date = $info->{date}        || error ("$id: JSON: no date");
+  my $rend = $json->{renderpass}  || error ("$id: JSON: no renderpass");
+
+  foreach ($name, $user, $desc) { s/^\s+|\s+$//gs; }
+
+  # The "About" section of the /user/ page almost always has nothing on it.
+  if (0) {
+    my $url3 = "https://www.shadertoy.com/user/$user";
+    my $body2 = load ($user, $url3, undef, $cookie);
+    my ($about) = ($body2 =~ m@<b>About</b>(.*?)</td>@si);
+    $about =~ s@<BR/?>|<P>@\n@gsi;
+    $about =~ s/<[^<>]*>//gsi;
+    $about =~ s/^\s+|\s+$//gsi;
+    $about =~ s/\n\n+/\n/gsi;
+  }
+
+  $desc =~ s@\n@\n// @gs;
+  $date = strftime ("%d-%b-%Y", localtime ($date));
+  my $header = ("// Title:  $name\n" .
+                "// Author: $user\n" .
+                "// URL:    $url\n" .
+                "// Date:   $date\n" .
+                "// Desc:   $desc\n" .
+                "\n");
+
+  my $base = lc ($name);
+  $base =~ s/[^a-z\d]+/-/gs;
+  $base =~ s/-+/-/s;
+  $base =~ s/^-+|-+$//s;
+
+  my @common;
+  my @passes;
+  foreach my $pass (@$rend) {
+    my $ptype = $pass->{type} || error ("$id: JSON: no pass type");
+    my $code  = $pass->{code} || error ("$id: JSON: no pass code");
+    $code = "$header$code\n";
+    if ($ptype =~ m/common/si) {
+      push @common, $code;
+    } else {
+      push @passes, $code;
+    }
+  }
+
+  $base = "glsl/$base";
+
+  my @out;
+  push @out, [ "$base.json", $body, '' ];
+  push @out, [ "$base-common.glsl", $common[0], '-common' ] if (@common);
+
+  if (@passes == 1) {
+    push @out, [ "$base.glsl", $passes[0], '' ];
+  } else {
+    my $i = 0;
+    foreach my $c (@passes) {
+      push @out, [ "$base-$i.glsl", $c, $i ];
+      $i++;
+    }
+  }
+
+  foreach my $P (@out) {
+    my ($fn, $code, $pass) = @$P;
+    if ($debug_p) {
+      print STDERR "$progname: $id: not writing $fn\n";
+    } else {
+      open (my $out, '>:utf8', $fn) || error ("$id: $fn: $!");
+      print $out $code;
+      close ($out);
+      print STDERR "$progname: $id: wrote $fn\n" if ($verbose);
+    }
+  }
+
+  if ($verbose) {
+    my $cmd = 'xshadertoy';
+    my $i = 0;
+    foreach my $P (@out) {
+      my ($fn, $code, $pass) = @$P;
+      next if ($fn =~ m/\.json$/s);
+      $cmd .= " \\\n " if ($i > 0);
+      $cmd .= " --program$pass $fn";
+      $i++;
+    }
+    print STDERR "\n# $url\n$cmd\n";
+  }
+}
+
+
+sub error($) {
+  my ($err) = @_;
+  print STDERR "$progname: $err\n";
+  exit 1;
+}
+
+sub usage() {
+  print STDERR "usage: $progname [--verbose] [--quiet] [--cookie C] url...\n";
+  exit 1;
+}
+
+sub main() {
+  my @urls = ();
+  my $cookie = '';
+  while (@ARGV) {
+    $_ = shift @ARGV;
+    if (m/^--?verbose$/s) { $verbose++; }
+    elsif (m/^-v+$/s) { $verbose += length($_)-1; }
+    elsif (m/^--?q(uiet)?$/s) { $verbose = 0; }
+    elsif (m/^--?debug$/s) { $debug_p++; }
+    elsif (m/^--?cookie$/s) { $cookie = shift @ARGV; }
+    elsif (m/^-./s) { usage; }
+    else { push @urls, $_; }
+  }
+
+  usage unless (@urls);
+  foreach my $url (@urls) {
+    download ($url, $cookie);
+  }
+}
+
+main();
+exit 0;
diff --git a/hacks/glx/xshadertoy.c b/hacks/glx/xshadertoy.c
new file mode 100644 (file)
index 0000000..380e9eb
--- /dev/null
@@ -0,0 +1,1089 @@
+/* xshadertoy, Copyright © 2025-2026 Jamie Zawinski <jwz@jwz.org>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation.  No representations are made about the suitability of this
+ * software for any purpose.  It is provided "as is" without express or 
+ * implied warranty.
+ *
+ * Run arbitrary GLSL programs that use the shadertoy.com API.
+ * Usage:
+ *
+ *   xshadertoy --program FILE.glsl
+ *
+ *   xshadertoy --program-common FILE.glsl     \
+ *             --program0 FILE0.glsl           \
+ *             --program1 FILE1.glsl           \
+ *             --program2 FILE2.glsl           \
+ *             --program3 FILE3.glsl           \
+ *             --program4 FILE4.glsl           \
+ *             --speed 2.0                     \
+ *             --scale 0.5                     \
+ *             --automouse                     \
+ *
+ *   It is not possible to have this program load the code directly from
+ *   shadertoy.com due to their scraping countermeasures, so you must
+ *   download the GLSL files manually.  The "xshadertoy-download.pl"
+ *   script makes that a little easier, but not much easier.
+ *
+ *   Does not support texture or other input assets; the programs must
+ *   be self-contained.
+ *
+ *   Multi-pass rendering is supported, but only in the default order:
+ *   e.g. program3 gets program2's output on iChannel2 and can't bind
+ *   iChannel2 to a different pass instead.  Likewise, self-access to
+ *   previously-generated frames is not supported.
+ *
+ *
+ * LICENSING:
+ *
+ *   The default license on shadertoy.com is "CC BY-NC-SA", and so the vast
+ *   majority of uploads use that.  However, that license, by prohibiting
+ *   commercial use, is not an open source license, and is more restrictive
+ *   than the MIT/BSD-style license used by the rest of XScreenSaver.
+ *
+ *   For a Shadertoy program to be distributed with or within XScreenSaver,
+ *   it must be licensed under a compatible license, such as: MIT, BSD,
+ *   CC-BY, CC-BY-SA or CC0.
+ *
+ *   Also: The Shadertoy community has a strong culture of remixing, so
+ *   when evaluating the license terms of a program, any programs that
+ *   it was derived from must also have compatible terms.
+ *
+ *
+ * CONTROL FLOW:
+ *
+ *   The naming convention for Shadertoy-based XScreenSaver modules is
+ *   that the GLSL files have the same basename as the hack itself,
+ *   plus an optional suffix ("HACK-[c0-4].glsl").  Each gets its own
+ *   config/HACK.xml and .man as usual.
+ *
+ *   X11:
+ *     /usr/libexec/xscreensaver/HACK is a bash script that invokes
+ *     "xshadertoy" with the GLSL code on stdin.  It uses "exec -a" so
+ *     that argv0 / progname = "HACK" and progclass = "XShadertoy".
+ *     Makefile.in rules build these via xshadertoy-compile.pl.
+ *
+ *   macOS Cocoa:
+ *     The HACK.saver target compiles xshadertoy.c and XScreenSaverView.c
+ *     and includes the .glsl files as assets.
+ *
+ *     As usual, XScreenSaverView compiles to class XScreenSaverHACKView,
+ *     but it is also compiled with -DUSE_SHADERTOY=1 which causes it
+ *     to use "xshadertoy_xscreensaver_function_table" instead of
+ *     "HACK_xscreensaver_function_table".  It then changes progclass
+ *     from "XShadertoy" back to "HACK".
+ *
+ *     This file, xshadertoy.c, searches in $BUNDLE_RESPATH (which is
+ *     "HACK.saver/Contents/Resources/") for the .glsl files and loads
+ *     them as normal files.
+ *
+ *   iOS Cocoa:
+ *     Same as macOS except that instead of -DUSE_SHADERTOY, the
+ *     ios-function-table.m maps "xshadertoy_xscreensaver_function_table".
+ *
+ *   Android:
+ *     The .glsl files are copied into xscreensaver/assets/glsl/ in the
+ *     APK by check-configs.pl.  Similarly to iOS, function-table.h maps
+ *     "xshadertoy_xscreensaver_function_table".  This file loads them
+ *     with android_read_asset_file() instead of with fopen().
+ */
+
+#define DEFAULTS       "*delay:                20000   \n" \
+                       "*showFPS:              False   \n" \
+                       "*prefersGLSL:          True    \n" \
+                       "*forceSingleSample:    True    \n" \
+
+# define release_xshadertoy 0
+
+#include "xlockmore.h"
+#include <ctype.h>
+
+#ifdef USE_GL /* whole file */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <ctype.h>
+
+#include "doubletime.h"
+#include "glsl-utils.h"
+#include "rotator.h"
+
+#define DEF_SPEED "1.0"
+#define DEF_AUTOMOUSE "False"
+#define DEF_AUTOMOUSE_SPEED "1.0"
+#define DEF_SCALE "1.0"
+#define DEF_SHADER_FILE0 "(none)"
+#define DEF_SHADER_FILE1 "(none)"
+#define DEF_SHADER_FILE2 "(none)"
+#define DEF_SHADER_FILE3 "(none)"
+#define DEF_SHADER_FILE4 "(none)"
+#define DEF_SHADER_FILE_COMMON "(none)"
+
+static GLfloat speed;
+static GLfloat scale;
+static Bool automouse_p;
+static GLfloat automouse_speed;
+static char *shader_file0 = 0;
+static char *shader_file1 = 0;
+static char *shader_file2 = 0;
+static char *shader_file3 = 0;
+static char *shader_file4 = 0;
+static char *shader_file_common = 0;
+
+typedef struct {
+  GLXContext *glx_context;
+
+  GLint gl_major, gl_minor, glsl_major, glsl_minor;
+  GLboolean gl_gles3;
+
+  char *shader_program[6];             /* BufferA, B, C, D, Image, Common */
+
+  GLuint vertex_pos_buffer;
+  GLuint win_draw_fbo, win_read_fbo;
+  GLuint vao;
+  struct {
+    GLuint poly_shader_program;
+    GLuint fbo, tex, draw_fbo, read_fbo;
+    GLint poly_pos;
+    GLint frag_irez;
+    GLint frag_itime;
+    GLint frag_idelta;
+    GLint frag_ifps;
+    GLint frag_iframe;
+    GLint frag_idate;
+    GLint frag_imouse;
+    GLint frag_ichan[4];
+  } channels[5];
+
+  double start_time, last_time, last_tm, midnight;
+  struct tm now;
+  unsigned long total_frames;
+  struct { int x, y; } mouse_clicked, mouse_dragged;
+  Bool button_down_p, was_button_down_p;
+  rotator *rot;
+
+} xshadertoy_configuration;
+
+static xshadertoy_configuration *bps = NULL;
+
+static XrmOptionDescRec opts[] = {
+  {"-speed",          ".speed",          XrmoptionSepArg, 0 },
+  {"-scale",          ".scale",          XrmoptionSepArg, 0 },
+  {"-automouse",      ".automouse",      XrmoptionNoArg, "True"  },
+  {"+automouse",      ".automouse",      XrmoptionNoArg, "False" },
+  {"-automouse-speed",".automouseSpeed", XrmoptionSepArg, 0 },
+  {"-program",        ".shaderChannel0", XrmoptionSepArg, 0 },
+  {"-program-common", ".shaderCommon",   XrmoptionSepArg, 0 },
+  {"-program0",       ".shaderChannel0", XrmoptionSepArg, 0 },
+  {"-program1",       ".shaderChannel1", XrmoptionSepArg, 0 },
+  {"-program2",       ".shaderChannel2", XrmoptionSepArg, 0 },
+  {"-program3",       ".shaderChannel3", XrmoptionSepArg, 0 },
+  {"-program4",       ".shaderChannel4", XrmoptionSepArg, 0 },
+};
+
+static argtype vars[] = {
+  { &speed, "speed", "Speed", DEF_SPEED, t_Float },
+  { &scale, "scale", "Scale", DEF_SCALE, t_Float },
+  { &automouse_p, "automouse", "Automouse", DEF_AUTOMOUSE, t_Bool },
+  { &automouse_speed, "automouseSpeed", "Speed", DEF_AUTOMOUSE_SPEED, t_Float },
+  { &shader_file0, "shaderChannel0", "ShaderChannel",
+      DEF_SHADER_FILE0, t_String },
+  { &shader_file1, "shaderChannel1", "ShaderChannel",
+      DEF_SHADER_FILE1, t_String },
+  { &shader_file2, "shaderChannel2", "ShaderChannel",
+      DEF_SHADER_FILE2, t_String },
+  { &shader_file3, "shaderChannel3", "ShaderChannel",
+      DEF_SHADER_FILE3, t_String },
+  { &shader_file4, "shaderChannel4", "ShaderChannel",
+      DEF_SHADER_FILE4, t_String },
+  { &shader_file_common, "shaderCommon", "ShaderChannel",
+      DEF_SHADER_FILE_COMMON, t_String },
+};
+
+ENTRYPOINT ModeSpecOpt xshadertoy_opts = {
+  countof(opts), opts, countof(vars), vars, NULL};
+
+#ifdef HAVE_GLSL
+
+static const GLchar *vertex_shader = "\
+       #ifdef GL_ES                                                    \n\
+         precision highp float;                                        \n\
+         precision highp int;                                          \n\
+       #endif                                                          \n\
+                                                                       \n\
+       #if __VERSION__ <= 120                                          \n\
+         attribute vec2 a_Position;                                    \n\
+       #else                                                           \n\
+         in vec2 a_Position;                                           \n\
+       #endif                                                          \n\
+                                                                       \n\
+       void main() {                                                   \n\
+         gl_Position = vec4 (a_Position.xy, 0.0, 1.0);                 \n\
+       }                                                               \n\
+";
+
+/* Docs:
+   https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.1.20.pdf
+   https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.1.30.pdf
+   https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.1.50.pdf
+   https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.1.40.pdf
+   https://registry.khronos.org/OpenGL/specs/gl/GLSLangSpec.4.00.pdf
+ */
+
+static const GLchar *fragment_shader_head = "\
+       #ifdef GL_ES                                                    \n\
+         precision highp float;                                        \n\
+         precision highp int;                                          \n\
+       #endif                                                          \n\
+                                                                       \n\
+       #if __VERSION__ >= 130                                          \n\
+         out vec4 frag_color;                                          \n\
+        #endif                                                         \n\
+                                                                       \n\
+       uniform vec3  iResolution;  // viewport resolution (in pixels)  \n\
+       uniform float iTime;        // shader playback time (in secs)   \n\
+       uniform float iTimeDelta;   // render time (in secs)            \n\
+       uniform float iFrameRate;   // shader FPS                       \n\
+       uniform int   iFrame;       // shader frame number              \n\
+       uniform vec4  iDate;        // (Y, M, D, secs since midnight)   \n\
+       uniform vec4  iMouse;       // mouse pos (see below)            \n\
+                                                                       \n\
+       uniform vec3  iChannelResolution[4];    // Texture sizes        \n\
+                                                                       \n\
+       // These are for audio:                                         \n\
+       uniform float iChannelTime[4];                                  \n\
+       uniform float iSampleRate;                                      \n\
+                                                                       \n\
+       // On the web version, these might be of type sampler3D or      \n\
+       // something else, depending on what input was selected in      \n\
+       // then menu.  Here, we only support 2D textures because we     \n\
+       // only allow input from the output of the previous pass.       \n\
+       //                                                              \n\
+       uniform sampler2D iChannel0;                                    \n\
+       uniform sampler2D iChannel1;                                    \n\
+       uniform sampler2D iChannel2;                                    \n\
+       uniform sampler2D iChannel3;                                    \n\
+                                                                       \n\
+                                                                       \n\
+       // These library functions existed in GLSL 1.2 but were         \n\
+       // removed in GLSL 1.3; avoid name conflicts if programs        \n\
+       // happen to use these names for their own functions.           \n\
+       //                                                              \n\
+       # define noise  xshadertoy_noise                                \n\
+       # define noise2 xshadertoy_noise2                               \n\
+                                                                       \n\
+                                                                       \n\
+       #if __VERSION__ <= 120                                          \n\
+                                                                       \n\
+       // The ivec and uvec types were introduced in GLSL 1.3.         \n\
+       #define ivec2 vec2                                              \n\
+       #define ivec3 vec3                                              \n\
+       #define ivec4 vec4                                              \n\
+       #define uvec2 vec2                                              \n\
+       #define uvec3 vec3                                              \n\
+       #define uvec4 vec4                                              \n\
+       #define uint  int                                               \n\
+                                                                       \n\
+       // The texture2D() function was renamed texture() in GLSL 1.3.  \n\
+       // (Deprecated in GLSL 1.3, removed in GLSL 1.5.)               \n\
+       //                                                              \n\
+       vec4 texture (sampler2D sampler, vec2 coord) {                  \n\
+         return texture2D (sampler, coord);                            \n\
+       }                                                               \n\
+        vec4 texture (sampler2D sampler, vec3 coord) {                 \n\
+          return texture2D (sampler, coord.xy);                                \n\
+        }                                                              \n\
+       vec4 texture (sampler2D sampler, vec2 coord, float bias) {      \n\
+         return texture2D (sampler, coord, bias);                      \n\
+       }                                                               \n\
+       vec4 texture (sampler2D sampler, vec3 coord, float bias) {      \n\
+         return texture2D (sampler, coord.xy, bias);                   \n\
+       }                                                               \n\
+                                                                       \n\
+       vec4 texelFetch(sampler2D sampler, ivec2 coord, int lod) {      \n\
+         return texture (sampler, (coord + 0.5) / iResolution.xy);     \n\
+       }                                                               \n\
+       vec4 texelFetch(sampler2D sampler, ivec3 coord, int lod) {      \n\
+         return texture (sampler, (coord + 0.5) / iResolution);        \n\
+       }                                                               \n\
+                                                                       \n\
+       // Hyperbolic functions were added in GLSL 1.3.                 \n\
+       //                                                              \n\
+       float sinh(in float i) {                                        \n\
+         // return (exp(i) - exp(-i)) / 2;                             \n\
+         float j = exp(i);                                             \n\
+         return (j - 1 / j) / 2;                                       \n\
+       }                                                               \n\
+       float cosh(in float i) {                                        \n\
+         // return (exp(i) + exp(-i)) / 2;                             \n\
+         float j = exp(i);                                             \n\
+         return (j + 1 / j) / 2;                                       \n\
+       }                                                               \n\
+       float tanh(in float i) {                                        \n\
+          // return sinh(i) / cosh(i);                                 \n\
+         return (2 / (1 + exp(-2 * i))) - 1;                           \n\
+       }                                                               \n\
+       vec2 sinh(in vec2 v) { return vec2(sinh(v.x), sinh(v.y)); }     \n\
+       vec2 cosh(in vec2 v) { return vec2(cosh(v.x), cosh(v.y)); }     \n\
+       vec2 tanh(in vec2 v) { return vec2(tanh(v.x), tanh(v.y)); }     \n\
+                                                                       \n\
+       vec3 sinh(in vec3 v) {                                          \n\
+         return vec3(sinh(v.x), sinh(v.y), sinh(v.z));                 \n\
+       }                                                               \n\
+       vec3 cosh(vec3 v) {                                             \n\
+         return vec3(cosh(v.x), cosh(v.y), cosh(v.z));                 \n\
+       }                                                               \n\
+       vec3 tanh(vec3 v) {                                             \n\
+         return vec3(tanh(v.x), tanh(v.y), tanh(v.z));                 \n\
+       }                                                               \n\
+                                                                       \n\
+       vec4 sinh(in vec4 v) {                                          \n\
+         return vec4(sinh(v.x), sinh(v.y), sinh(v.z), sinh(v.w));      \n\
+       }                                                               \n\
+       vec4 cosh(vec4 v) {                                             \n\
+         return vec4(cosh(v.x), cosh(v.y), cosh(v.z), cosh(v.w));      \n\
+       }                                                               \n\
+       vec4 tanh(vec4 v) {                                             \n\
+         return vec4(tanh(v.x), tanh(v.y), tanh(v.z), tanh(v.w));      \n\
+       }                                                               \n\
+                                                                       \n\
+       // The modern concept of rounding was added in GLSL 1.3.        \n\
+       //                                                              \n\
+       int round(float f) { return int(f + 0.5); }                     \n\
+       ivec2 round(vec2 v) { return ivec2(round(v.x), round(v.y)); }   \n\
+       ivec3 round(vec3 v) {                                           \n\
+         return ivec3(round(v.x), round(v.y), round(v.z));             \n\
+       }                                                               \n\
+       ivec4 round(vec4 v) {                                           \n\
+         return ivec4(round(v.x), round(v.y), round(v.z), round(v.w)); \n\
+       }                                                               \n\
+                                                                       \n\
+       // I think the type propagation rules changed?                  \n\
+       // This makes 'int i = max(...)' work.                          \n\
+       int max(int a, int b) { return a > b ? a : b; }                 \n\
+        // I hate that GLSL's method-selection signatures include      \n\
+       // arg types but not return types, yet require them to match,   \n\
+       // so these conflict:                                           \n\
+        // int max(int a, float b) { return a > b ? a : int(b); }      \n\
+        // int max(float a, int b) { return a > b ? int(a) : b; }      \n\
+                                                                       \n\
+       #endif   // __VERSION__ > 120                                   \n\
+                                                                       \n\
+       #line 1                                                         \n\
+";
+static const char *fragment_shader_tail = "\
+                                                                       \n\
+       void main() {                                                   \n\
+         vec4 col = vec4 (0.0, 0.0, 0.0, 1.0);                         \n\
+         mainImage (col, gl_FragCoord.xy);                             \n\
+       #if __VERSION__ <= 120                                          \n\
+         gl_FragColor = col;                                           \n\
+       #else                                                           \n\
+         frag_color = col;                                             \n\
+        #endif                                                         \n\
+       }                                                               \n\
+";
+
+#endif /* HAVE_GLSL */
+
+
+static void
+gen_framebuffers (ModeInfo *mi)
+{
+  xshadertoy_configuration *bp = &bps[MI_SCREEN(mi)];
+  GLint internal_format, format, type;
+  int i;
+
+  if (!bp->gl_gles3)
+    {
+      internal_format = GL_RGBA;
+      format = GL_RGBA;
+      type = GL_FLOAT;
+    }
+  else
+    {
+      if (bp->gl_major == 3 && bp->gl_minor >= 2)
+        {
+          internal_format = GL_RGBA16F;
+          format = GL_RGBA;
+          type = GL_HALF_FLOAT;
+        }
+      else
+        {
+          internal_format = GL_RGBA8;
+          format = GL_RGBA;
+          type = GL_UNSIGNED_BYTE;
+        }
+    }
+
+  for (i = 0; i < countof(bp->channels); i++)
+    {
+      if (!bp->shader_program[i] || !*bp->shader_program[i])
+        continue;
+
+      glGenFramebuffers (1, &bp->channels[i].fbo);
+      glGenTextures (1, &bp->channels[i].tex);
+      glBindTexture (GL_TEXTURE_2D, bp->channels[i].tex);
+      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+      glTexImage2D (GL_TEXTURE_2D, 0, internal_format,
+                    MI_WIDTH(mi) * scale, MI_HEIGHT(mi) * scale,
+                    0, format, type, 0);
+    
+      glBindFramebuffer (GL_FRAMEBUFFER, bp->channels[i].fbo);
+      glFramebufferTexture2D (GL_FRAMEBUFFER,
+                              GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+                              bp->channels[i].tex, 0);
+      if (GL_FRAMEBUFFER_COMPLETE !=
+          glCheckFramebufferStatus (GL_FRAMEBUFFER))
+        {
+          fprintf (stderr,
+                   "%s: GLSL FBO failed for FBO %d \n", progname, i);
+          exit (1);
+        }
+
+      bp->channels[i].draw_fbo = bp->channels[i].fbo;
+      bp->channels[i].read_fbo = bp->channels[i].fbo;
+    }
+}
+
+
+static void
+delete_framebuffers (ModeInfo *mi)
+{
+  xshadertoy_configuration *bp = &bps[MI_SCREEN(mi)];
+  int i;
+
+  for (i = 0; i < countof(bp->channels); i++)
+    {
+      if (bp->channels[i].fbo)
+        glDeleteFramebuffers (1, &bp->channels[i].fbo);
+      if (bp->channels[i].tex)
+        glDeleteTextures (1, &bp->channels[i].tex);
+    }
+}
+
+
+static void
+init_glsl (ModeInfo *mi)
+{
+# ifndef HAVE_GLSL
+  fprintf (stderr, "%s: GLSL is required.\n", progname);
+  exit (1);
+# else /* HAVE_GLSL */
+
+  xshadertoy_configuration *bp = &bps[MI_SCREEN(mi)];
+  int i;
+
+  if (!glsl_GetGlAndGlslVersions (&bp->gl_major, &bp->gl_minor,
+                                  &bp->glsl_major, &bp->glsl_minor,
+                                  &bp->gl_gles3))
+    {
+      fprintf (stderr, "%s: GLSL is required\n", progname);
+      exit (1);
+    }
+
+  if (glsl_IsCoreProfile())
+    glGenVertexArrays (1, &bp->vao);
+
+  /* The FBOs of the output window, before channel FBOs were created. */
+  glGetIntegerv (GL_DRAW_FRAMEBUFFER_BINDING, (GLint *) &bp->win_draw_fbo);
+  glGetIntegerv (GL_READ_FRAMEBUFFER_BINDING, (GLint *) &bp->win_read_fbo);
+
+  if (scale > 1 || scale <= 0)  /* Scale down only */
+    scale = 1;
+
+  for (i = 0; i < countof(bp->channels); i++)
+    {
+      const char *fn = (i == 0 ? shader_file0 :
+                        i == 1 ? shader_file1 :
+                        i == 2 ? shader_file2 :
+                        i == 3 ? shader_file3 :
+                        i == 4 ? shader_file4 : "???");
+      GLuint p;
+      const GLchar *vertex_shader_source[2];
+      const GLchar *fragment_shader_source[6];
+      const GLchar *common =
+        bp->shader_program[countof(bp->shader_program) - 1];
+      if (!common) common = "";
+
+      if (!bp->shader_program[i] || !*bp->shader_program[i])
+        continue;
+
+      vertex_shader_source[0]   = glsl_GetGLSLVersionString();
+      vertex_shader_source[1]   = vertex_shader;
+      fragment_shader_source[0] = glsl_GetGLSLVersionString();
+      fragment_shader_source[1] = fragment_shader_head;
+      fragment_shader_source[2] = common;
+      fragment_shader_source[3] = "\n#line 1\n";
+      fragment_shader_source[4] = bp->shader_program[i];
+      fragment_shader_source[5] = fragment_shader_tail;
+      if (!glsl_CompileAndLinkShaders(
+           countof(vertex_shader_source),   vertex_shader_source,
+           countof(fragment_shader_source), fragment_shader_source,
+           &bp->channels[i].poly_shader_program))
+        {
+          fprintf (stderr,
+                   "%s: GLSL compilation of --program%d \"%s\" failed\n",
+                   progname, i, fn);
+          exit (1);
+        }
+
+      /* These are -1 if names are not declared in the shader program,
+         or if the program does not use them. */
+      p = bp->channels[i].poly_shader_program;
+      bp->channels[i].poly_pos    = glGetAttribLocation  (p, "a_Position");
+      bp->channels[i].frag_irez   = glGetUniformLocation (p, "iResolution");
+      bp->channels[i].frag_itime  = glGetUniformLocation (p, "iTime");
+      bp->channels[i].frag_idelta = glGetUniformLocation (p, "iTimeDelta");
+      bp->channels[i].frag_ifps   = glGetUniformLocation (p, "iFrameRate");
+      bp->channels[i].frag_iframe = glGetUniformLocation (p, "iFrame");
+      bp->channels[i].frag_imouse = glGetUniformLocation (p, "iMouse");
+      bp->channels[i].frag_idate  = glGetUniformLocation (p, "iDate");
+      bp->channels[i].frag_ichan[0] = glGetUniformLocation (p, "iChannel0");
+      bp->channels[i].frag_ichan[1] = glGetUniformLocation (p, "iChannel1");
+      bp->channels[i].frag_ichan[2] = glGetUniformLocation (p, "iChannel2");
+      bp->channels[i].frag_ichan[3] = glGetUniformLocation (p, "iChannel3");
+    }
+
+  gen_framebuffers (mi);
+
+  {
+    static const GLfloat verts[] = {
+      -1, -1,
+       1, -1,
+      -1,  1,
+      -1,  1,
+       1, -1,
+       1,  1,
+    };
+    glGenBuffers (1, &bp->vertex_pos_buffer);
+    glBindBuffer (GL_ARRAY_BUFFER, bp->vertex_pos_buffer);
+    glBufferData (GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
+  }
+# endif /* HAVE_GLSL */
+}
+
+
+ENTRYPOINT void
+reshape_xshadertoy (ModeInfo *mi, int width, int height)
+{
+  /* Since this is GLES-only, the fixed function pipeline is not used. */
+  glViewport (0, 0, (GLint) width, (GLint) height);
+
+  /* Reallocate the framebuffers with the current window size. */
+  delete_framebuffers (mi);
+  gen_framebuffers (mi);
+}
+
+
+ENTRYPOINT Bool
+xshadertoy_handle_event (ModeInfo *mi, XEvent *event)
+{
+  xshadertoy_configuration *bp = &bps[MI_SCREEN(mi)];
+  if (event->xany.type == ButtonPress)
+    {
+      bp->button_down_p++;
+      return True;
+    }
+  else if (event->xany.type == ButtonRelease)
+    {
+      if (bp->button_down_p) bp->button_down_p--;
+      return True;
+    }
+  else if (screenhack_event_helper (MI_DISPLAY(mi), MI_WINDOW(mi), event))
+    return True;
+  return False;
+}
+
+
+ENTRYPOINT void
+init_xshadertoy (ModeInfo *mi)
+{
+  xshadertoy_configuration *bp;
+  int i;
+
+  MI_INIT (mi, bps);
+  bp = &bps[MI_SCREEN(mi)];
+
+  bp->glx_context = init_GL(mi);
+
+  reshape_xshadertoy (mi, MI_WIDTH(mi), MI_HEIGHT(mi));
+
+  /* Pack the programs to the left, if they did --program0 --program2 */
+  {
+    char *p[countof(bp->channels)];
+    memset (p, 0, sizeof(p));
+    i = 0;
+# define PUSH(S) if (S && *S && !!strcasecmp (S, DEF_SHADER_FILE0)) p[i++] = S
+    PUSH (shader_file0);
+    PUSH (shader_file1);
+    PUSH (shader_file2);
+    PUSH (shader_file3);
+    PUSH (shader_file4);
+# undef PUSH
+    shader_file0 = p[0];
+    shader_file1 = p[1];
+    shader_file2 = p[2];
+    shader_file3 = p[3];
+    shader_file4 = p[4];
+  }
+
+# ifdef HAVE_COCOA
+  /* When xshadertoy is run under a macOS Cocoa .saver bundle, we search
+     in the $BUNDLE_RESPATH directory for any files whose names match
+     "progname-N.glsl", etc.
+   */
+  {
+    const char *dir = getenv ("BUNDLE_RESPATH");
+    const char *ext = "glsl";
+    char *name = strdup (progname);
+    char *s;
+    for (s = name; *s; s++) *s = tolower(*s);
+
+    if (!dir)
+      {
+        fprintf (stderr, "%s: BUNDLE_RESPATH is unset\n", name);
+        abort();
+      }
+
+    for (i = 0; i < countof(bp->shader_program); i++)
+      {
+        char *fn = (char *)
+          malloc (strlen(dir) + strlen(name) + strlen(ext) + 20);
+        struct stat st;
+
+        if (i == countof(bp->shader_program) - 1)
+          sprintf (fn, "%s/%s-%s.%s", dir, name, "c", ext);
+        else
+          sprintf (fn, "%s/%s-%d.%s", dir, name, i, ext);
+
+        if (i == 0 && !!stat (fn, &st))
+          sprintf (fn, "%s/%s.%s", dir, name, ext);
+
+        if (!stat (fn, &st))
+          switch (i) {
+          case 0: shader_file0 = strdup (fn); break;
+          case 1: shader_file1 = strdup (fn); break;
+          case 2: shader_file2 = strdup (fn); break;
+          case 3: shader_file3 = strdup (fn); break;
+          case 4: shader_file4 = strdup (fn); break;
+          case 5: shader_file_common = strdup (fn); break;
+          default: abort(); break;
+          }
+        free (fn);
+      }
+    free (name);
+  }
+# elif defined(HAVE_ANDROID)
+  /* Under Android, search for any files whose names match "progname-N.glsl",
+     except that these pseudo-files are "assets" instead.
+   */
+  {
+    const char *ext = "glsl";
+    const char *dir = ext;
+    char *name = strdup (progname);
+    char *s;
+    for (s = name; *s; s++) *s = tolower(*s);
+
+    for (i = 0; i < countof(bp->shader_program); i++)
+      {
+        char *body;
+        char *fn = (char *) malloc (strlen(name) + strlen(ext) + 20);
+  
+        if (i == countof(bp->shader_program) - 1)
+          sprintf (fn, "%s-c.%s", name, ext);
+        else
+          sprintf (fn, "%s-%d.%s", name, i, ext);
+  
+        body = android_read_asset_file (MI_WINDOW(mi), dir, fn);
+        if (i == 0 && !body)
+          {
+            sprintf (fn, "%s.%s", name, ext);
+            body = android_read_asset_file (MI_WINDOW(mi), dir, fn);
+          }
+  
+        if (body)
+          {
+            bp->shader_program[i] = body;
+            switch (i) {
+            case 0: shader_file0 = strdup (fn); break;
+            case 1: shader_file1 = strdup (fn); break;
+            case 2: shader_file2 = strdup (fn); break;
+            case 3: shader_file3 = strdup (fn); break;
+            case 4: shader_file4 = strdup (fn); break;
+            case 5: shader_file_common = strdup (fn); break;
+            default: abort(); break;
+            }
+          }
+        free (fn);
+      }
+    free (name);
+  }
+# endif /* HAVE_ANDROID */
+
+
+# ifndef HAVE_ANDROID /* X11, Cocoa and iOS read files with fopen. */
+  {
+    int j;
+    FILE *in = 0, *stdin = 0;
+    Bool nl_p = True;
+    int order[] = { 5, 0, 1, 2, 3, 4 };    /* Read "common" first on stdin */
+
+    for (j = 0; j < countof (bp->shader_program); j++)
+      {
+        int i = order[j];
+        const char *fn = (i == 0 ? shader_file0 :
+                          i == 1 ? shader_file1 :
+                          i == 2 ? shader_file2 :
+                          i == 3 ? shader_file3 :
+                          i == 4 ? shader_file4 :
+                          i == 5 ? shader_file_common : 0);
+
+        char buf[255];
+        int res;
+        int len = 0;
+        int size = 0;
+
+        if (!fn || !*fn || !strcasecmp (fn, DEF_SHADER_FILE0))
+          continue;
+        else if (!!strcmp (fn, "-"))
+          in = fopen (fn, "r");
+        else
+          {
+            in = (stdin ? stdin : fdopen (STDIN_FILENO, "r"));
+            stdin = in;
+          }
+
+        if (!in)
+          {
+            sprintf (buf, "%s: error reading \"%.200s\"", progname, fn);
+            perror (buf);
+            exit (1);
+          }
+
+        bp->shader_program[i] = NULL;
+
+        while (fgets (buf, sizeof(buf)-1, in))
+          {
+            res = strlen (buf);
+            if (nl_p && stdin &&
+                !strcmp (buf, ".\n"))  /* "." alone on a line is EOF */
+              break;
+            nl_p = (res > 0 && buf[res-1] == '\n');
+            if (len + res >= size)
+              {
+                size += sizeof(buf);
+                bp->shader_program[i] =
+                  (bp->shader_program[i]
+                   ? realloc (bp->shader_program[i], size)
+                   : malloc (size));
+                if (!bp->shader_program[i]) abort();
+              }
+            memcpy (bp->shader_program[i] + len, buf, res);
+            len += res;
+            bp->shader_program[i][len] = 0;
+          }
+
+        if (!stdin)
+          {
+            fclose (in);
+            in = 0;
+          }
+
+        if (!bp->shader_program[i] || !*bp->shader_program[i] ||
+            strlen (bp->shader_program[i]) < 10)
+          {
+            fprintf (stderr, "%s: no program in \"%s\"\n", progname,
+                     fn);
+            exit (1);
+          }
+      }
+
+    if (in)
+      fclose (in);
+  }
+
+# endif /* !HAVE_ANDROID */
+
+  if (!bp->shader_program[0] || !*bp->shader_program[0])
+    {
+      fprintf (stderr, "%s: no --program specified\n", progname);
+      exit (1);
+    }
+
+  {
+    double mouse_speed = 0.01 * speed * automouse_speed;
+    bp->rot = make_rotator (0, 0, 0, 0, mouse_speed, False);
+  }
+
+  init_glsl (mi);
+
+  bp->total_frames = 0;
+  bp->start_time   = double_time();
+  bp->last_time    = bp->start_time;
+  {
+    time_t t = bp->start_time;
+    struct tm *tm = localtime (&t);
+    bp->now = *tm;
+  }
+  
+# ifndef HAVE_JWXYZ
+  /* Put the name of this script in the window title, in case it was launched
+     with "exec -a" to set argv[0] to something other than "xshadertoy".
+   */
+  if (!MI_WIN_IS_INROOT(mi))
+    {
+      char *s, *s1;
+      XFetchName (MI_DISPLAY(mi), MI_WINDOW(mi), &s);
+      s1 = s ? strchr (s, ':') : 0;
+      if (s1)
+        {
+          const char *s2, *s3;
+          *s1 = 0;
+          s2 = s1+1;
+          while (*s2 == ' ') s2++;
+          s3 = strrchr (progname, '/');
+          s3 = s3 ? s3+1 : progname;
+          if (!!strcasecmp (progname, s))
+            {
+              char *s4 = (char *)
+                malloc (strlen(s) + strlen(s2) + strlen(s3) + 10);
+              sprintf (s4, "%s: %s: %s", s, s3, s2);
+              XStoreName (MI_DISPLAY(mi), MI_WINDOW(mi), s4);
+              free (s4);
+            }
+        }
+      if (s) free (s);
+    }
+# endif /* HAVE_JWXYZ */
+
+}
+
+
+ENTRYPOINT void
+draw_xshadertoy (ModeInfo *mi)
+{
+  xshadertoy_configuration *bp = &bps[MI_SCREEN(mi)];
+  Display *dpy = MI_DISPLAY(mi);
+  Window window = MI_WINDOW(mi);
+  double now = double_time();
+  int mx, my, mz, mw;
+  int i;
+
+  if (!bp->glx_context)
+    return;
+
+  now = bp->start_time + (now - bp->start_time) * speed;  /* Time warp */
+
+  /* Shadertoy mouse input is, shall we say, idiosyncratic.  Test cases:
+     https://www.shadertoy.com/view/Mss3zH
+     https://www.shadertoy.com/view/MdXyzX */
+  {
+    int x, y;
+
+    if (automouse_p)   /* Hold button forever and drag sinusoidally. */
+      {
+        double dx, dy, dz;
+        get_position (bp->rot, &dx, &dy, &dz, True);
+        x = dx * (MI_WIDTH(mi));
+        y = dy * (MI_HEIGHT(mi));
+        bp->button_down_p = True;
+      }
+    else
+      {
+        Window r, c;
+        int rx, ry;
+        unsigned int m;
+        XQueryPointer (MI_DISPLAY (mi), MI_WINDOW (mi),
+                       &r, &c, &rx, &ry, &x, &y, &m);
+      }
+
+    y = MI_HEIGHT(mi) - 1 - y;
+
+    if (x < 1) x = 1;    /* 0 means "button not down" */
+    if (y < 1) y = 1;
+    if (x >= MI_WIDTH(mi))  x = MI_WIDTH(mi)  - 1;
+    if (y >= MI_HEIGHT(mi)) y = MI_HEIGHT(mi) - 1;
+
+    if (bp->button_down_p && !bp->was_button_down_p)   /* Drag beginning */
+      {
+        mx = x;
+        my = y;
+        mz = x;
+        mw = y;
+        bp->mouse_clicked.x = x;
+        bp->mouse_clicked.y = y;
+      }
+    else if (bp->button_down_p)                                /* Drag continuing */
+      {
+        mx =  x;
+        my =  y;
+        mz =  bp->mouse_clicked.x;
+        mw = -bp->mouse_clicked.y;
+        bp->mouse_dragged.x = x;
+        bp->mouse_dragged.y = y;
+      }
+    else if (!bp->button_down_p && bp->was_button_down_p) /* Drag released */
+      {
+        mx =  x;
+        my =  y;
+        mz = -bp->mouse_clicked.x;
+        mw = -bp->mouse_clicked.y;
+        bp->mouse_dragged.x = x;
+        bp->mouse_dragged.y = y;
+      }
+    else                                               /* Not dragging */
+      {
+        mx =  bp->mouse_dragged.x;
+        my =  bp->mouse_dragged.y;
+        mz = -bp->mouse_clicked.x;
+        mw = -bp->mouse_clicked.y;
+      }
+
+    mx *= scale;
+    my *= scale;
+    mz *= scale;
+    mw *= scale;
+
+    bp->was_button_down_p = bp->button_down_p;
+  }
+
+  /* Shadertoy keyboard input is insane: you have to feed it a texture map
+     as input that has a bit set for the ASCII character of each key that is
+     down.  So we're not doing that.  https://www.shadertoy.com/view/lsXGzf */
+
+  /* "iDate" is year, month, day and fractional-seconds-since-midnight.
+     Only recompute once a second, since localtime and mktime are a lot.
+     Test case: https://www.shadertoy.com/view/lsXGz8 */
+  if (now >= bp->last_tm + 1)
+    {
+      time_t t      = now;
+      struct tm *tm = localtime (&t);
+      bp->now       = *tm;
+      bp->last_tm   = t;
+      tm->tm_hour   = tm->tm_min = tm->tm_sec = 0;
+      bp->midnight  = mktime (tm);
+    }
+
+  glXMakeCurrent (MI_DISPLAY(mi), MI_WINDOW(mi), *bp->glx_context);
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+# ifdef HAVE_GLSL
+
+  for (i = 0; i < countof(bp->channels); i++)
+    {
+      Bool last_p = (i == countof(bp->channels) - 1 ||
+                     !bp->shader_program[i + 1]);
+      int j;
+
+      if (!bp->channels[i].poly_shader_program)
+        continue;
+
+      glUseProgram (bp->channels[i].poly_shader_program);
+
+      /* Bind to this layer's output buffer */
+      glBindFramebuffer (GL_DRAW_FRAMEBUFFER, bp->channels[i].draw_fbo);
+      glBindFramebuffer (GL_READ_FRAMEBUFFER, bp->channels[i].read_fbo);
+
+      for (j = 0; j < countof(bp->channels); j++)
+        {
+          if (!bp->channels[j].tex ||
+              bp->channels[i].frag_ichan[j] < 0)
+            continue;
+          glActiveTexture (GL_TEXTURE0 + j);
+          glBindTexture (GL_TEXTURE_2D, bp->channels[j].tex);
+          glUniform1i (bp->channels[i].frag_ichan[j], j);
+        }
+
+      glUniform3f (bp->channels[i].frag_irez,
+                   MI_WIDTH(mi) * scale,
+                   MI_HEIGHT(mi) * scale,
+                   1);
+      glUniform1f (bp->channels[i].frag_itime,  now - bp->start_time);
+      glUniform1f (bp->channels[i].frag_idelta, now - bp->last_time);
+      glUniform1f (bp->channels[i].frag_ifps,
+                   bp->total_frames / (now - bp->start_time));
+      glUniform1i (bp->channels[i].frag_iframe, bp->total_frames);
+      glUniform4f (bp->channels[i].frag_imouse, mx, my, mz, mw);
+      glUniform4f (bp->channels[i].frag_idate,
+                   bp->now.tm_year + 1900,
+                   bp->now.tm_mon + 1,
+                   bp->now.tm_mday,
+                   now - bp->midnight);
+
+      if (bp->channels[i].poly_pos < 0) abort();
+      if (bp->vao)
+        glBindVertexArray (bp->vao);
+      glBindBuffer (GL_ARRAY_BUFFER, bp->vertex_pos_buffer);
+      glVertexAttribPointer (bp->channels[i].poly_pos, 2,
+                             GL_FLOAT, GL_FALSE, 0, 0);
+      glEnableVertexAttribArray (bp->channels[i].poly_pos);
+      glDrawArrays (GL_TRIANGLES, 0, 6);
+      glBindBuffer (GL_ARRAY_BUFFER, 0);
+      if (bp->vao)
+        glBindVertexArray (0);
+
+      glUseProgram (0);
+
+      if (last_p)
+        break;
+    }
+
+  glBindFramebuffer (GL_READ_FRAMEBUFFER, bp->channels[i].draw_fbo);
+  glBindFramebuffer (GL_DRAW_FRAMEBUFFER, bp->win_draw_fbo);
+
+  glBlitFramebuffer (0, 0, MI_WIDTH(mi) * scale, MI_HEIGHT(mi) * scale,
+                     0, 0, MI_WIDTH(mi), MI_HEIGHT(mi),
+                     GL_COLOR_BUFFER_BIT, GL_LINEAR);
+
+  glBindFramebuffer (GL_READ_FRAMEBUFFER, bp->win_read_fbo);
+
+# endif /* HAVE_GLSL */
+
+  bp->last_time = now;
+  bp->total_frames++;
+
+#ifndef HAVE_MOBILE  // #### texfont not working with GLSL
+  if (mi->fps_p) do_fps (mi);
+#endif
+  glFinish();
+
+  glXSwapBuffers(dpy, window);
+}
+
+
+ENTRYPOINT void
+free_xshadertoy (ModeInfo *mi)
+{
+  xshadertoy_configuration *bp = &bps[MI_SCREEN(mi)];
+  int i;
+  if (!bp->glx_context) return;
+  for (i = 0; i < countof(bp->shader_program); i++)
+    if (bp->shader_program[i]) free (bp->shader_program[i]);
+  if (bp->rot) free_rotator (bp->rot);
+# ifdef HAVE_GLSL
+  glUseProgram (0);
+  glBindBuffer (GL_ARRAY_BUFFER, 0);
+  for (i = 0; i < countof(bp->channels); i++)
+    {
+      if (bp->channels[i].poly_shader_program)
+        glDeleteProgram (bp->channels[i].poly_shader_program);
+    }
+  delete_framebuffers (mi);
+  glDeleteBuffers (1, &bp->vertex_pos_buffer);
+  if (bp->vao)
+    glDeleteVertexArrays (1, &bp->vao);
+
+# endif
+}
+
+XSCREENSAVER_MODULE ("XShadertoy", xshadertoy)
+
+#endif /* USE_GL */
diff --git a/hacks/glx/xshadertoy.man b/hacks/glx/xshadertoy.man
new file mode 100644 (file)
index 0000000..e5ada20
--- /dev/null
@@ -0,0 +1,93 @@
+.TH XScreenSaver 1 "" "X Version 11"
+.SH NAME
+xshadertoy \- screen saver for Shadertoy GLSL programs.
+.SH SYNOPSIS
+.B xshadertoy
+[\-\-display \fIhost:display.screen\fP]
+[\-\-visual \fIvisual\fP]
+[\-\-window]
+[\-\-root]
+[\-\-delay \fInumber\fP]
+[\-\-speed \fInumber\fP]
+[\-\-scale \fInumber\fP]
+[\-\-automouse]
+[\-\-automouse\-speed \fInumber\fP]
+[\-\-program\-common \fIfile\fP]
+[\-\-program0 \fIfile\fP]
+[\-\-program1 \fIfile\fP]
+[\-\-program2 \fIfile\fP]
+[\-\-program3 \fIfile\fP]
+[\-\-program4 \fIfile\fP]
+[\-\-fps]
+.SH DESCRIPTION
+Runs arbitrary GLSL programs that use the shadertoy.com API.
+.SH OPTIONS
+.TP 8
+.B \-\-visual \fIvisual\fP
+Specify which visual to use.  Legal values are the name of a visual class,
+or the id number (decimal or hex) of a specific visual.
+.TP 8
+.B \-\-window
+Draw on a newly-created window.  This is the default.
+.TP 8
+.B \-\-root
+Draw on the root window.
+.TP 8
+.B \-\-delay \fInumber\fP
+Per-frame delay, in microseconds.  Default: 20000 (0.02 seconds).
+.TP 8
+.B \-\-speed \fInumber\fP
+Animation speed.  2.0 means twice as fast, 0.5 means half as fast.
+.TP 8
+.B \-\-scale \fInumber\fP
+Frame buffer resolution.  0.5 means halve the resolution for better
+performance but lower quality output.  Default 1.0, full quality.
+.TP 8
+.B \-\-program0 \fIfile\fP
+.TP 8
+.B \-\-program1 \fIfile\fP
+.TP 8
+.B \-\-program2 \fIfile\fP
+.TP 8
+.B \-\-program3 \fIfile\fP
+.TP 8
+.B \-\-program4 \fIfile\fP
+GLSL code, each as an input to the previous.
+.TP 8
+.B \-\-program\-common \fIfile\fP
+GLSL code to prepend to each program.
+.TP 8
+.B \-\-automouse | \-\-no\-automouse
+Whether to pretend to drag the mouse around sinusoidally.  Default false.
+.TP 8
+.B \-\-automouse\-speed \fIratio\fP
+How fast. Default 1.0.
+.TP 8
+.B \-\-fps | \-\-no\-fps
+Whether to show a frames-per-second display at the bottom of the screen.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+to get the default host and display number.
+.TP 8
+.B XENVIRONMENT
+to get the name of a resource file that overrides the global resources
+stored in the RESOURCE_MANAGER property.
+.TP 8
+.B XSCREENSAVER_WINDOW
+The window ID to use with \fI\-\-root\fP.
+.SH SEE ALSO
+.BR X (1),
+.BR xscreensaver (1),
+.BR https://www.shadertoy.com/
+.SH COPYRIGHT
+Copyright \(co 2025 by Jamie Zawinski.  Permission to use, copy, modify, 
+distribute, and sell this software and its documentation for any purpose is 
+hereby granted without fee, provided that the above copyright notice appear 
+in all copies and that both that copyright notice and this permission notice
+appear in supporting documentation.  No representations are made about the 
+suitability of this software for any purpose.  It is provided "as is" without
+express or implied warranty.
+.SH AUTHOR
+Jamie Zawinski.
index 46aa4dc7b1b655b0b2dda81c75d2fdfb8f5dfd8b..b0e66a03813a8be159586b06c13374b644735f8c 100644 (file)
@@ -1,4 +1,4 @@
-# hacks/images/Makefile.in --- xscreensaver, Copyright © 2018-2021 Jamie Zawinski.
+# hacks/images/Makefile.in --- xscreensaver, Copyright © 2018-2025 Jamie Zawinski.
 # the `../configure' script generates `hacks/images/Makefile' from this file.
 
 
@@ -46,7 +46,7 @@ clean:
 # Note: don't remove the generated Makefile.  We include that in the tar file
 # so that OSX and Android can run 'make' in this directory without 'configure'.
 distclean:: clean
-       -rm -f TAGS *~ "#"*
+       -rm -f TAGS ./*~ "#"*
 
 list_tarfiles:
        @find $(TARFILES) -type f -print | sort
index 6bdfbb0e519f493aa7f89e78f6b8f9b15ae7f425..ac0d2b0a3c7afeb5c925319d3f445e036c76fff1 100644 (file)
@@ -1,4 +1,4 @@
-# hacks/images/Makefile.in --- xscreensaver, Copyright © 2018-2021 Jamie Zawinski.
+# hacks/images/Makefile.in --- xscreensaver, Copyright © 2018-2025 Jamie Zawinski.
 # the `../configure' script generates `hacks/images/Makefile' from this file.
 
 @SET_MAKE@
@@ -46,7 +46,7 @@ clean:
 # Note: don't remove the generated Makefile.  We include that in the tar file
 # so that OSX and Android can run 'make' in this directory without 'configure'.
 distclean:: clean
-       -rm -f TAGS *~ "#"*
+       -rm -f TAGS ./*~ "#"*
 
 list_tarfiles:
        @find $(TARFILES) -type f -print | sort
index 30f338c98c1dffb8d47437971c9fc07fab1f6733..304a592ff15ab849aaff6aa15a2f551b4c446d6e 100755 (executable)
@@ -4,10 +4,10 @@ TARGET=$1
 shift
 SRCS=$*
 
-TMP1=m6502.h.1.$$
-TMP2=m6502.h.2.$$
+TMP1="m6502.h.1.$$"
+TMP2="m6502.h.2.$$"
 rm -f $TMP1 $TMP2
-trap "rm -f $TMP1 $TMP2" 1 2 3 15 EXIT
+trap 'rm -f $TMP1 $TMP2' 1 2 3 15 EXIT
 
 if [ -z "$UTILS_SRC" ]; then UTILS_SRC="../utils"; fi
 
@@ -17,10 +17,10 @@ for f in $SRCS ; do
     sed 's/",$/\\n"/' >> $TMP2
   echo ',' >> $TMP2
 done
-rm -f $TMP1
-if cmp -s $TMP2 $TARGET ; then
-  rm -f $TMP2
+rm -f "$TMP1"
+if cmp -s "$TMP2" "$TARGET" ; then
+  rm -f "$TMP2"
 else
-  mv $TMP2 $TARGET
+  mv "$TMP2" "$TARGET"
 fi
 
index 87196c44a7eb25a5f9ed9d454c12896610344853..731c50cb1529860b122c53270610a90b8180731a 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2008-2022 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2008-2026 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -18,7 +18,7 @@ use diagnostics;
 use strict;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.16 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.17 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -106,10 +106,12 @@ sub munge_ad($) {
     local $/ = undef;  # read entire file
     my $b = <$in>;
     close $in;
+    my ($oname) = ($xml =~ m@/([^/]+)\.xml$@si);
     my ($name)  = ($b =~ m@<screensaver[^<>]* \b name   = \" ([^<>\"]+) \"@sx);
     my ($label) = ($b =~ m@<screensaver[^<>]* \b _label = \" ([^<>\"]+) \"@sx);
     error ("$xml: no name") unless $name;
     error ("$xml: no label") unless $label;
+    error ("$xml: mismatched name: $oname") unless ($name eq $oname);
 
     my $label2 = lc($name);
     $label2 =~ s/^((x|gl)?[a-z])/\U$1/s;  # what prefs.c (make_hack_name) does
@@ -151,6 +153,8 @@ sub munge_ad($) {
     my $glep = ($hack eq 'extrusion');
     if (-f "$hack.c" || -f "$hack") { $glp = 0; }
     elsif (-f "glx/$hack.c") { $glp = 1; }
+    elsif (-f "glx/glsl/$hack.glsl") { $glp = 1; }
+    elsif (-f "glx/glsl/$hack-0.glsl") { $glp = 1; }
     elsif ($hack eq 'companioncube') { $glp = 1; }  # kludge
     elsif ($dis != 2) { error ("is $hack X or GL?"); }
 
index 303d90b0fbf4e389402fc3dce77d0054fa365b7e..14657053604769c9c3efe846b8f3f46f3758aead 100644 (file)
@@ -1,4 +1,4 @@
-/* recanim, Copyright © 2014-2025 Jamie Zawinski <jwz@jwz.org>
+/* recanim, Copyright © 2014-2026 Jamie Zawinski <jwz@jwz.org>
  * Record animation frames of the running screenhack.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -8,6 +8,25 @@
  * documentation.  No representations are made about the suitability of this
  * software for any purpose.  It is provided "as is" without express or 
  * implied warranty.
+ *
+ * When configured --with-record-animation, each screenhack takes a
+ * "-record-animation DUR" arg that will cause it to run for exactly that
+ * many frames, and write a "progname.mp4" file into the current directory.
+ * "DUR" may be a number of frames, or a time specified as H:MM:SS, "N sec",
+ * etc. at 30 FPS.
+ *
+ * The MP4 file will be written at 30 FPS, and it is therefore assumed that
+ * each frame of the screenhack took 1/30th second to render and display,
+ * regardless of the --delay option, or how long it actually took; so using
+ * --delay 0 will speed up encoding.
+ *
+ * Likewise, any calls the saver makes to time(), double_time() or
+ * gettimeofday() will be falsified to maintain this timing illusion.
+ * Even if it takes 2 minutes to write out 30 seconds of video, the
+ * screenhack will only see the wall clock advance by 30 seconds.
+ *
+ * This is how I generate the videos for the XScreenSaver YouTube playlist:
+ * https://www.youtube.com/playlist?list=PLbe67PprBSpqM_-HU49fmIS8ncApw4i08
  */
 
 #include "screenhackI.h"
@@ -50,6 +69,8 @@
 
 #undef gettimeofday  /* wrapped by recanim.h */
 #undef time
+#undef double_time
+extern double double_time(void);
 
 struct record_anim_state {
   Screen *screen;
@@ -80,7 +101,7 @@ struct record_anim_state {
    down that clock by discounting the time taken up by snapshotting and
    saving the frame.
  */
-static double recanim_time_warp = 0;
+static double recanim_current_time = 0;
 
 void
 screenhack_record_anim_gettimeofday (struct timeval *tv
@@ -89,13 +110,10 @@ screenhack_record_anim_gettimeofday (struct timeval *tv
 # endif
                                      )
 {
-  gettimeofday (tv
-# ifdef GETTIMEOFDAY_TWO_ARGS
-                , tz
-# endif
-                );
-  tv->tv_sec  -= (time_t) recanim_time_warp;
-  tv->tv_usec -= 1000000 * (recanim_time_warp - (time_t) recanim_time_warp);
+  /* recanim_current_time == 0 if we are not recording. */
+  double now = (recanim_current_time ? recanim_current_time : double_time());
+  tv->tv_sec  = (time_t) now;
+  tv->tv_usec = 1000000 * (now - tv->tv_sec);
 }
 
 time_t
@@ -115,6 +133,22 @@ screenhack_record_anim_time (time_t *o)
 }
 
 
+double
+screenhack_record_anim_double_time (void)
+{
+  struct timeval tv;
+# ifdef GETTIMEOFDAY_TWO_ARGS
+  struct timezone tz;
+# endif
+  screenhack_record_anim_gettimeofday (&tv
+# ifdef GETTIMEOFDAY_TWO_ARGS
+                                       , &tz
+# endif
+                                       );
+  return (tv.tv_sec + ((double) tv.tv_usec * 0.000001));
+}
+
+
 record_anim_state *
 screenhack_record_anim_init (Screen *screen, Window window, int target_frames)
 {
@@ -137,6 +171,8 @@ screenhack_record_anim_init (Screen *screen, Window window, int target_frames)
   st->frame_count = 0;
   st->fade_frames = st->fps * 1.5;
 
+  recanim_current_time = st->start_time;
+
   if (st->fade_frames >= (st->target_frames / 2) - st->fps)
     st->fade_frames = 0;
 
@@ -214,7 +250,6 @@ fade_frame (record_anim_state *st, unsigned char *data, double ratio)
 void
 screenhack_record_anim (record_anim_state *st)
 {
-  double start_time = double_time();
   int obpl    = st->img->bytes_per_line;
   char *odata = st->img->data;
 
@@ -350,7 +385,8 @@ screenhack_record_anim (record_anim_state *st)
   if (++st->frame_count >= st->target_frames)
     screenhack_record_anim_free (st);
 
-  recanim_time_warp += double_time() - start_time;
+  /* Report to screenhack that each frame took exactly 1/30th second. */
+  recanim_current_time += 1.0 / st->fps;
 }
 
 
@@ -361,8 +397,11 @@ screenhack_record_anim_free (record_anim_state *st)
   Display *dpy = DisplayOfScreen (st->screen);
 # endif /* !USE_GL */
   struct stat s;
-
-  fprintf (stderr, "%s: wrote %d frames\n", progname, st->frame_count);
+  double real_end     = double_time();
+  double virt_end     = screenhack_record_anim_double_time();
+  double real_elapsed = real_end - st->start_time;
+  double virt_elapsed = virt_end - st->start_time;
+  double video_dur    = st->frame_count / (double) st->fps;
 
 # ifdef USE_GL
   free (st->data2);
@@ -378,12 +417,28 @@ screenhack_record_anim_free (record_anim_state *st)
 
   if (stat (st->outfile, &s))
     {
-      fprintf (stderr, "%s: %s was not created\n", progname, st->outfile);
+      fprintf (stderr, "%s: error writing %s\n", progname, st->outfile);
       exit (1);
     }
 
-  fprintf (stderr, "%s: wrote %s (%.1f MB)\n", progname, st->outfile,
+# define FMT "%-24.24s %d:%02d:%02d  %5.1f fps"
+  fprintf (stderr, FMT ", %d frames, %.1f MB\n", st->outfile,
+           (((int)video_dur)/60/60),
+           (((int)video_dur)/60)%60,
+           ((int)video_dur)%60,
+           (double) st->fps,
+           st->frame_count,
            s.st_size / (float) (1024 * 1024));
+  fprintf (stderr, FMT "\n", "elapsed virtual",
+           (((int)virt_elapsed)/60/60),
+           (((int)virt_elapsed)/60)%60,
+           ((int)virt_elapsed)%60,
+           st->frame_count / virt_elapsed);
+  fprintf (stderr, FMT "\n", "elapsed actual",
+           (((int)real_elapsed)/60/60),
+           (((int)real_elapsed)/60)%60,
+           ((int)real_elapsed)%60,
+           st->frame_count / real_elapsed);
 
   if (st->title)
     free (st->title);
index 16021e3ec4a88f457dda10dfdb0ced42af8c0520..5f5b1851d7f7d6075679668dc87550ecb7237067 100644 (file)
@@ -1,4 +1,4 @@
-/* recanim, Copyright (c) 2014-2021 Jamie Zawinski <jwz@jwz.org>
+/* recanim, Copyright © 2014-2026 Jamie Zawinski <jwz@jwz.org>
  * Record animation frames of the running screenhack.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
@@ -28,5 +28,6 @@ extern void screenhack_record_anim_gettimeofday (struct timeval *
                                                  );
 #define time screenhack_record_anim_time
 #define gettimeofday screenhack_record_anim_gettimeofday
+#define double_time screenhack_record_anim_double_time
 
 #endif /* __XSCREENSAVER_RECORD_ANIM_H__ */
index dab3e878ab99937efabcf7bed245dafe3835ae48..8c5aa3bd6d82197c53e58e519c3e251825de59c2 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright © 1992-2025 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1992-2026 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 # if defined(HAVE_COCOA) && !defined(HAVE_IPHONE)  /* macOS */
 #  include <OpenGL/gl.h>
 #  include <OpenGL/glu.h>
+#  define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
+#  ifndef GL_SILENCE_DEPRECATION
+#   define GL_SILENCE_DEPRECATION
+#  endif
+#  include <OpenGL/gl3.h>
+#  undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
 # elif defined(HAVE_IPHONE)
 #  ifdef HAVE_GLES3
 #   include "OpenGLES/ES3/gl.h"
index a13556c3d4e5a181ff29313cbb336c47a3bb4411..1312895905729b9cd964614828b672c29c18b1c4 100755 (executable)
@@ -1,5 +1,5 @@
 #!/usr/bin/perl -w
-# Copyright © 2002-2023 Jamie Zawinski <jwz@jwz.org>
+# Copyright © 2002-2025 Jamie Zawinski <jwz@jwz.org>
 #
 # Permission to use, copy, modify, distribute, and sell this software and its
 # documentation for any purpose is hereby granted without fee, provided that
@@ -24,7 +24,7 @@ use strict;
 use Text::Wrap;
 
 my $progname = $0; $progname =~ s@.*/@@g;
-my ($version) = ('$Revision: 1.15 $' =~ m/\s(\d[.\d]+)\s/s);
+my ($version) = ('$Revision: 1.16 $' =~ m/\s(\d[.\d]+)\s/s);
 
 my $verbose = 0;
 
@@ -90,11 +90,10 @@ sub xml2man($) {
   error ("$xml does not exist") if (! -f $xml);
   error ("$man already exists") if (-f $man);
 
-  local *IN;
-  open (IN, "<$xml") || error ("$xml: $!");
+  open (my $in, '<:utf8', $xml) || error ("$xml: $!");
   my $xmltxt = "";
-  while (<IN>) { $xmltxt .= $_; }
-  close IN;
+  while (<$in>) { $xmltxt .= $_; }
+  close ($in);
 
   my $args = "";
   my $body = "";
@@ -215,6 +214,8 @@ sub xml2man($) {
 
   $desc =~ s@https?://en\.wikipedia\.org/[^\s]+@@gs;
 
+  my $url = ($desc =~ s@(https?://www\.shadertoy\.com/[^\s]+)@@gs) ? $1 : undef;
+
   $desc = wrap ("", "", $desc);
 
   $body = (".TH XScreenSaver 1 \"\" \"X Version 11\"\n" .
@@ -231,16 +232,18 @@ sub xml2man($) {
            $body .
            $man_suffix);
 
+  $body =~ s/(\n\.BR[^\n]+)(\n\.SH)/$1,\n.BR $url$2/s
+    if ($url);
+
   my $year = $1 if ($author =~ s/; (\d{4})$//s);
   $year = (localtime)[5] + 1900 unless $year;
 
   $body =~ s/%AUTHOR%/$author/g;
   $body =~ s/%YEAR%/$year/g;
 
-  local *OUT;
-  open (OUT, ">$man") || error ("$man: $!");
-  print OUT $body || error ("$man: $!");
-  close OUT || error ("$man: $!");
+  open (my $out, '>:utf8', $man) || error ("$man: $!");
+  print $out $body || error ("$man: $!");
+  close ($out) || error ("$man: $!");
   print STDERR "$progname: wrote $man\n";
 }
 
index 29a2cb925b4986512c0f328141d689a34f88b964..2f3397c5d9176e47f3fa89fa5e25e1de86f5b366 100644 (file)
@@ -2121,7 +2121,7 @@ get_image (Screen *screen,
                           verbose_p, &geom))
         goto COLORBARS;
       file_prop = file;
-      get_file_xattrs (file, &xattr_url, &xattr_title);
+      get_file_xattrs ((absfile ? absfile : file), &xattr_url, &xattr_title);
       break;
 
     case GRAB_VIDEO:
index 53f7189fcdd159594b9f5ad1749877bce56da1d1..0d1127df93a80646bfd602655885c27b6ca4fc34 100644 (file)
@@ -1,4 +1,4 @@
-# utils/Makefile.in --- xscreensaver, Copyright © 1997-2023 Jamie Zawinski.
+# utils/Makefile.in --- xscreensaver, Copyright © 1997-2025 Jamie Zawinski.
 # the `../configure' script generates `jwxyz/Makefile' from this file.
 
 # JWXYZ Is Not Xlib.
@@ -79,7 +79,7 @@ depend:
 # to include only dependencies on files which are themselves a part of this
 # package.
 distdepend::
-       @echo updating dependencies in `pwd`/Makefile.in... ;               \
+       @echo "updating dependencies in `pwd`/Makefile.in..." ;             \
        $(DEPEND) -w 0 -f -                                                 \
        -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \
        $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --    \
@@ -92,8 +92,8 @@ distdepend::
              -e 's@ \([^$$]\)@ $$(srcdir)/\1@g'                            \
              -e 's@ $$(srcdir)/\(.*config.h\)@ \1@g' ;                     \
          echo ''                                                           \
-       ) > /tmp/distdepend.$$$$ &&                                         \
-       mv /tmp/distdepend.$$$$ Makefile.in
+       ) > "/tmp/distdepend.$$$$" &&                                       \
+       mv "/tmp/distdepend.$$$$" Makefile.in
 
 TAGS: tags
 tags:
index 8523bf62b3e420c68172cd6333af0b537bd2f5b8..9f282ef171b598a37b1dbc9274d10376d1debe87 100644 (file)
@@ -891,8 +891,7 @@ acquireClass (JNIEnv *env, const char *className, jobject *globalRef)
 
 
 /* Note: to find signature strings for native methods:
-   cd ./project/xscreensaver/build/intermediates/classes/debug/
-   javap -s -p org.jwz.xscreensaver.jwxyz
+   javap -s -p xscreensaver/build/intermediates/javac/debug/compileDebugJavaWithJavac/classes/org/jwz/xscreensaver/jwxyz.class
  */
 
 
@@ -1917,4 +1916,69 @@ jwxyz_png_to_ximage (Display *dpy, Visual *visual,
   return img;
 }
 
+// Returns a list of the asset files under the named subdir.
+// NULL if the directory does not exist.
+//
+char **
+android_list_asset_files (Window window, const char *dir)
+{
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jstring jstr = (*env)->NewStringUTF (env, dir);
+  jclass     c = (*env)->GetObjectClass (env, obj);
+  jmethodID  m = (*env)->GetMethodID (env, c, "listAssetFiles",
+                           "(Ljava/lang/String;)[Ljava/lang/String;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  jobjectArray array = (m
+                        ? (*env)->CallObjectMethod (env, obj, m, jstr)
+                        : NULL);
+  (*env)->DeleteLocalRef (env, c);
+  (*env)->DeleteLocalRef (env, jstr);
+
+  char **ret = 0;
+  if (array) {
+    int len = (*env)->GetArrayLength (env, array);
+    ret = (char **) calloc (len + 1, sizeof(*ret));
+    for (int i = 0; i < len; i++) {
+      jobject jvalue =
+        (jstring) ((*env)->GetObjectArrayElement (env, array, i));
+      if ((*env)->ExceptionOccurred(env)) abort();
+      ret[i] = jstring_dup (env, jvalue);
+    }
+  }
+
+  return ret;
+}
+
+// Returns the contents of the asset file "dir/file".
+// NULL if the file does not exist.
+//
+char *
+android_read_asset_file (Window window, const char *dir, const char *file)
+{
+  JNIEnv *env = window->window.rh->jni_env;
+  jobject obj = window->window.rh->jobject;
+
+  if ((*env)->ExceptionOccurred(env)) abort();
+  jstring jstr1 = (*env)->NewStringUTF (env, dir);
+  jstring jstr2 = (*env)->NewStringUTF (env, file);
+  jclass      c = (*env)->GetObjectClass (env, obj);
+  jmethodID   m = (*env)->GetMethodID (env, c, "readAssetFile",
+                 "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
+  if ((*env)->ExceptionOccurred(env)) abort();
+
+  jobject body = (m
+                  ? (*env)->CallObjectMethod (env, obj, m, jstr1, jstr2)
+                  : NULL);
+  (*env)->DeleteLocalRef (env, c);
+  (*env)->DeleteLocalRef (env, jstr1);
+  (*env)->DeleteLocalRef (env, jstr2);
+
+  char *ret = (body ? jstring_dup (env, body) : NULL);
+  return ret;
+}
+
 #endif /* HAVE_ANDROID */
index 207ba37a0bd81cc3f26c52b265d0c418bae944df..d388705b6f73ece82c161813dde0639d47709961 100644 (file)
@@ -472,6 +472,11 @@ extern void jwxyz_draw_NSImage_or_CGImage (Display *, Drawable,
                                            int exif_rotation);
 extern XImage *jwxyz_png_to_ximage (Display *, Visual *,
                                     const unsigned char *, unsigned long size);
+#ifdef HAVE_ANDROID
+extern char **android_list_asset_files (Window, const char *dir);
+extern char *android_read_asset_file (Window, const char *dir,
+                                      const char *file);
+#endif
 
 extern int XSetGraphicsExposures (Display *, GC, Bool);
 extern Bool XTranslateCoordinates (Display *, Window src_w, Window dest_w,
index f7fd69903e9dc22f2e7d8bd12a2c0539e2b065e9..10df9e4b77770ebe6dbdd080b8d58725514fa501 100644 (file)
@@ -1,4 +1,4 @@
-# Auto-generated: Tue Dec  2 17:18:02 PST 2025
+# Auto-generated: Thu Jan 15 14:28:57 PST 2026
 driver/demo-Gtk-conf.c
 driver/demo-Gtk.c
 driver/demo.ui
@@ -8,6 +8,7 @@ driver/subprocs.c
 driver/xscreensaver-settings.desktop.in
 driver/xscreensaver.desktop.in
 hacks/config/abstractile.xml
+hacks/config/alienbeacon.xml
 hacks/config/anemone.xml
 hacks/config/anemotaxis.xml
 hacks/config/ant.xml
@@ -20,6 +21,7 @@ hacks/config/atlantis.xml
 hacks/config/attraction.xml
 hacks/config/atunnel.xml
 hacks/config/barcode.xml
+hacks/config/batteredplanet.xml
 hacks/config/beats.xml
 hacks/config/binaryhorizon.xml
 hacks/config/binaryring.xml
@@ -76,6 +78,7 @@ hacks/config/drift.xml
 hacks/config/droste.xml
 hacks/config/dumpsterfire.xml
 hacks/config/dymaxionmap.xml
+hacks/config/elementalring.xml
 hacks/config/endgame.xml
 hacks/config/energystream.xml
 hacks/config/engine.xml
@@ -97,6 +100,7 @@ hacks/config/fliptext.xml
 hacks/config/flow.xml
 hacks/config/fluidballs.xml
 hacks/config/flurry.xml
+hacks/config/fluxcore.xml
 hacks/config/flyingtoasters.xml
 hacks/config/fontglide.xml
 hacks/config/forest.xml
@@ -107,6 +111,7 @@ hacks/config/geodesic.xml
 hacks/config/geodesicgears.xml
 hacks/config/gflux.xml
 hacks/config/gibson.xml
+hacks/config/gimbalharmonics.xml
 hacks/config/glblur.xml
 hacks/config/glcells.xml
 hacks/config/gleidescope.xml
@@ -130,6 +135,7 @@ hacks/config/handsy.xml
 hacks/config/headroom.xml
 hacks/config/helix.xml
 hacks/config/hexadrop.xml
+hacks/config/hexplasma.xml
 hacks/config/hexstrut.xml
 hacks/config/hextrail.xml
 hacks/config/highvoltage.xml
@@ -166,6 +172,7 @@ hacks/config/lisa.xml
 hacks/config/lissie.xml
 hacks/config/lmorph.xml
 hacks/config/lockward.xml
+hacks/config/logarithmiccircles.xml
 hacks/config/loop.xml
 hacks/config/m6502.xml
 hacks/config/mapscroller.xml
@@ -186,6 +193,8 @@ hacks/config/morph3d.xml
 hacks/config/mountain.xml
 hacks/config/munch.xml
 hacks/config/nakagin.xml
+hacks/config/neongravity.xml
+hacks/config/neontriangulator.xml
 hacks/config/nerverot.xml
 hacks/config/noof.xml
 hacks/config/noseguy.xml
@@ -208,6 +217,7 @@ hacks/config/polytopes.xml
 hacks/config/pong.xml
 hacks/config/popsquares.xml
 hacks/config/projectiveplane.xml
+hacks/config/protophore.xml
 hacks/config/providence.xml
 hacks/config/pulsar.xml
 hacks/config/pyro.xml
@@ -226,10 +236,12 @@ hacks/config/rubik.xml
 hacks/config/rubikblocks.xml
 hacks/config/sballs.xml
 hacks/config/scooter.xml
+hacks/config/selfreflect.xml
 hacks/config/shadebobs.xml
 hacks/config/sierpinski.xml
 hacks/config/sierpinski3d.xml
 hacks/config/skulloop.xml
+hacks/config/skyline.xml
 hacks/config/skytentacles.xml
 hacks/config/slidescreen.xml
 hacks/config/slip.xml
@@ -246,14 +258,18 @@ hacks/config/sproingies.xml
 hacks/config/squiral.xml
 hacks/config/squirtorus.xml
 hacks/config/stairs.xml
+hacks/config/stardome.xml
 hacks/config/starfish.xml
+hacks/config/starnest.xml
 hacks/config/starwars.xml
 hacks/config/stonerview.xml
 hacks/config/strange.xml
+hacks/config/stripeytorus.xml
 hacks/config/substrate.xml
 hacks/config/superquadrics.xml
 hacks/config/surfaces.xml
 hacks/config/swirl.xml
+hacks/config/synthwavecity.xml
 hacks/config/t3d.xml
 hacks/config/tangram.xml
 hacks/config/tessellimage.xml
@@ -261,9 +277,11 @@ hacks/config/testx11.xml
 hacks/config/thornbird.xml
 hacks/config/timetunnel.xml
 hacks/config/topblock.xml
+hacks/config/topologica.xml
 hacks/config/triangle.xml
 hacks/config/tronbit.xml
 hacks/config/truchet.xml
+hacks/config/truchetzoom.xml
 hacks/config/twang.xml
 hacks/config/unicrud.xml
 hacks/config/unknownpleasures.xml
index 42ee665f3f2086d9e78c10c1870d62609b3efcfa..e6a122a33321ea00381fc5505a0d323c1e1b7ad9 100644 (file)
@@ -166,7 +166,7 @@ depend:
 # to include only dependencies on files which are themselves a part of this
 # package.
 distdepend::
-       @echo updating dependencies in `pwd`/Makefile.in... ;               \
+       @echo "updating dependencies in `pwd`/Makefile.in..." ;             \
        $(DEPEND) -w 0 -f -                                                 \
        -s '# DO NOT DELETE: updated by make distdepend' $(DEPEND_FLAGS) -- \
        $(INCLUDES_1) $(DEFS) $(DEPEND_DEFINES) $(CFLAGS) $(X_CFLAGS) --    \
index e2bee9ab27ee60cb0797fffbc9cab3f2803deee0..5c34dd11213975bdfbb0aaaf4b7d2c32bbd857dc 100755 (executable)
@@ -30,7 +30,7 @@ NAME=`echo "$OUT" | sed \
   -e 's/[-.]/_/g' \
   -e 's/^\([^a-zA-Z]\)/_\1/'`;
 
-if [ x"$PERL" = "x" ]; then PERL=perl ; fi
+if [ -z "$PERL" ]; then PERL=perl ; fi
 
 # Perl fails if set to run in UTF-8 mode
 unset PERL5OPTS
index 03fc4050e9f2a7161f6dce4d274043e0b6ca67cf..af0cdcfcebe9236571746c27b4d4743b2ab8672e 100644 (file)
@@ -1,4 +1,4 @@
 static const char screensaver_id[] =
-       "@(#)xscreensaver 6.13 (02-Dec-2025), by Jamie Zawinski (jwz@jwz.org)";
-#define XSCREENSAVER_VERSION "6.13"
-#define XSCREENSAVER_RELEASED 1764705600
+       "@(#)xscreensaver 6.14 (15-Jan-2026), by Jamie Zawinski (jwz@jwz.org)";
+#define XSCREENSAVER_VERSION "6.14"
+#define XSCREENSAVER_RELEASED 1768507200
index 8f4135d4ffa1a8d7d8f0365c8a2314cd53264b1e..c933dc8a828f85ebe036be8ed4a7aec7011eb1ce 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright © 1999-2025 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright © 1999-2026 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 extern char *progname;
 
 
+#ifdef HAVE_EGL
+static EGLDisplay *
+get_egl_display (Screen *screen)
+{
+  Display *dpy = DisplayOfScreen (screen);
+  EGLDisplay *egl_display;
+  EGLAttrib av[10];
+  int ac = 0;
+
+# ifdef EGL_PLATFORM_X11_SCREEN_KHR
+  av[ac++] = EGL_PLATFORM_X11_SCREEN_KHR;
+  av[ac++] = (EGLAttrib) screen_number (screen);
+# endif
+  av[ac] = EGL_NONE;
+
+  egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, (void *) dpy, av);
+  if (!egl_display)
+    {
+      /* If you pass in a non-NULL EGLAttrib list to eglGetPlatformDisplay --
+         even an empty one, that is, the single terminator { EGL_NONE } --
+         you get the error, "no matching EGL config for X11 visual 0x21".
+         So it is impossible for us to inform EGL which X11 screen number
+         is in use, for any weirdos still using Zaphod multi-head. Oh well.
+       */
+      egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, (void *) dpy,
+                                           NULL);
+    }
+
+  return egl_display;
+}
+#endif /* HAVE_EGL */
+
+
 Visual *
 get_gl_visual (Screen *screen)
 {
@@ -58,30 +91,12 @@ get_gl_visual (Screen *screen)
   EGLConfig egl_config = 0;
   int egl_major = -1, egl_minor = -1;
 
-  /* If you pass in a non-NULL EGLAttrib list to eglGetPlatformDisplay --
-     even one with no elements, that is, the single terminator { EGL_NONE } --
-     you get the error, "no matching EGL config for X11 visual 0x21".
-     So it is impossible for us to inform EGL which X11 screen number
-     is in use, for any weirdos still using Zaphod multi-head.
-   */
-# if 1
-  EGLAttrib *av = NULL;
-# else
-  EGLAttrib av[10];
-  int ac = 0;
-#  ifdef EGL_PLATFORM_X11_SCREEN_KHR
-  av[ac++] = EGL_PLATFORM_X11_SCREEN_KHR;
-  av[ac++] = (EGLAttrib) screen_number (screen);
-#  endif
-  av[ac] = EGL_NONE;
-#endif
-
   /* This is re-used, no need to close it. */
-  egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR, (void *) dpy, av);
+  egl_display = get_egl_display (screen);
 
   if (!egl_display)
     {
-      fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname);
+      fprintf (stderr, "%s: eglGetPlatformDisplay failed (1)\n", progname);
       return 0;
     }
 
@@ -170,7 +185,8 @@ get_gl_visual (Screen *screen)
   int i = 0;
 
 # ifdef SB
-  if (! get_boolean_resource (dpy, "multiSample", "MultiSample"))
+  if (! get_boolean_resource (dpy, "multiSample", "MultiSample") ||
+      get_boolean_resource (dpy, "forceSingleSample", "ForceSingleSample"))
     i = SB_COUNT;  /* skip over the multibuffer entries in 'attrs' */
 # endif /* SB */
 
@@ -257,7 +273,8 @@ get_egl_config (Display *dpy, EGLDisplay *egl_display,
 
   i_start = 0;
 # ifdef SB
-  if (! get_boolean_resource (dpy, "multiSample", "MultiSample"))
+  if (! get_boolean_resource (dpy, "multiSample", "MultiSample") ||
+      get_boolean_resource (dpy, "forceSingleSample", "ForceSingleSample"))
     i_start = SB_COUNT;  /* skip over the multibuffer entries in 'attrs' */
 # endif /* SB */
 
@@ -343,11 +360,10 @@ describe_gl_visual (FILE *f, Screen *screen, Visual *visual,
 # ifdef HAVE_EGL
 
     /* This is re-used, no need to close it. */
-    egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR,
-                                         (void *) dpy, NULL);
+    egl_display = get_egl_display (screen);
     if (!egl_display)
       {
-        fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname);
+        /* fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname); */
         return;
       }
 
@@ -635,7 +651,9 @@ static Bool got_error = 0;
 static int
 BadValue_ehandler (Display *dpy, XErrorEvent *error)
 {
-  if (error->error_code == BadValue)
+  if (error->error_code == BadValue ||
+      /* GLXBadFBConfig == 167, but glxproto.h defines it as 9...? */
+      error->error_code == 167)
     {
       got_error = True;
       return 0;
@@ -646,6 +664,25 @@ BadValue_ehandler (Display *dpy, XErrorEvent *error)
 #endif /* !HAVE_EGL */
 
 
+/* Under GLX, it is possible to request an OpenGL 3.2 core profile context
+   by calling glXCreateContextAttribsARB(), however, that doesn't work.
+   On Raspberry Pi 4b Debian 13, the driver supports no core profile
+   contexts and only supports OpenGL up to 3.1.  On macOS X11 it returns
+   an OpenGL 2.1 context.  Whereas the standard glXCreateContext() seems
+   to return the highest-available OpenGL compatibility context by default.
+ */
+#undef USE_GLXCREATECONTEXTATTRIBSARB
+
+#if !defined(HAVE_EGL) && \
+    defined(HAVE_GLXGETPROCADDRESSARB) && \
+    defined(USE_GLXCREATECONTEXTATTRIBSARB)
+typedef GLXContext (*glXCreateContextAttribsARBProc) (Display *,
+                                                      GLXFBConfig,
+                                                      GLXContext, Bool,
+                                                      const int *);
+#endif
+
+
 /* Initializes OpenGL and returns a GLXContext or egl_data for the window.
    The window is assumed to have been created with the proper visual.
  */
@@ -711,11 +748,10 @@ GLXContext openGL_context_for_window (Screen *screen, Window window)
 # endif /* HAVE_GLES3 */
 
     /* This is re-used, no need to close it. */
-    d->egl_display = eglGetPlatformDisplay (EGL_PLATFORM_X11_KHR,
-                                            (void *) dpy, NULL);
+    d->egl_display = get_egl_display (screen);
     if (!d->egl_display)
       {
-        fprintf (stderr, "%s: eglGetPlatformDisplay failed\n", progname);
+        fprintf (stderr, "%s: eglGetPlatformDisplay failed (2)\n", progname);
         abort();
       }
 
@@ -790,7 +826,77 @@ GLXContext openGL_context_for_window (Screen *screen, Window window)
   {
     XSync (dpy, False);
     orig_ehandler = XSetErrorHandler (BadValue_ehandler);
-    glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
+
+#  if defined(HAVE_GLXGETPROCADDRESSARB) && \
+      defined(USE_GLXCREATECONTEXTATTRIBSARB)
+  if (get_boolean_resource (dpy, "prefersGLSL", "PrefersGLSL"))
+    {
+      glXCreateContextAttribsARBProc fn =
+        (glXCreateContextAttribsARBProc)
+        glXGetProcAddressARB ((const GLubyte *) "glXCreateContextAttribsARB");
+      if (fn)
+        {
+          GLXFBConfig *confs;
+          int nconfs = 0;
+          int av[100];
+          int ac = 0;
+
+          /* Request a GLXFBConfig that matches our Visual. */
+#   define PUSH(FIELD) do { \
+            int value;                                          \
+            if (! glXGetConfig (dpy, vi_out, FIELD, &value)) {  \
+              av[ac++] = FIELD;                                 \
+              av[ac++] = value;                                 \
+            }} while (0)
+          PUSH (GLX_RED_SIZE);
+          PUSH (GLX_GREEN_SIZE);
+          PUSH (GLX_BLUE_SIZE);
+          PUSH (GLX_ALPHA_SIZE);
+          /* Removed from OpenGL 3.2 core profile.
+          PUSH (GLX_ACCUM_RED_SIZE);
+          PUSH (GLX_ACCUM_GREEN_SIZE);
+          PUSH (GLX_ACCUM_BLUE_SIZE);
+          PUSH (GLX_ACCUM_ALPHA_SIZE); */
+          PUSH (GLX_BUFFER_SIZE);
+          PUSH (GLX_LEVEL);
+          PUSH (GLX_DOUBLEBUFFER);
+          PUSH (GLX_DEPTH_SIZE);
+          PUSH (GLX_STENCIL_SIZE);
+          av[ac] = 0;
+          confs = glXChooseFBConfig (dpy, vi_in.screen, av, &nconfs);
+#   undef PUSH
+
+          if (nconfs)
+            {
+              /* Request OpenGL 3.2+ for GLSL 1.5+ */
+              ac = 0;
+              av[ac++] = GLX_CONTEXT_MAJOR_VERSION_ARB; av[ac++] = 3;
+              av[ac++] = GLX_CONTEXT_MINOR_VERSION_ARB; av[ac++] = 2;
+              av[ac++] = GLX_CONTEXT_PROFILE_MASK_ARB;
+              av[ac++] = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
+              av[ac] = 0;
+
+              glx_context = fn (dpy, confs[0], NULL, GL_TRUE, av);
+
+              /* We get a "GLXBadFBConfig" X error if we have requested
+                 a newer version of OpenGL than the server supports.
+                 Ignore it and make a default context instead. */
+              XSync (dpy, False);
+              if (got_error)
+                {
+                  glx_context = 0;
+                  got_error = False;
+                }
+            }
+
+          if (confs) XFree (confs);
+        }
+    }
+#  endif /* HAVE_GLXGETPROCADDRESSARB && USE_GLXCREATECONTEXTATTRIBSARB */
+
+    if (! glx_context)
+      glx_context = glXCreateContext (dpy, vi_out, 0, GL_TRUE);
+
     XSync (dpy, False);
     XSetErrorHandler (orig_ehandler);
     if (got_error)
@@ -820,6 +926,7 @@ GLXContext openGL_context_for_window (Screen *screen, Window window)
   XFree((char *) vi_out);
 
 
+# ifndef HAVE_JWZGLES
   /* jwz: the doc for glDrawBuffer says "The initial value is GL_FRONT
      for single-buffered contexts, and GL_BACK for double-buffered
      contexts."  However, I find that this is not always the case,
@@ -839,6 +946,7 @@ GLXContext openGL_context_for_window (Screen *screen, Window window)
     else
       glDrawBuffer (GL_FRONT);
   }
+# endif /* !HAVE_JWZGLES */
 
   /* Sometimes glDrawBuffer() throws "invalid op". Dunno why. Ignore. */
   while (glGetError() != GL_NO_ERROR)
index a4cf1d839458a804075ef1fa640c579431988104..092fa20dafd52d0be9fd4f2b46279219ac556309 100644 (file)
@@ -1,5 +1,5 @@
 /* xftwrap.c --- XftDrawStringUtf8 with multi-line strings.
- * xscreensaver, Copyright © 2021 Jamie Zawinski <jwz@jwz.org>
+ * xscreensaver, Copyright © 2021-2025 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
@@ -14,6 +14,7 @@
 # include "config.h"
 #endif
 
+#include <ctype.h>
 #include "utils.h"
 #include "xft.h"
 #include "xftwrap.h"
@@ -39,68 +40,80 @@ LOG(const char *ss, const char *s, int n)
 
 
 /* Returns a new string word-wrapped to fit in the width in pixels.
+   Words may be wrapped at whitespace or ASCII punctuation.
+   Words longer than the width will be split.
  */
 char *
 xft_word_wrap (Display *dpy, XftFont *font, const char *str, int pixels)
 {
   const char *in = str;
-  char *ret = (char *) malloc (strlen(in) + 2);
+  char *ret = (char *) malloc (strlen(in) * 2);
   char *out = ret;
-  const char *line_out = out;
-  char *word_out = 0;
-  while (1)
+
+  const char *splitpoint_in = in;
+  char *splitpoint_out      = out;
+  const char *start_of_line = out;
+
+  /* Ideally this would use utf8_split() and would wrap at Unicrud dashes
+     as well as ASCII, but this is probably good enough. */
+
+  for (in = str; *in; in++)
     {
-      if (*in == ' ' || *in == '\t' ||
-          *in == '\r' || *in == '\n' ||
-          *in == 0)
-        {
-          Bool done = (*in == 0);      /* To wrap the *last* word. */
-          XGlyphInfo overall;
-          Bool nl = (*in == '\r' || *in == '\n');
+      XGlyphInfo overall;
+      *out++ = *in;
 
-          if (nl) in++;
-          while (*in == ' ' || *in == '\t') in++;
-          in--;
-          if (out < line_out) abort();
+      if (isspace(*in) || ispunct(*in))
+        {
+          splitpoint_in  = in;
+          splitpoint_out = out;
+        }
 
-          XftTextExtentsUtf8 (dpy, font,
-                              (FcChar8 *) line_out,
-                              out - line_out,
-                              &overall);
-          if (overall.width - overall.x >= pixels &&
-              word_out)
+      XftTextExtentsUtf8 (dpy, font,
+                          (FcChar8 *) start_of_line,
+                          out - start_of_line,
+                          &overall);
+      if (overall.width - overall.x < pixels)
+        {
+          LOG("keep", start_of_line, out-start_of_line);
+        }
+      else
+        {
+          /* Backtrack 'out' and 'in' to the last splitpoint.
+             Insert a newline and restart.
+           */
+          LOG("split", start_of_line, splitpoint_out - start_of_line);
+          if (splitpoint_out == start_of_line)
             {
-              word_out[0] = '\n';
-              line_out = word_out + 1;
-              word_out = 0;
-              if (done) break;
-              *out++ = *in;
-              if (out < line_out) abort();
+              /* Breaking in the middle of a long word. */
+              LOG("long", splitpoint_in, in - splitpoint_in);
+              while (out > ret && (isblank (out[-1])))
+                out--;  /* Trim trailing horizontal whitespace on line */
+              *out++ = '\n';
+              splitpoint_out = out;
+              start_of_line = out;
             }
           else
             {
-              if (done) break;
-              word_out = out;
-              *out++ = *in;
-              if (nl)
-                {
-                  line_out = out;  /* Why was I adding 1 to this? */
-                  word_out = 0;
-                }
-              if (out < line_out) abort();
+              LOG("back", splitpoint_in, in - splitpoint_in);
+              out = splitpoint_out;
+              in  = splitpoint_in;
+              while (out > ret && (isblank (out[-1])))
+                out--;  /* Trim trailing horizontal whitespace on line */
+              *out++ = '\n';
+              splitpoint_out = out;
+              start_of_line = out;
+              while (isblank (*in) && isblank (in[1]))
+                in++;  /* Swallow horizontal whitespace after breaking line. */
             }
-
-          if (done) break;
         }
-      else
-        {
-          *out++ = *in;
-        }
-      in++;
     }
 
+  while (out > ret && (isspace (out[-1])))
+    out--;  /* Trim trailing whitespace and blank lines */
   *out = 0;
 
+  LOG("DONE",ret,strlen(ret));
+
   return ret;
 }
 
index 05681bdf5d19c75b1bb0705ce248a022b5eacdb3..262543183954671720101f0fe28680f1e6be10a4 100644 (file)
@@ -1,5 +1,5 @@
 %define        name xscreensaver
-%define        version 6.13
+%define        version 6.14
 
 Summary:       X screen saver and locker
 Name:          %{name}
@@ -33,12 +33,17 @@ BuildRequires:      libXxf86vm-devel
 BuildRequires: xorg-x11-proto-devel
 BuildRequires: mesa-libGL-devel
 BuildRequires: mesa-libGLU-devel
+
+%if 0%{?rhel} >= 8
+# libgle-devel was deprecated in RHEL 8/9 and moved into mesa-libGL-devel
+%else
 BuildRequires: libgle-devel
+%endif
+
 BuildRequires: pam-devel
 BuildRequires: systemd-devel
 BuildRequires: gtk3-devel
 BuildRequires: gdk-pixbuf2-devel
-BuildRequires: libglade2
 BuildRequires: libxml2-devel
 BuildRequires: gettext-devel
 BuildRequires: libjpeg-turbo-devel
@@ -95,9 +100,9 @@ if [ -x %{_datadir}/libtool/config.guess ]; then
 fi
 
 %build
-archdir=`./config.guess`
-mkdir $archdir
-cd $archdir
+archdir="`./config.guess`"
+mkdir "$archdir" || exit 1
+cd "$archdir" || exit 1
 
 export CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}"
 
@@ -110,42 +115,74 @@ rm -f configure
 make
 
 %install
-archdir=`./config.guess`
-cd $archdir
+archdir="`./config.guess`"
+cd "$archdir" || exit 1
 
-rm -rf ${RPM_BUILD_ROOT}
-mkdir -p $RPM_BUILD_ROOT/etc/pam.d
+rm -rf   "$RPM_BUILD_ROOT"
+mkdir -p "$RPM_BUILD_ROOT/etc/pam.d"
+mkdir -p "$RPM_BUILD_ROOT/usr/lib/systemd/user"
 
-make install_prefix=$RPM_BUILD_ROOT install
+make DESTDIR="$RPM_BUILD_ROOT" \
+     UPDATE_ICON_CACHE=true \
+     SUID_FLAGS= \
+     install
 
 dd=%{_builddir}/%{name}-%{version}
 
-make -s install_prefix=${RPM_BUILD_ROOT} \
-       INSTALL=true \
-       UPDATE_ICON_CACHE='true false' \
-        install |
-grep -v '^true false' |
-sed -n -e 's@.* \(/[^ ]*\)$@\1@p' |
-sed    -e "s@^${RPM_BUILD_ROOT}@@" \
-       -e "s@/[a-z][a-z]*/\.\./@/@" |
-sed    -e 's@\(.*/man/.*\)@\1\*@' |
-sort | uniq |
-sed    -e 's@\(.*/app-defaults/\)@%config \1@' \
-       -e 's@\(.*/pam\.d/\)@%config(missingok) \1@' \
-> $dd/all.files
+( cd "$RPM_BUILD_ROOT" || exit 1
+  find * -type f -o -type l |
+  grep -vF '/.' |
+  sed 's@^@/@'  |
+  sort |
+  sed -e 's@^\(.*/app-defaults/\)@%config \1@' \
+      -e 's@^\(.*/pam\.d/\)@%config(missingok) \1@' \
+      -e 's@^\(.*/xscreensaver-auth\)$@%attr(4755,root,root) \1@' \
+      -e 's@^\(.*/sonar\)$@%attr(4755,root,root) \1@' \
+      -e 's@\(.*/man/.*\)@\1\*@' \
+) > $dd/allfiles.txt
+
+#cat $dd/allfiles.txt
 
 #%find_lang %{name}
-#cat %{name}.lang >> $dd/all.files
+#cat %{name}.lang >> $dd/allfiles.txt
 
-chmod -R a+r,u+w,og-w ${RPM_BUILD_ROOT}
+chmod -R a+r,u+w,og-w "$RPM_BUILD_ROOT"
 
 %clean
-rm -rf ${RPM_BUILD_ROOT}
+rm -rf "$RPM_BUILD_ROOT"
+
+%files -f allfiles.txt
+%defattr(-, root, root)
 
-%files -f all.files
-%defattr(-,root,root)
+%post
+killall -HUP xscreensaver 2>&-
+
+# I think that without this, newly-installed icons don't show up in
+# desktop menus or in xscreensaver-settings.  Is there a better way?
+#
+for f in /usr/share/icons/index.theme     \
+         /usr/share/icons/*/index.theme   \
+         /usr/share/pixmaps/index.theme   \
+         /usr/share/pixmaps/*/index.theme \
+; do
+  if [ -f "$f" ]; then
+    f=`dirname "$f"`
+    gtk-update-icon-cache --force --quiet "$f"
+  fi
+done
+
+%preun
+# 0 = removing, 1 = upgrading.
+if [ "$1" = 0 ] ; then
+  killall -q /usr/bin/xscreensaver          || true
+  killall -q /usr/bin/xscreensaver-settings || true
+  killall -q /usr/bin/xscreensaver-command  || true
+fi
+exit 0
 
 %changelog
+* Tue Dec 02 2025 jwz
+- Cleanup.
 * Mon Jul 31 2023 jwz
 - Splitting this into multiple packages is a support nightmare, please don't.
 * Mon Nov 16 1998 jwz