<html>
<body>
  <div id="body" style="background-color:#ffffff;" >
<table cellspacing="0" cellpadding="0" border="0" rules="cols">
<tr class="head" style="border-bottom-width:1px;border-bottom-style:solid;" ><td class="headtd" style="padding:0;padding-top:.2em;" colspan="4">Commit in <b><tt>lxdream/src</tt></b></td></tr>
<tr><td><tt><a href="#file1">Makefile.am</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+6</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-5</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c -> 5f56fc931112</td></tr>
<tr class="alt" style=";" ><td><tt><a href="#file2">Makefile.in</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+69</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-82</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c -> 5f56fc931112</td></tr>
<tr><td><tt>pvr2/<a href="#file3"><span id="removed" style="background-color:#ffdddd;" >fragment.glsl</span></a></tt></td><td></td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-7</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c removed</td></tr>
<tr class="alt" style=";" ><td><tt>    /<a href="#file4">gl_sl.c</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+267</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-120</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c -> 5f56fc931112</td></tr>
<tr><td><tt>    /<a href="#file5">glrender.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+3</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-3</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c -> 5f56fc931112</td></tr>
<tr class="alt" style=";" ><td><tt>    /<a href="#file6">glutil.h</a></tt></td><td id="addedalt" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ccf7cc;" align="right">+4</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-5</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c -> 5f56fc931112</td></tr>
<tr><td><tt>    /<a href="#file7"><span id="added" style="background-color:#ddffdd;" >shaders.glsl</span></a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+42</td><td></td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" align="right" nowrap="nowrap">added 5f56fc931112</td></tr>
<tr class="alt" style=";" ><td><tt>    /<a href="#file8"><span id="removedalt" style="background-color:#f7cccc;" >vertex.glsl</span></a></tt></td><td></td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-12</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c removed</td></tr>
<tr><td><tt>tools/<a href="#file9">genglsl.c</a></tt></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+245</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-37</td><td class="headtd2" style="padding-left:.3em;padding-right:.3em;" nowrap="nowrap">7b16bbd6209c -> 5f56fc931112</td></tr>
<tr><td></td><td id="added" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ddffdd;" align="right">+636</td><td id="removed" class="headtd2" style="padding-left:.3em;padding-right:.3em; background-color:#ffdddd;" align="right">-271</td><td></td></tr>
</table>
<small id="info" style="color: #888888;" >1 added + 2 removed + 6 modified, total 9 files</small><br />
<pre class="comment" style="white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap;white-space:pre-wrap;word-wrap:break-word;padding:4px;border:1px dashed #000000;background-color:#ffffdd;" >
Refactor shader management to support multiple programs, which are all
defined in the shaders.glsl, rather than split up into one file per
fragment.
</pre>
<hr /><a name="file1" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>Makefile.am</b></big> <small id="info" style="color: #888888;" >7b16bbd6209c -> 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/Makefile.am
+++ lxdream/src/Makefile.am
@@ -27,9 +27,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 TESTS = test/testxlt
 BUILT_SOURCES = sh4/sh4core.c sh4/sh4dasm.c sh4/sh4x86.c sh4/sh4stat.c \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/gl_slsrc.c drivers/mac_keymap.h version.c
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/shaders.def pvr2/shaders.h drivers/mac_keymap.h version.c
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > CLEANFILES = sh4/sh4core.c sh4/sh4dasm.c sh4/sh4x86.c sh4/sh4stat.c \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/gl_slsrc.c drivers/mac_keymap.h version.c  \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/shaders.def pvr2/shaders.h drivers/mac_keymap.h version.c  \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    audio_alsa.lo audio_sdl.lo audio_esd.lo audio_pulse.lo input_lirc.lo \
        lxdream_dummy.lo
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -58,7 +58,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      pvr2/pvr2.c pvr2/pvr2.h pvr2/pvr2mem.c pvr2/pvr2mmio.h \
        pvr2/tacore.c pvr2/rendsort.c \
        pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c pvr2/scene.c pvr2/scene.h \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/gl_sl.c pvr2/<span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >gl_slsrc.c</span> pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/gl_sl.c pvr2/<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >shaders.h pvr2/shaders.def</span> pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    pvr2/vertex.glsl pvr2/fragment.glsl \
         maple/maple.c maple/maple.h \
         maple/controller.c maple/kbd.c maple/mouse.c maple/lightgun.c maple/vmu.c \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -254,9 +254,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > sh4/sh4stat.c: gendec sh4/sh4.def sh4/sh4stat.in
        $(mkdir_p) `dirname $@`
        ./gendec $(srcdir)/sh4/sh4.def $(srcdir)/sh4/sh4stat.in -o $@
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-pvr2/gl_slsrc.c: genglsl pvr2/vertex.glsl pvr2/fragment.glsl
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+pvr2/shaders.def: genglsl pvr2/shaders.glsl
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    $(mkdir_p) `dirname $@`
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   ./genglsl $(srcdir)/pvr2/vertex.glsl $(srcdir)/pvr2/fragment.glsl $@
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     ./genglsl $(srcdir)/pvr2/shaders.glsl $@
+pvr2/shaders.h: pvr2/shaders.def
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > drivers/mac_keymap.h: drivers/mac_keymap.txt drivers/genkeymap.pl
        $(mkdir_p) `dirname $@`
        $(srcdir)/drivers/genkeymap.pl mac $(srcdir)/drivers/mac_keymap.txt > $@
</pre></div>
<hr /><a name="file2" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>Makefile.in</b></big> <small id="info" style="color: #888888;" >7b16bbd6209c -> 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/Makefile.in
+++ lxdream/src/Makefile.in
@@ -157,45 +157,46 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      aica/aica.c aica/aica.h aica/audio.c aica/audio.h pvr2/pvr2.c \
        pvr2/pvr2.h pvr2/pvr2mem.c pvr2/pvr2mmio.h pvr2/tacore.c \
        pvr2/rendsort.c pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/scene.c pvr2/scene.h pvr2/gl_sl.c pvr2/gl_slsrc.c \
-       pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c pvr2/vertex.glsl \
-       pvr2/fragment.glsl maple/maple.c maple/maple.h \
-       maple/controller.c maple/kbd.c maple/mouse.c maple/lightgun.c \
-       maple/vmu.c loader.c loader.h elf.h bootstrap.c bootstrap.h \
-       util.c gdlist.c gdlist.h vmu/vmuvol.c vmu/vmuvol.h \
-       vmu/vmulist.c vmu/vmulist.h display.c display.h dckeysyms.h \
-       drivers/audio_null.c drivers/video_null.c drivers/video_gl.c \
-       drivers/video_gl.h drivers/gl_fbo.c drivers/serial_unix.c \
-       drivers/cdrom/cdrom.h drivers/cdrom/cdrom.c \
-       drivers/cdrom/drive.h drivers/cdrom/sector.h \
-       drivers/cdrom/sector.c drivers/cdrom/defs.h \
-       drivers/cdrom/cd_nrg.c drivers/cdrom/cd_cdi.c \
-       drivers/cdrom/cd_gdi.c drivers/cdrom/edc_ecc.c \
-       drivers/cdrom/ecc.h drivers/cdrom/drive.c \
-       drivers/cdrom/edc_crctable.h drivers/cdrom/edc_encoder.h \
-       drivers/cdrom/edc_l2sq.h drivers/cdrom/edc_scramble.h \
-       drivers/cdrom/cd_mmc.c drivers/cdrom/isofs.h \
-       drivers/cdrom/isofs.c sh4/sh4.def sh4/sh4core.in sh4/sh4x86.in \
-       sh4/sh4dasm.in sh4/sh4stat.in hotkeys.c hotkeys.h plugin.c \
-       plugin.h sh4/sh4x86.c xlat/x86/x86op.h xlat/x86/ia32abi.h \
-       xlat/x86/amd64abi.h sh4/sh4trans.c sh4/sh4trans.h sh4/mmux86.c \
-       x86dasm/x86dasm.c x86dasm/x86dasm.h x86dasm/i386-dis.c \
-       x86dasm/dis-init.c x86dasm/dis-buf.c x86dasm/ansidecl.h \
-       x86dasm/bfd.h x86dasm/dis-asm.h x86dasm/symcat.h \
-       x86dasm/sysdep.h gtkui/gtkui.c gtkui/gtkui.h gtkui/gtk_win.c \
-       gtkui/gtkcb.c gtkui/gtk_cfg.c gtkui/gtk_mmio.c \
-       gtkui/gtk_debug.c gtkui/gtk_dump.c gtkui/gtk_ctrl.c \
-       gtkui/gtk_gd.c drivers/io_glib.c drivers/video_gtk.c \
-       cocoaui/cocoaui.m cocoaui/cocoaui.h cocoaui/cocoa_cfg.m \
-       cocoaui/cocoa_win.m cocoaui/cocoa_gd.m cocoaui/cocoa_prefs.m \
-       cocoaui/cocoa_ctrl.m cocoaui/paths_osx.m drivers/io_osx.m \
-       drivers/video_osx.m drivers/mac_keymap.h \
-       drivers/mac_keymap.txt paths_unix.c drivers/video_gdk.c \
-       drivers/video_glx.c drivers/video_glx.h drivers/video_nsgl.m \
-       drivers/video_nsgl.h drivers/audio_osx.m drivers/audio_sdl.c \
-       drivers/audio_pulse.c drivers/audio_esd.c drivers/audio_alsa.c \
-       drivers/input_lirc.c drivers/cdrom/cd_linux.c \
-       drivers/cdrom/cd_osx.c drivers/osx_iokit.m drivers/osx_iokit.h \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/scene.c pvr2/scene.h pvr2/gl_sl.c pvr2/shaders.h \
+       pvr2/shaders.def pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c \
+       pvr2/vertex.glsl pvr2/fragment.glsl maple/maple.c \
+       maple/maple.h maple/controller.c maple/kbd.c maple/mouse.c \
+       maple/lightgun.c maple/vmu.c loader.c loader.h elf.h \
+       bootstrap.c bootstrap.h util.c gdlist.c gdlist.h vmu/vmuvol.c \
+       vmu/vmuvol.h vmu/vmulist.c vmu/vmulist.h display.c display.h \
+       dckeysyms.h drivers/audio_null.c drivers/video_null.c \
+       drivers/video_gl.c drivers/video_gl.h drivers/gl_fbo.c \
+       drivers/serial_unix.c drivers/cdrom/cdrom.h \
+       drivers/cdrom/cdrom.c drivers/cdrom/drive.h \
+       drivers/cdrom/sector.h drivers/cdrom/sector.c \
+       drivers/cdrom/defs.h drivers/cdrom/cd_nrg.c \
+       drivers/cdrom/cd_cdi.c drivers/cdrom/cd_gdi.c \
+       drivers/cdrom/edc_ecc.c drivers/cdrom/ecc.h \
+       drivers/cdrom/drive.c drivers/cdrom/edc_crctable.h \
+       drivers/cdrom/edc_encoder.h drivers/cdrom/edc_l2sq.h \
+       drivers/cdrom/edc_scramble.h drivers/cdrom/cd_mmc.c \
+       drivers/cdrom/isofs.h drivers/cdrom/isofs.c sh4/sh4.def \
+       sh4/sh4core.in sh4/sh4x86.in sh4/sh4dasm.in sh4/sh4stat.in \
+       hotkeys.c hotkeys.h plugin.c plugin.h sh4/sh4x86.c \
+       xlat/x86/x86op.h xlat/x86/ia32abi.h xlat/x86/amd64abi.h \
+       sh4/sh4trans.c sh4/sh4trans.h sh4/mmux86.c x86dasm/x86dasm.c \
+       x86dasm/x86dasm.h x86dasm/i386-dis.c x86dasm/dis-init.c \
+       x86dasm/dis-buf.c x86dasm/ansidecl.h x86dasm/bfd.h \
+       x86dasm/dis-asm.h x86dasm/symcat.h x86dasm/sysdep.h \
+       gtkui/gtkui.c gtkui/gtkui.h gtkui/gtk_win.c gtkui/gtkcb.c \
+       gtkui/gtk_cfg.c gtkui/gtk_mmio.c gtkui/gtk_debug.c \
+       gtkui/gtk_dump.c gtkui/gtk_ctrl.c gtkui/gtk_gd.c \
+       drivers/io_glib.c drivers/video_gtk.c cocoaui/cocoaui.m \
+       cocoaui/cocoaui.h cocoaui/cocoa_cfg.m cocoaui/cocoa_win.m \
+       cocoaui/cocoa_gd.m cocoaui/cocoa_prefs.m cocoaui/cocoa_ctrl.m \
+       cocoaui/paths_osx.m drivers/io_osx.m drivers/video_osx.m \
+       drivers/mac_keymap.h drivers/mac_keymap.txt paths_unix.c \
+       drivers/video_gdk.c drivers/video_glx.c drivers/video_glx.h \
+       drivers/video_nsgl.m drivers/video_nsgl.h drivers/audio_osx.m \
+       drivers/audio_sdl.c drivers/audio_pulse.c drivers/audio_esd.c \
+       drivers/audio_alsa.c drivers/input_lirc.c \
+       drivers/cdrom/cd_linux.c drivers/cdrom/cd_osx.c \
+       drivers/osx_iokit.m drivers/osx_iokit.h \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    drivers/cdrom/cd_none.c drivers/joy_linux.c \
        drivers/joy_linux.h
 @BUILD_SHARED_TRUE@am__objects_1 = lxdream-plugin.$(OBJEXT)
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -264,28 +265,28 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      lxdream-tacore.$(OBJEXT) lxdream-rendsort.$(OBJEXT) \
        lxdream-texcache.$(OBJEXT) lxdream-yuv.$(OBJEXT) \
        lxdream-rendsave.$(OBJEXT) lxdream-scene.$(OBJEXT) \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   lxdream-gl_sl.$(OBJEXT) lxdream-gl_slsrc.$(OBJEXT) \
-       lxdream-glutil.$(OBJEXT) lxdream-glrender.$(OBJEXT) \
-       lxdream-maple.$(OBJEXT) lxdream-controller.$(OBJEXT) \
-       lxdream-kbd.$(OBJEXT) lxdream-mouse.$(OBJEXT) \
-       lxdream-lightgun.$(OBJEXT) lxdream-vmu.$(OBJEXT) \
-       lxdream-loader.$(OBJEXT) lxdream-bootstrap.$(OBJEXT) \
-       lxdream-util.$(OBJEXT) lxdream-gdlist.$(OBJEXT) \
-       lxdream-vmuvol.$(OBJEXT) lxdream-vmulist.$(OBJEXT) \
-       lxdream-display.$(OBJEXT) lxdream-audio_null.$(OBJEXT) \
-       lxdream-video_null.$(OBJEXT) lxdream-video_gl.$(OBJEXT) \
-       lxdream-gl_fbo.$(OBJEXT) lxdream-serial_unix.$(OBJEXT) \
-       lxdream-cdrom.$(OBJEXT) lxdream-sector.$(OBJEXT) \
-       lxdream-cd_nrg.$(OBJEXT) lxdream-cd_cdi.$(OBJEXT) \
-       lxdream-cd_gdi.$(OBJEXT) lxdream-edc_ecc.$(OBJEXT) \
-       lxdream-drive.$(OBJEXT) lxdream-cd_mmc.$(OBJEXT) \
-       lxdream-isofs.$(OBJEXT) lxdream-hotkeys.$(OBJEXT) \
-       $(am__objects_1) $(am__objects_2) $(am__objects_3) \
-       $(am__objects_4) $(am__objects_5) $(am__objects_6) \
-       $(am__objects_7) $(am__objects_8) $(am__objects_9) \
-       $(am__objects_10) $(am__objects_11) $(am__objects_12) \
-       $(am__objects_13) $(am__objects_14) $(am__objects_15) \
-       $(am__objects_16) $(am__objects_17) $(am__objects_18)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     lxdream-gl_sl.$(OBJEXT) lxdream-glutil.$(OBJEXT) \
+       lxdream-glrender.$(OBJEXT) lxdream-maple.$(OBJEXT) \
+       lxdream-controller.$(OBJEXT) lxdream-kbd.$(OBJEXT) \
+       lxdream-mouse.$(OBJEXT) lxdream-lightgun.$(OBJEXT) \
+       lxdream-vmu.$(OBJEXT) lxdream-loader.$(OBJEXT) \
+       lxdream-bootstrap.$(OBJEXT) lxdream-util.$(OBJEXT) \
+       lxdream-gdlist.$(OBJEXT) lxdream-vmuvol.$(OBJEXT) \
+       lxdream-vmulist.$(OBJEXT) lxdream-display.$(OBJEXT) \
+       lxdream-audio_null.$(OBJEXT) lxdream-video_null.$(OBJEXT) \
+       lxdream-video_gl.$(OBJEXT) lxdream-gl_fbo.$(OBJEXT) \
+       lxdream-serial_unix.$(OBJEXT) lxdream-cdrom.$(OBJEXT) \
+       lxdream-sector.$(OBJEXT) lxdream-cd_nrg.$(OBJEXT) \
+       lxdream-cd_cdi.$(OBJEXT) lxdream-cd_gdi.$(OBJEXT) \
+       lxdream-edc_ecc.$(OBJEXT) lxdream-drive.$(OBJEXT) \
+       lxdream-cd_mmc.$(OBJEXT) lxdream-isofs.$(OBJEXT) \
+       lxdream-hotkeys.$(OBJEXT) $(am__objects_1) $(am__objects_2) \
+       $(am__objects_3) $(am__objects_4) $(am__objects_5) \
+       $(am__objects_6) $(am__objects_7) $(am__objects_8) \
+       $(am__objects_9) $(am__objects_10) $(am__objects_11) \
+       $(am__objects_12) $(am__objects_13) $(am__objects_14) \
+       $(am__objects_15) $(am__objects_16) $(am__objects_17) \
+       $(am__objects_18)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > lxdream_OBJECTS = $(am_lxdream_OBJECTS)
 lxdream_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
        $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -544,10 +545,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > AM_CFLAGS = -D__EXTENSIONS__ -D_BSD_SOURCE -D_GNU_SOURCE
 TESTS = test/testxlt
 BUILT_SOURCES = sh4/sh4core.c sh4/sh4dasm.c sh4/sh4x86.c sh4/sh4stat.c \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/gl_slsrc.c drivers/mac_keymap.h version.c
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/shaders.def pvr2/shaders.h drivers/mac_keymap.h version.c
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 CLEANFILES = sh4/sh4core.c sh4/sh4dasm.c sh4/sh4x86.c sh4/sh4stat.c \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/gl_slsrc.c drivers/mac_keymap.h version.c  \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/shaders.def pvr2/shaders.h drivers/mac_keymap.h version.c  \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    audio_alsa.lo audio_sdl.lo audio_esd.lo audio_pulse.lo input_lirc.lo \
        lxdream_dummy.lo
 
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -576,8 +577,8 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >      aica/audio.c aica/audio.h pvr2/pvr2.c pvr2/pvr2.h \
        pvr2/pvr2mem.c pvr2/pvr2mmio.h pvr2/tacore.c pvr2/rendsort.c \
        pvr2/texcache.c pvr2/yuv.c pvr2/rendsave.c pvr2/scene.c \
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   pvr2/scene.h pvr2/gl_sl.c pvr2/gl_slsrc.c pvr2/glutil.c \
-       pvr2/glutil.h pvr2/glrender.c pvr2/vertex.glsl \
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     pvr2/scene.h pvr2/gl_sl.c pvr2/shaders.h pvr2/shaders.def \
+       pvr2/glutil.c pvr2/glutil.h pvr2/glrender.c pvr2/vertex.glsl \
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    pvr2/fragment.glsl maple/maple.c maple/maple.h \
        maple/controller.c maple/kbd.c maple/mouse.c maple/lightgun.c \
        maple/vmu.c loader.c loader.h elf.h bootstrap.c bootstrap.h \
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -816,7 +817,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gdrom.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gl_fbo.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gl_sl.Po@am__quote@
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gl_slsrc.Po@am__quote@
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-glrender.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-glutil.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxdream-gtk_cfg.Po@am__quote@
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -1663,20 +1663,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > @AMDEP_TRUE@@am__fastdepCC_FALSE@    DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lxdream-gl_sl.obj `if test -f 'pvr2/gl_sl.c'; then $(CYGPATH_W) 'pvr2/gl_sl.c'; else $(CYGPATH_W) '$(srcdir)/pvr2/gl_sl.c'; fi`
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-lxdream-gl_slsrc.o: pvr2/gl_slsrc.c
-@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-gl_slsrc.o -MD -MP -MF "$(DEPDIR)/lxdream-gl_slsrc.Tpo" -c -o lxdream-gl_slsrc.o `test -f 'pvr2/gl_slsrc.c' || echo '$(srcdir)/'`pvr2/gl_slsrc.c; \
-@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/lxdream-gl_slsrc.Tpo" "$(DEPDIR)/lxdream-gl_slsrc.Po"; else rm -f "$(DEPDIR)/lxdream-gl_slsrc.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='pvr2/gl_slsrc.c' object='lxdream-gl_slsrc.o' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lxdream-gl_slsrc.o `test -f 'pvr2/gl_slsrc.c' || echo '$(srcdir)/'`pvr2/gl_slsrc.c
-
-lxdream-gl_slsrc.obj: pvr2/gl_slsrc.c
-@am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-gl_slsrc.obj -MD -MP -MF "$(DEPDIR)/lxdream-gl_slsrc.Tpo" -c -o lxdream-gl_slsrc.obj `if test -f 'pvr2/gl_slsrc.c'; then $(CYGPATH_W) 'pvr2/gl_slsrc.c'; else $(CYGPATH_W) '$(srcdir)/pvr2/gl_slsrc.c'; fi`; \
-@am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/lxdream-gl_slsrc.Tpo" "$(DEPDIR)/lxdream-gl_slsrc.Po"; else rm -f "$(DEPDIR)/lxdream-gl_slsrc.Tpo"; exit 1; fi
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='pvr2/gl_slsrc.c' object='lxdream-gl_slsrc.obj' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCC_FALSE@  $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o lxdream-gl_slsrc.obj `if test -f 'pvr2/gl_slsrc.c'; then $(CYGPATH_W) 'pvr2/gl_slsrc.c'; else $(CYGPATH_W) '$(srcdir)/pvr2/gl_slsrc.c'; fi`
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > lxdream-glutil.o: pvr2/glutil.c
 @am__fastdepCC_TRUE@   if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lxdream_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT lxdream-glutil.o -MD -MP -MF "$(DEPDIR)/lxdream-glutil.Tpo" -c -o lxdream-glutil.o `test -f 'pvr2/glutil.c' || echo '$(srcdir)/'`pvr2/glutil.c; \
 @am__fastdepCC_TRUE@   then mv -f "$(DEPDIR)/lxdream-glutil.Tpo" "$(DEPDIR)/lxdream-glutil.Po"; else rm -f "$(DEPDIR)/lxdream-glutil.Tpo"; exit 1; fi
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -3193,9 +3179,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > sh4/sh4stat.c: gendec sh4/sh4.def sh4/sh4stat.in
        $(mkdir_p) `dirname $@`
        ./gendec $(srcdir)/sh4/sh4.def $(srcdir)/sh4/sh4stat.in -o $@
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-pvr2/gl_slsrc.c: genglsl pvr2/vertex.glsl pvr2/fragment.glsl
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+pvr2/shaders.def: genglsl pvr2/shaders.glsl
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >    $(mkdir_p) `dirname $@`
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-   ./genglsl $(srcdir)/pvr2/vertex.glsl $(srcdir)/pvr2/fragment.glsl $@
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+     ./genglsl $(srcdir)/pvr2/shaders.glsl $@
+pvr2/shaders.h: pvr2/shaders.def
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > drivers/mac_keymap.h: drivers/mac_keymap.txt drivers/genkeymap.pl
        $(mkdir_p) `dirname $@`
        $(srcdir)/drivers/genkeymap.pl mac $(srcdir)/drivers/mac_keymap.txt > $@
</pre></div>
<hr /><a name="file3" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span id="removed" class="pathname" style="font-family:monospace; float:right; background-color:#ffdddd;" >lxdream/src/pvr2</span><br />
<div id="removed" class="fileheader" style="margin-bottom:.5em; background-color:#ffdddd;" ><big><b>fragment.glsl</b></big> <small id="info" style="color: #888888;" >removed after 7b16bbd6209c</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/fragment.glsl
+++ lxdream/src/pvr2/fragment.glsl
@@ -1,7 +0,0 @@
</small></pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-// Standard PVR2 fragment shader
-
-void main()
-{
-       gl_FragColor = gl_Color;
-       gl_FragDepth = gl_FragCoord.z;
-}
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >\ No newline at end of file
</small></pre></div>
<hr /><a name="file4" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>gl_sl.c</b></big> <small id="info" style="color: #888888;" >7b16bbd6209c -> 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/gl_sl.c
+++ lxdream/src/pvr2/gl_sl.c
@@ -1,11 +1,9 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * $Id$
  *
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * GLSL shader loader/unloader. Current version assumes there's exactly
- * 1 shader program that's used globally. This may turn out not to be the
- * most efficient approach.
- *
- * Copyright (c) 2007 Nathan Keynes.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * GLSL wrapper code to hide the differences between the different gl/sl APIs.
+  *
+ * Copyright (c) 2007-2010 Nathan Keynes.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -18,11 +16,33 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * GNU General Public License for more details.
  */
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <assert.h>
+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include "lxdream.h"
 #include "display.h"
 #include "pvr2/glutil.h"
 
 #define MAX_ERROR_BUF 4096
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#define INVALID_SHADER 0
+#define INVALID_PROGRAM 0
+
+#ifdef HAVE_OPENGL_SHADER_ARB
+typedef GLhandleARB gl_program_t;
+typedef GLhandleARB gl_shader_t;
+#else
+typedef GLuint gl_program_t;
+typedef GLuint gl_shader_t;
+#endif
+
+gboolean glsl_is_supported();
+gl_shader_t glsl_create_vertex_shader( const char *source );
+gl_shader_t glsl_create_fragment_shader( const char *source );
+gl_program_t glsl_create_program( gl_shader_t *shaderv );
+void glsl_use_program(gl_program_t program);
+void glsl_destroy_shader(gl_shader_t shader);
+void glsl_destroy_program(gl_program_t program);
+
+#ifdef HAVE_OPENGL_SHADER_ARB
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 gboolean glsl_is_supported()
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -31,9 +51,6 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     isGLExtensionSupported("GL_ARB_shading_language_100");
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#ifdef HAVE_OPENGL_SHADER_ARB
-static GLhandleARB glsl_program = 0, glsl_vert_shader = 0, glsl_frag_shader = 0;
-
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void glsl_print_error( char *msg, GLhandleARB obj )
 {
     char buf[MAX_ERROR_BUF];
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -62,73 +79,82 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return TRUE;
 }
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gl_shader_t glsl_create_vertex_shader( const char *source )
+{
+    gboolean ok;
+    gl_shader_t shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src )
-{
-    gboolean vsok = TRUE, fsok = TRUE, pok = FALSE;
-
-    if( vertex_src == NULL && fragment_src == NULL ) {
-        return TRUE; // nothing to do
-    }
-
-    glsl_program = glCreateProgramObjectARB();
-
-    if( vertex_src != NULL ) {
-        glsl_vert_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
-        glShaderSourceARB( glsl_vert_shader, 1, &vertex_src, NULL );
-        glCompileShaderARB(glsl_vert_shader);
-        vsok = glsl_check_shader_error("Failed to compile vertex shader", glsl_vert_shader);
-    }
-    if( fragment_src != NULL ) {
-        glsl_frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
-        glShaderSourceARB( glsl_frag_shader, 1, &fragment_src, NULL );
-        glCompileShaderARB(glsl_frag_shader);
-        fsok = glsl_check_shader_error("Failed to compile fragment shader", glsl_frag_shader);
-    }
-
-    if( vsok && fsok ) {
-        if( vertex_src != NULL ) {
-            glAttachObjectARB(glsl_program, glsl_vert_shader);
-        }
-        if( fragment_src != NULL ) {
-            glAttachObjectARB(glsl_program, glsl_frag_shader);
-        }
-        glLinkProgramARB(glsl_program);
-        pok = glsl_check_program_error( "Failed to link shader program", glsl_program );
-    }
-    if( pok ) {
-        glUseProgramObjectARB(glsl_program);
-        pok = glsl_check_program_error( "Failed to apply shader program", glsl_program );
-        glsl_enable_shaders(FALSE); // initially disabled
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glShaderSourceARB( shader, 1, &source, NULL );
+    glCompileShaderARB(shader);
+    ok = glsl_check_shader_error("Failed to compile vertex shader", shader);
+    if( !ok ) {
+        glDeleteObjectARB(shader);
+        return INVALID_SHADER;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } else {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glsl_unload_shaders();
-    }
-    return pok;
-}
-
-void glsl_enable_shaders(gboolean en)
-{
-    if( glsl_program != 0 ) {
-        if( en ) {
-            glUseProgramObjectARB(glsl_program);
-        } else {
-            glUseProgramObjectARB(0);
-        }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return shader;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-void glsl_unload_shaders(void)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gl_shader_t glsl_create_fragment_shader( const char *source )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glUseProgramObjectARB(0);
-    glDetachObjectARB(glsl_program, glsl_vert_shader);
-    glDetachObjectARB(glsl_program, glsl_frag_shader);
-    glDeleteObjectARB(glsl_program);
-    glDeleteObjectARB(glsl_vert_shader);
-    glDeleteObjectARB(glsl_frag_shader);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gboolean ok;
+    gl_shader_t shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
+
+    glShaderSourceARB( shader, 1, &source, NULL );
+    glCompileShaderARB(shader);
+    ok = glsl_check_shader_error("Failed to compile fragment shader", shader);
+    if( !ok ) {
+        glDeleteObjectARB(shader);
+        return INVALID_SHADER;
+    } else {
+        return shader;
+    }
+}
+
+gl_program_t glsl_create_program( gl_shader_t *shaderv )
+{
+    gboolean ok;
+    unsigned i;
+    gl_program_t program = glCreateProgramObjectARB();
+
+    for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
+        glAttachObjectARB(program, shaderv[i]);
+    }
+
+    glLinkProgramARB(program);
+    ok = glsl_check_program_error( "Failed to link shader program", program );
+    if( !ok ) {
+        glDeleteObjectARB(program);
+        return INVALID_PROGRAM;
+    } else {
+        return program;
+    }
+}
+
+void glsl_use_program(gl_program_t program)
+{
+    glUseProgramObjectARB(program);
+    glsl_check_program_error( "Failed to activate shader program", program );
+}
+
+void glsl_destroy_shader(gl_shader_t shader)
+{
+    glDeleteObjectARB(shader);
+}
+
+void glsl_destroy_program(gl_program_t program)
+{
+    glDeleteObjectARB(program);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
 #elif HAVE_OPENGL_SHADER
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static GLuint glsl_program = 0, glsl_vert_shader = 0, glsl_frag_shader = 0;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
+gboolean glsl_is_supported()
+{
+    return isGLExtensionSupported("GL_ARB_fragment_shader") &&
+    isGLExtensionSupported("GL_ARB_vertex_shader") &&
+    isGLExtensionSupported("GL_ARB_shading_language_100");
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 gboolean glsl_check_shader_error( char *msg, GLuint shader )
 {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -144,6 +170,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
     return TRUE;
 }
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > gboolean glsl_check_program_error( char *msg, GLuint program )
 {
     if( glGetError() != GL_NO_ERROR ) {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -156,83 +183,203 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return TRUE;
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gl_shader_t glsl_create_vertex_shader( const char *source )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    gboolean vsok = TRUE, fsok = TRUE, pok = FALSE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    gboolean ok;
+    gl_shader_t shader = glCreateShader(GL_VERTEX_SHADER);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( vertex_src == NULL && fragment_src == NULL ) {
-        return TRUE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glShaderSource( shader, 1, &source, NULL );
+    glCompileShader(shader);
+    ok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
+    if( !ok ) {
+        glDeleteShader(shader);
+        return INVALID_SHADER;
+    } else {
+        return shader;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glsl_program = glCreateProgram();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( vertex_src != NULL ) {
-        glsl_vert_shader = glCreateShader(GL_VERTEX_SHADER);
-        glShaderSource( glsl_vert_shader, 1, &vertex_src, NULL );
-        glCompileShader(glsl_vert_shader);
-        vsok = glsl_check_shader_error( "Failed to compile vertex shader", glsl_vert_shader );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gl_shader_t glsl_create_fragment_shader( const char *source )
+{
+    gboolean ok;
+    gl_shader_t shader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    glShaderSource( shader, 1, &source, NULL );
+    glCompileShader(shader);
+    ok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
+    if( !ok ) {
+        glDeleteShader(shader);
+        return INVALID_SHADER;
+    } else {
+        return shader;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( fragment_src != NULL ) {
-        glsl_frag_shader = glCreateShader(GL_FRAGMENT_SHADER);
-        glShaderSource( glsl_frag_shader, 1, &fragment_src, NULL );
-        glCompileShader(glsl_frag_shader);
-        fsok = glsl_check_shader_error( "Failed to compile fragment shader", glsl_frag_shader );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+}
+
+gl_program_t glsl_create_program( gl_shader_t *shaderv )
+{
+    gboolean ok;
+    unsigned i;
+    gl_program_t program = glCreateProgram();
+
+    for( i=0; shaderv[i] != INVALID_SHADER; i++ ) {
+        glAttachShader(program, shaderv[i]);
+    }
+    glLinkProgram(program);
+    ok = glsl_check_program_error( "Failed to link shader program", program );
+    if( !ok ) {
+        glDeleteProgram(program);
+        return INVALID_PROGRAM;
+    } else {
+        return program;
+    }
+}
+
+void glsl_use_program(gl_program_t program)
+{
+    glUseProgram(program);
+}
+
+void glsl_destroy_shader(gl_shader_t shader)
+{
+    glDeleteShader(shader);
+}
+
+void glsl_destroy_program(gl_program_t program)
+{
+    glDeleteProgram(program);
+}
+
+#else
+gboolean glsl_is_supported()
+{
+    return FALSE;
+}
+
+gl_shader_t glsl_create_vertex_shader( const char *source )
+{
+    return 0;
+}
+
+gl_shader_t glsl_create_fragment_shader( const char *source )
+{
+    return 0;
+}
+
+gl_program_t glsl_create_program( gl_shader_t vertex, gl_shader_t fragment )
+{
+    return 0;
+}
+
+void glsl_use_program(gl_program_t program)
+{
+}
+
+void glsl_destroy_shader(gl_shader_t shader)
+{
+}
+
+void glsl_destroy_program(gl_program_t program)
+{
+}
+#endif
+
+/****************************************************************************/
+
+/* Pull in the auto-generated shader definitions */
+
+#include "pvr2/shaders.def"
+
+static gl_program_t program_array[GLSL_NUM_PROGRAMS];
+
+gboolean glsl_load_shaders()
+{
+    gl_shader_t shader_array[GLSL_NUM_SHADERS];
+    gboolean ok = TRUE;
+    unsigned i, j;
+    for( i=0; i<GLSL_NUM_SHADERS; i++ )
+        shader_array[i] = INVALID_SHADER;
+    for( i=0; i<GLSL_NUM_PROGRAMS; i++ )
+        program_array[i] = INVALID_PROGRAM;
+
+    /* Compile the shader fragments */
+    for( i=0; shader_source[i].type != GLSL_NO_SHADER; i++ ) {
+        gl_shader_t shader = INVALID_SHADER;
+        switch(shader_source[i].type) {
+        case GLSL_VERTEX_SHADER:
+            shader = glsl_create_vertex_shader(shader_source[i].source);
+            break;
+        case GLSL_FRAGMENT_SHADER:
+            shader = glsl_create_fragment_shader(shader_source[i].source);
+            break;
+        }
+        if( shader == INVALID_SHADER ) {
+            ok = FALSE;
+            break;
+        } else {
+            shader_array[i] = shader;
+        }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( vsok && fsok ) {
-        if( vertex_src != NULL ) {
-            glAttachShader(glsl_program, glsl_vert_shader);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /* Link the programs */
+    if(ok) for( i=0; program_list[i][0] != GLSL_NO_SHADER; i++ ) {
+        gl_shader_t shaderv[GLSL_NUM_SHADERS+1];
+        for( j=0; program_list[i][j] != GLSL_NO_SHADER; j++ ) {
+            shaderv[j] = shader_array[program_list[i][j]];
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        if( fragment_src != NULL ) {
-            glAttachShader(glsl_program, glsl_frag_shader);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        shaderv[j] = INVALID_SHADER;
+        gl_program_t program = glsl_create_program(shaderv);
+        if( program == INVALID_PROGRAM ) {
+            ok = FALSE;
+            break;
+        } else {
+            program_array[i] = program;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        glLinkProgram(glsl_program);
-        pok = glsl_check_program_error( "Failed to link shader program", glsl_program );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( pok ) {
-        glUseProgram(glsl_program);
-        pok = glsl_check_program_error( "Failed to apply shader program", glsl_program );
-        glsl_enable_shaders(FALSE); // initially disabled
-    } else {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    /**
+     * Destroy the compiled fragments (the linked programs don't need them
+     * anymore)
+     */
+    for( i=0; i<GLSL_NUM_SHADERS; i++ ) {
+        if( shader_array[i] != INVALID_SHADER )
+            glsl_destroy_shader(shader_array[i]);
+    }
+
+    /**
+     * If we errored, delete the programs. It's all or nothing.
+     */
+    if( !ok ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         glsl_unload_shaders();
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        return FALSE;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    return <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >pok</span>;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    return <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >TRUE</span>;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
-void glsl_enable_shaders(gboolean en)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void glsl_unload_shaders()
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( glsl_program != 0 ) {
-        if( en ) {
-            glUseProgram(glsl_program);
-        } else {
-            glUseProgram(0);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    unsigned i;
+    for( i=0; i<GLSL_NUM_PROGRAMS; i++ ) {
+        if( program_array[i] != INVALID_PROGRAM ) {
+            glsl_destroy_program(program_array[i]);
+            program_array[i] = INVALID_PROGRAM;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         }
     }
 }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-void glsl_unload_shaders(void)
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean glsl_set_shader(unsigned i)
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glUseProgram(0);
-    glDetachShader(glsl_program, glsl_vert_shader);
-    glDetachShader(glsl_program, glsl_frag_shader);
-    glDeleteProgram(glsl_program);
-    glDeleteShader(glsl_vert_shader);
-    glDeleteShader(glsl_frag_shader);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    assert( i >= 0 && i <= GLSL_LAST_PROGRAM );
+
+    if( program_array[i] != INVALID_PROGRAM ) {
+        glsl_use_program(program_array[i]);
+        return TRUE;
+    } else {
+        return FALSE;
+    }
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-#else
-gboolean glsl_load_shaders( const char *vertex_src, const char *fragment_src )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+void glsl_clear_shader()
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    return FALSE;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glsl_use_program(0);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-
-void glsl_unload_shaders()
-{
-}
-
-void glsl_enable_shaders( gboolean enable )
-{
-}
-#endif
</pre></div>
<hr /><a name="file5" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>glrender.c</b></big> <small id="info" style="color: #888888;" >7b16bbd6209c -> 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glrender.c
+++ lxdream/src/pvr2/glrender.c
@@ -95,7 +95,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
 
     if( glsl_is_supported() ) {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        if( !glsl_load_shaders( glsl_vertex_shader_src, NULL ) ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        if( !glsl_load_shaders( ) ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             WARN( "Unable to load GL shaders" );
         }
     }
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -526,7 +526,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     glFogf(GL_FOG_START, 0.0);
     glFogf(GL_FOG_END, 1.0);
     /* Turn on the shaders (if available) */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glsl_enable_shaders(TRUE);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glsl_set_shader(DEFAULT_PROGRAM);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     /* Render the background */
     gl_render_bkgnd( pvr2_scene.bkgnd_poly );
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -580,7 +580,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     } while( !IS_LAST_SEGMENT(segment++) );
     glDisable( GL_SCISSOR_TEST );
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    glsl_enable_shaders(FALSE);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glsl_clear_shader();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
     gettimeofday( &end_tv, NULL );
     ms = (end_tv.tv_sec - tex_tv.tv_sec) * 1000 +
</pre></div>
<hr /><a name="file6" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/pvr2</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>glutil.h</b></big> <small id="info" style="color: #888888;" >7b16bbd6209c -> 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/glutil.h
+++ lxdream/src/pvr2/glutil.h
@@ -21,6 +21,7 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #include <stdio.h>
 #include "display.h"
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include "pvr2/shaders.h"
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #ifdef __cplusplus
 extern "C" {
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -49,12 +50,10 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /****** Shader handling (gl_sl.c) *****/
 gboolean glsl_is_supported(void);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-gboolean glsl_load_shaders( const char *vert_shader, const char *frag_shader );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean glsl_load_shaders( );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > void glsl_unload_shaders(void);
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-void glsl_enable_shaders( gboolean enable );
-
-extern const char *glsl_vertex_shader_src;
-extern const char *glsl_fragment_shader_src;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+gboolean glsl_set_shader( unsigned program_id );
+void glsl_clear_shader();
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 #ifdef __cplusplus
 }
</pre></div>
<hr /><a name="file7" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span id="added" class="pathname" style="font-family:monospace; float:right; background-color:#ddffdd;" >lxdream/src/pvr2</span><br />
<div id="added" class="fileheader" style="margin-bottom:.5em; background-color:#ddffdd;" ><big><b>shaders.glsl</b></big> <small id="info" style="color: #888888;" >added at 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/shaders.glsl
+++ lxdream/src/pvr2/shaders.glsl
@@ -0,0 +1,42 @@
</small></pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+/**
+ * $Id$
+ *
+ * Assorted shader definitions (optionally) used by the PVR2 rendering
+ * engine.
+ * 
+ * This file is preprocessed by genglsl to produce shaders.c and shaders.h.
+ *
+ * Copyright (c) 2007-2010 Nathan Keynes.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#vertex DEFAULT_VERTEX_SHADER
+void main()
+{
+    vec4 tmp = ftransform();
+    float w = gl_Vertex.z;
+    gl_Position  = tmp * w;
+    gl_FrontColor = gl_Color;
+    gl_FrontSecondaryColor = gl_SecondaryColor;
+    gl_TexCoord[0] = gl_MultiTexCoord0;
+    gl_FogFragCoord = gl_FogCoord;
+}
+
+#fragment DEFAULT_FRAGMENT_SHADER
+void main()
+{
+       gl_FragColor = gl_Color;
+       gl_FragDepth = gl_FragCoord.z;
+}
+
+#program DEFAULT_PROGRAM = DEFAULT_VERTEX_SHADER
+
</pre></div>
<hr /><a name="file8" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span id="removed" class="pathname" style="font-family:monospace; float:right; background-color:#ffdddd;" >lxdream/src/pvr2</span><br />
<div id="removed" class="fileheader" style="margin-bottom:.5em; background-color:#ffdddd;" ><big><b>vertex.glsl</b></big> <small id="info" style="color: #888888;" >removed after 7b16bbd6209c</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/pvr2/vertex.glsl
+++ lxdream/src/pvr2/vertex.glsl
@@ -1,12 +0,0 @@
</small></pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-// Standard PVR2 vertex shader
-
-void main()
-{
-    vec4 tmp = ftransform();
-    float w = gl_Vertex.z;
-    gl_Position  = tmp * w;
-    gl_FrontColor = gl_Color;
-    gl_FrontSecondaryColor = gl_SecondaryColor;
-    gl_TexCoord[0] = gl_MultiTexCoord0;
-    gl_FogFragCoord = gl_FogCoord;
-}
</pre></div>
<hr /><a name="file9" /><div class="file" style="border:1px solid #eeeeee;margin-top:1em;margin-bottom:1em;" >
<span class="pathname" style="font-family:monospace; float:right;" >lxdream/src/tools</span><br />
<div class="fileheader" style="margin-bottom:.5em;" ><big><b>genglsl.c</b></big> <small id="info" style="color: #888888;" >7b16bbd6209c -> 5f56fc931112</small></div>
<pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >--- lxdream/src/tools/genglsl.c
+++ lxdream/src/tools/genglsl.c
@@ -1,10 +1,13 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > /**
  * $Id$
  *
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * Trivial tool to take two shader source files and dump them out in
- * a C file with appropriate escaping.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Tool to take an input .glsl file and write out a corresponding .c and .h
+ * file based on the content. The .glsl file contains a number of shaders
+ * marked with either #fragment <name> or #vertex <name>
+ * a C file with appropriate escaping, as well as program definitions
+ * written as #program <name> = <shader1> <shader2> ... <shaderN>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  *
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >- * Copyright (c) 2007 Nathan Keynes.
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+ * Copyright (c) 2007<span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >-2010</span> Nathan Keynes.
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
</pre><pre class="diff" style="margin:0;" ><small id="info" style="color: #888888;" >@@ -17,62 +20,267 @@
</small></pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >  * GNU General Public License for more details.
  */
 
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <assert.h>
+#include <errno.h>
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > #include <stdio.h>
 #include <stdlib.h>
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+#include <string.h>
+#include <glib/gstrfuncs.h>
+#include <glib/glist.h>
+
+#define MAX_LINE 4096
+#define DEF_ALLOC_SIZE 4096
+#define MAX_SHADERS 128
+
+typedef enum {
+    VERTEX_SHADER = 0,
+    FRAGMENT_SHADER = 1
+} shader_type_t;
+
+typedef struct shader {
+    shader_type_t type;
+    const char *name;
+    char *body;
+} *shader_t;
+
+typedef struct program {
+    const char *name;
+    gchar **shader_names;
+} *program_t;
+
+typedef struct glsldata {
+    const char *filename;
+    unsigned max_shaders;
+    GList *shaders;
+    GList *programs;
+} *glsldata_t;
+
+static struct glsldata *readInput( const char *filename )
+{
+    char buf[MAX_LINE];
+    size_t current_size = 0, current_posn = 0;
+    unsigned i;
+
+    FILE *f = fopen( filename, "ro" );
+    if( f == NULL ) {
+        fprintf( stderr, "Error: unable to open input file '%s': %s\n", filename, strerror(errno) );
+        exit(1);
+    }
+
+    shader_t shader = NULL;
+    glsldata_t result = malloc(sizeof(struct glsldata));
+    assert( result != NULL );
+    result->filename = strdup(filename);
+    result->shaders = NULL;
+    result->programs = NULL;
+    result->max_shaders = 0;
+
+    while( fgets(buf, sizeof(buf), f) != NULL ) {
+        if( strlen(buf) == 0 )
+            continue;
+
+        if( strncmp(buf, "#vertex ", 8) == 0 ) {
+            shader = malloc(sizeof(struct shader));
+            assert( shader != NULL );
+            shader->type = VERTEX_SHADER;
+            shader->name = strdup(g_strstrip(buf+8));
+            shader->body = malloc(DEF_ALLOC_SIZE);
+            shader->body[0] = '\0';
+            current_size = DEF_ALLOC_SIZE;
+            current_posn = 0;
+            result->shaders = g_list_append(result->shaders, shader);
+        } else if( strncmp( buf, "#fragment ", 10 ) == 0 ) {
+            shader = malloc(sizeof(struct shader));
+            assert( shader != NULL );
+            shader->type = FRAGMENT_SHADER;
+            shader->name = strdup(g_strstrip(buf+10));
+            shader->body = malloc(DEF_ALLOC_SIZE);
+            shader->body[0] = '\0';
+            current_size = DEF_ALLOC_SIZE;
+            current_posn = 0;
+            result->shaders = g_list_append(result->shaders, shader);
+        } else if( strncmp( buf, "#program ", 9 ) == 0 ) {
+            shader = NULL;
+            program_t program = malloc(sizeof(struct program));
+            char *rest = buf+9;
+            char *equals = strchr(rest, '=');
+            if( equals == NULL ) {
+                fprintf( stderr, "Error: invalid program line %s\n", buf );
+                exit(2);
+            }
+            *equals = '\0';
+            program->name = g_strdup(g_strstrip(rest));
+            program->shader_names = g_strsplit_set(g_strstrip(equals+1), " \t\r,", 0);
+            result->programs = g_list_append(result->programs, program);
+            for(i=0;program->shader_names[i] != NULL; i++ );
+            if( i > result->max_shaders )
+                result->max_shaders = i;
+        } else if( shader != NULL ) {
+            size_t len = strlen(buf);
+            if( current_posn + len > current_size ) {
+                shader->body = realloc(shader->body, current_size*2);
+                assert( shader->body != NULL );
+                current_size *= 2;
+            }
+            strcpy( shader->body + current_posn, buf );
+            current_posn += len;
+        }
+    }
+
+    fclose(f);
+    return result;
+}
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
 /**
  * Copy input to output, quoting " characters as we go.
  */
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-static void writeShader( FILE *out, FILE *in )
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+static void writeCString( FILE *out, const char *str )
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    int ch;
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    const char *p = str;
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" > 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    while( (ch = fgetc(in)) != EOF ) {
-        if( ch == '\"' ) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    while( *p != 0 ) {
+        if( *p == '\"' ) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             fputc( '\\', out );
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        } else if( <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >ch == '\n'</span>) {
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        } else if( <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >*p == '\n' </span>) {
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >             fputs( "\\n\\", out );
         }
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-        fputc( <span id="removedchars" style="background-color:#ff9999;font-weight:bolder;" >ch</span>, out );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+        fputc( <span id="addedchars" style="background-color:#99ff99;font-weight:bolder;" >*p</span>, out );
+        p++;
+    }
+}
+
+static void writeHeader( FILE *out, glsldata_t data )
+{
+    fprintf( out, "/*\n * This file automatically generated by genglsl from %s\n */\n", data->filename );
+}
+
+static void writeInterface( const char *filename, glsldata_t data )
+{
+    FILE *f = fopen(filename, "wo");
+    if( f == NULL ) {
+        fprintf( stderr, "Error: Unable to write interface file '%s': %s\n", filename, strerror(errno) );
+        exit(1);
+    }
+
+    writeHeader( f, data );
+    fprintf( f, "#ifndef lxdream_glsl_H\n#define lxdream_glsl_H 1\n\n" );
+
+    fprintf( f, "typedef enum {\n" );
+    const char *last_name = NULL;
+    int count = 0;
+    GList *shader_ptr;
+    for( shader_ptr = data->shaders; shader_ptr != NULL; shader_ptr = shader_ptr->next ) {
+        count++;
+        shader_t shader = (shader_t)shader_ptr->data;
+        fprintf( f, "    %s,\n", shader->name );
+        last_name = shader->name;
+    }
+    fprintf( f, "} shader_id;\n\n" );
+
+    if( last_name == NULL )
+        last_name = "NULL";
+    fprintf( f, "#define GLSL_LAST_SHADER %s\n", last_name );
+    fprintf( f, "#define GLSL_NUM_SHADERS %d\n", count );
+    fprintf( f, "#define GLSL_NO_SHADER -1\n\n" );
+    fprintf( f, "#define GLSL_VERTEX_SHADER 1\n" );
+    fprintf( f, "#define GLSL_FRAGMENT_SHADER 2\n" );
+
+    fprintf( f, "typedef enum {\n" );
+    last_name = NULL;
+    count = 0;
+    GList *program_ptr;
+    for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
+        count++;
+        program_t program = (program_t)program_ptr->data;
+        fprintf( f, "    %s,\n", program->name );
+        last_name = program->name;
+    }
+    fprintf( f, "} program_id;\n\n" );
+
+    if( last_name == NULL )
+        last_name = "NULL";
+    fprintf( f, "#define GLSL_LAST_PROGRAM %s\n", last_name );
+    fprintf( f, "#define GLSL_NUM_PROGRAMS %d\n", count );
+    fprintf( f, "#define GLSL_NO_PROGRAM -1\n\n" );
+
+    fprintf( f, "int glsl_load_programs();\n" );
+    fprintf( f, "void glsl_use_program_id( program_id );\n" );
+
+    fprintf( f, "#endif /* !lxdream_glsl_H */\n" );
+
+    fclose(f);
+}
+
+static void writeSource( const char *filename, glsldata_t data )
+{
+    FILE *f = fopen(filename, "wo");
+    if( f == NULL ) {
+        fprintf( stderr, "Error: Unable to write interface file '%s': %s\n", filename, strerror(errno) );
+        exit(1);
+    }
+
+    writeHeader( f, data );
+    fprintf( f, "struct shader_def {\n    int type;\n    const char *source;\n};\n" );
+
+    fprintf( f, "const struct shader_def shader_source[] = {\n" );
+    GList *shader_ptr;
+    for( shader_ptr = data->shaders; shader_ptr != NULL; shader_ptr = shader_ptr->next ) {
+        shader_t shader = (shader_t)shader_ptr->data;
+        fprintf( f, "    {%s,\"", (shader->type == VERTEX_SHADER ? "GLSL_VERTEX_SHADER" : "GLSL_FRAGMENT_SHADER") );
+        writeCString( f, shader->body );
+        fprintf( f, "\"},\n" );
+    }
+    fprintf( f, "    {GLSL_NO_SHADER,NULL}};\n\n" );
+
+    fprintf( f, "const int program_list[][%d] = {\n", data->max_shaders+1 );
+    GList *program_ptr;
+    unsigned i;
+    for( program_ptr = data->programs; program_ptr != NULL; program_ptr = program_ptr->next ) {
+        program_t program = (program_t)program_ptr->data;
+        fprintf( f, "    {" );
+        for( i=0; program->shader_names[i] != NULL; i++ ) {
+            fprintf(f, "%s,", program->shader_names[i] );
+        }
+        fprintf( f, "GLSL_NO_SHADER},\n" );
+    }
+    fprintf( f, "    {GLSL_NO_SHADER}};\n" );
+
+    fclose(f);
+}
+
+const char *makeExtension(const char *basename, const char *ext)
+{
+    const char *oldext = strrchr(basename, '.');
+    if( oldext == NULL ) {
+        return g_strdup_printf("%s%s", basename, ext);
+    } else {
+        return g_strdup_printf("%.*s%s", oldext-basename, basename, ext);
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 }
 
 int main( int argc, char *argv[] )
 {
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    if( argc != 4 ) {
-        fprintf( stderr, "Usage: genglsl <vertex-shader-file> <fragment-shader-file> <output-file>\n");
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( argc < 2 ) {
+        fprintf( stderr, "Usage: genglsl <glsl-source-file> [output.c [output.h]]\n");
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >         exit(1);
     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    FILE *vsin = fopen( argv[1], "ro" );
-    if( vsin == NULL ) {
-        perror( "Unable to open vertex shader source" );
-        exit(2);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    glsldata_t data = readInput(argv[1]);
+
+    const char *sourcefile, *ifacefile;
+    if( argc > 2 ) {
+        sourcefile = argv[2];
+    } else {
+        sourcefile = makeExtension(argv[1], ".def");
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    FILE *fsin = fopen( argv[2], "ro" );
-    if( fsin == NULL ) {
-        perror( "Unable to open fragment shader source" );
-        exit(2);
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    if( argc > 3 ) {
+        ifacefile = argv[3];
+    } else {
+        ifacefile = makeExtension(sourcefile, ".h");
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     }
 
</pre><pre id="removed" class="diff" style="margin:0; background-color:#ffdddd;" >-    FILE *out = fopen( argv[3], "wo" );
-    if( out == NULL ) {
-        perror( "Unable to open output file" );
-        exit(2);
-    }
-
-    fprintf( out, "/**\n * This file is automatically generated - do not edit\n */\n\n" );
-    fprintf( out, "const char *glsl_vertex_shader_src = \"" );
-
-    writeShader( out, vsin );
-
-    fprintf( out, "\";\n\n" );
-    fprintf( out, "const char *glsl_fragment_shader_src = \"" );
-    writeShader( out, fsin );
-    fprintf( out, "\";\n\n" );
-    fclose( fsin );
-    fclose( vsin );
-    fclose( out );
</pre><pre id="added" class="diff" style="margin:0; background-color:#ddffdd;" >+    writeSource( sourcefile, data );
+    writeInterface( ifacefile, data );
</pre><pre id="context" class="diff" style="margin:0; background-color:#eeeeee;" >     return 0;
 }
</pre></div>
<center><small>Chaos Theory</small></center>
</div></body></html>