All pastes #341324 Raw Edit

Unnamed

public text v1 · immutable
·published 2007-02-05 14:59 UTC
rendered paste body
Index: beryl-plugins-unsupported/src/group/group.h
===================================================================
--- beryl-plugins-unsupported/src/group/group.h	(Revision 3571)
+++ beryl-plugins-unsupported/src/group/group.h	(Arbeitskopie)
@@ -595,7 +595,7 @@
 Bool groupPaintScreen(CompScreen * s, const ScreenPaintAttrib * sAttrib, Region region, int output, unsigned int mask);
 void groupPaintTransformedScreen(CompScreen * s, const ScreenPaintAttrib * sa, Region region, int output, unsigned int mask);
 void groupDonePaintScreen(CompScreen * s);
-Bool groupDrawWindow(CompWindow * w,	const WindowPaintAttrib * attrib, Region region, unsigned int mask);
+Bool groupDrawWindow(CompWindow * w,	const FragmentAttrib * attrib, Region region, unsigned int mask);
 Bool groupPaintWindow(CompWindow * w, const WindowPaintAttrib * attrib, Region region, unsigned int mask);
 
 /*
Index: beryl-plugins-unsupported/src/group/paint.c
===================================================================
--- beryl-plugins-unsupported/src/group/paint.c	(Revision 3571)
+++ beryl-plugins-unsupported/src/group/paint.c	(Arbeitskopie)
@@ -61,6 +61,7 @@
 	sAttrib.opacity = sAttrib.opacity * targetOpacity / 0xffff;
 
 	if (w->mapNum) {
+		FragmentAttrib fragment;
 
 		if (WIN_WIDTH(w) > tw)
 			sAttrib.xScale = (float) tw / WIN_WIDTH(w);
@@ -83,9 +84,14 @@
 		sAttrib.xTranslate = slot->region->extents.x1 - w->attrib.x + vx;
 		sAttrib.yTranslate = slot->region->extents.y1 - w->attrib.y + vy;
 
-		(w->screen->drawWindow) (w, &sAttrib, getInfiniteRegion(),
+		initFragmentAttrib (&fragment, &sAttrib);
+		pushWindowTransform (w, &sAttrib);
+
+		(w->screen->drawWindow) (w, &fragment, getInfiniteRegion(),
 			PAINT_WINDOW_TRANSFORMED_MASK);
 
+		glPopMatrix();
+
 		addWindowDamage(w);
 	}
 	
@@ -480,10 +486,19 @@
 			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 			glColor4us(alpha, alpha, alpha, alpha);
 
-			(*topTab->screen->drawWindowTexture) (topTab, 
-				&layer->texture, &attrib,
-				PAINT_WINDOW_TRANSLUCENT_MASK | PAINT_WINDOW_TRANSFORMED_MASK);
+			if (topTab->vCount) {
+				FragmentAttrib fAttrib;
 
+				initFragmentAttrib (&fAttrib, &attrib);
+				pushWindowTransform (topTab, &attrib);
+
+				(*topTab->screen->drawWindowTexture) (topTab, 
+					&layer->texture, &fAttrib,
+					PAINT_WINDOW_TRANSLUCENT_MASK | PAINT_WINDOW_TRANSFORMED_MASK);
+
+				glPopMatrix();
+			}
+
 			screenTexEnvMode (s, GL_REPLACE);
 			glColor4usv(defaultColor);
 		}
@@ -941,7 +956,7 @@
  */
 Bool
 groupDrawWindow(CompWindow * w,
-		const WindowPaintAttrib * attrib,
+		const FragmentAttrib * attrib,
 		Region region, unsigned int mask)
 {
 	Bool status;
@@ -972,11 +987,11 @@
 			}
 
 			if (w->vCount) {
-				WindowPaintAttrib wAttrib = *attrib;
+				FragmentAttrib fAttrib = *attrib;
 
-				wAttrib.opacity = OPAQUE;
-				wAttrib.saturation = COLOR;
-				wAttrib.brightness = BRIGHT;
+				fAttrib.opacity = OPAQUE;
+				fAttrib.saturation = COLOR;
+				fAttrib.brightness = BRIGHT;
 
 				glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 				//glBlendFunc(GL_SRC_ALPHA, GL_ONE); - maybe add an option for that...
@@ -986,7 +1001,8 @@
 
 				/* we use PAINT_WINDOW_TRANSFORMED_MASK here to force
 				   the usage of a good texture filter */
-				(*w->screen->drawWindowTexture) (w, &gs->glowTexture, &wAttrib,
+
+				(*w->screen->drawWindowTexture) (w, &gs->glowTexture, &fAttrib,
 					mask | PAINT_WINDOW_TRANSLUCENT_MASK | PAINT_WINDOW_TRANSFORMED_MASK);
 
 				glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
Index: beryl-plugins-unsupported/src/tile.c
===================================================================
--- beryl-plugins-unsupported/src/tile.c	(Revision 3571)
+++ beryl-plugins-unsupported/src/tile.c	(Arbeitskopie)
@@ -224,6 +224,7 @@
 	if(tw->isResizing && td->currentAnimationType != outline) // on window texture animation
 	{
 	WindowPaintAttrib sAttrib = *attrib;
+	FragmentAttrib fragment;
 
 	glPushMatrix();
 	glLoadIdentity();
@@ -236,7 +237,11 @@
 		*/
 		case drop:
 			glRotatef(100.0f/td->animationDuration*ts->msResizing - 100, 0,0,1);
-			(*s->drawWindow) (w, &sAttrib, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+
+			initFragmentAttrib(&fragment, attrib);
+			pushWindowTransform(w, attrib);
+			(*s->drawWindow) (w, &fragment, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			glPopMatrix();
 		break;
 
 		/*
@@ -244,7 +249,10 @@
 		*/
 		case zoom:
 			glTranslatef(0,0, -1 + ts->msResizing/(float)td->animationDuration);
-			(*s->drawWindow) (w, &sAttrib, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			initFragmentAttrib(&fragment, attrib);
+			pushWindowTransform(w, attrib);
+			(*s->drawWindow) (w, &fragment, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			glPopMatrix();
 		break;
 
 		/*
@@ -255,10 +263,14 @@
 				sAttrib.opacity = OPAQUE / 2;
 			else
 				sAttrib.opacity = OPAQUE/2 + OPAQUE/2*(ts->msResizing - 0.75*td->animationDuration)/(0.25*td->animationDuration);
+
+			initFragmentAttrib (&fragment, &sAttrib);
 			
 			if(ts->msResizing > current*ts->oneDuration) // windows that have animation finished already
 			{
-				(*s->drawWindow) (w, &sAttrib, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+				pushWindowTransform (w, &sAttrib);
+				(*s->drawWindow) (w, &fragment, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+				glPopMatrix();
 			}
 			else if(ts->msResizing > (current-1)*ts->oneDuration && ts->msResizing < current*ts->oneDuration) // animation in progress
 			{
@@ -271,7 +283,9 @@
 				else
 					glTranslatef(s->width - s->width * (float)thisDur/ts->oneDuration, 0, 0);
 
-				(*s->drawWindow) (w, &sAttrib, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+				pushWindowTransform(w, &sAttrib);
+				(*s->drawWindow) (w, &fragment, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+				glPopMatrix();
 			}
 		break;
 
@@ -290,14 +304,20 @@
 		if(ts->msResizing < 0.40f*td->animationDuration)
 		{
 			sAttrib.opacity = OPAQUE - OPAQUE*ts->msResizing/(0.40f*td->animationDuration);
-			(*s->drawWindow) (w, &sAttrib, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			initFragmentAttrib(&fragment, &sAttrib);
+			pushWindowTransform(w, &sAttrib);
+			(*s->drawWindow) (w, &fragment, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			glPopMatrix();
 		}
 		else if(ts->msResizing > 0.40f*td->animationDuration && !tw->resizedAlready) // resize window right after first half
 			setWindowFutureSize(w);
 		else if(ts->msResizing > 0.60f*td->animationDuration) // second half of animation, fade in
 		{
 			sAttrib.opacity = OPAQUE*(ts->msResizing - 0.60f*td->animationDuration)/(0.40f*td->animationDuration);
-			(*s->drawWindow) (w, &sAttrib, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			initFragmentAttrib(&fragment, &sAttrib);
+			pushWindowTransform(w, &sAttrib);
+			(*s->drawWindow) (w, &fragment, region, mask | PAINT_WINDOW_TRANSFORMED_MASK);
+			glPopMatrix();
 		}
 		break;
 	}
Index: beryl-plugins/src/wobbly.c
===================================================================
--- beryl-plugins/src/wobbly.c	(Revision 3571)
+++ beryl-plugins/src/wobbly.c	(Arbeitskopie)
@@ -278,7 +278,6 @@
 	DamageWindowRectProc damageWindowRect;
 	AddWindowGeometryProc addWindowGeometry;
 	DrawWindowGeometryProc drawWindowGeometry;
-	DrawWindowTextureProc drawWindowTexture;
 
 	WindowResizeNotifyProc windowResizeNotify;
 	WindowMoveNotifyProc windowMoveNotify;
Index: beryl-plugins/src/blurfx.c
===================================================================
--- beryl-plugins/src/blurfx.c	(Revision 3571)
+++ beryl-plugins/src/blurfx.c	(Arbeitskopie)
@@ -1198,7 +1198,9 @@
 
 		for (w = s->reverseWindows; w; w = w->prev)
 		{
+			FragmentAttrib fragment;
 			BLURFX_WINDOW(w);
+
 			if (w->destroyed)
 				continue;
 
@@ -1211,8 +1213,14 @@
 					continue;
 			}
 			XUnionRegion(bs->occlusion, getEmptyRegion(), bw->clip);
-			(*s->drawWindow) (w, &w->paint, &s->region,
+
+			initFragmentAttrib (&fragment, &w->paint);
+			pushWindowTransform (w, &w->paint);
+
+			(*s->drawWindow) (w, &fragment, &s->region,
 							  PAINT_WINDOW_SOLID_MASK);
+
+			glPopMatrix();
 		}
 	}
 
@@ -1545,7 +1553,9 @@
 
 		for (w = s->reverseWindows; w; w = w->prev)
 		{
+			FragmentAttrib fragment;
 			BLURFX_WINDOW(w);
+
 			if (w->destroyed)
 				continue;
 
@@ -1555,8 +1565,14 @@
 					continue;
 			}
 			XUnionRegion(bs->occlusion, getEmptyRegion(), bw->clip);
-			(*s->drawWindow) (w, &w->paint, &s->region,
+
+			initFragmentAttrib (&fragment, &w->paint);
+			pushWindowTransform (w, &w->paint);
+
+			(*s->drawWindow) (w, &fragment, &s->region,
 							  PAINT_WINDOW_SOLID_MASK);
+
+			glPopMatrix();
 		}
 	}
 	bs->mode = MODE_NORMAL;
@@ -1567,7 +1583,7 @@
 
 
 static Bool
-blurfxDrawWindow(CompWindow * w, const WindowPaintAttrib * attrib,
+blurfxDrawWindow(CompWindow * w, const FragmentAttrib * attrib,
 				 Region region, unsigned int mask)
 {
 	Bool status;
@@ -1796,7 +1812,7 @@
 
 static void
 blurfxDrawWindowTexture(CompWindow * w, CompTexture * texture,
-						const WindowPaintAttrib * attrib, unsigned int mask)
+						const FragmentAttrib * attrib, unsigned int mask)
 {
 
 	CompScreen *s = w->screen;
@@ -4084,7 +4100,7 @@
 
 static void
 drawReflection(CompWindow * w, CompScreen * s, CompTexture * texture,
-			   const WindowPaintAttrib * attrib, int mask,
+			   const FragmentAttrib * attrib, int mask,
 			   CompTextureFilter filter)
 {
 
Index: beryl-plugins/src/blurfx.h
===================================================================
--- beryl-plugins/src/blurfx.h	(Revision 3571)
+++ beryl-plugins/src/blurfx.h	(Arbeitskopie)
@@ -331,9 +331,9 @@
 static Bool blurfxPaintScreen(CompScreen *s, const ScreenPaintAttrib *sa, Region region, int output, unsigned int mask);
 static void blurfxPaintTransformedScreen(CompScreen *s, const ScreenPaintAttrib
 *sa, Region region, int output, unsigned int mask);
-static Bool blurfxDrawWindow (CompWindow *w, const WindowPaintAttrib *attrib,
+static Bool blurfxDrawWindow (CompWindow *w, const FragmentAttrib *attrib,
 Region region, unsigned int mask);
-static void blurfxDrawWindowTexture(CompWindow *w,CompTexture *texture, const WindowPaintAttrib *attrib, unsigned int mask);
+static void blurfxDrawWindowTexture(CompWindow *w,CompTexture *texture, const FragmentAttrib *attrib, unsigned int mask);
 static void blurfxAddWindowGeometry (CompWindow *w, CompMatrix *m, int nM, Region region, Region clip);
 static Bool blurfxDamageWindowRect (CompWindow *w, Bool initial, BoxPtr box);
 static void updateBlur(CompWindow *w, CompScreen *s, const WindowPaintAttrib *attrib, unsigned int mask, CompTextureFilter filter);
Index: beryl-plugins/src/animation.c
===================================================================
--- beryl-plugins/src/animation.c	(Revision 3571)
+++ beryl-plugins/src/animation.c	(Arbeitskopie)
@@ -8304,7 +8304,8 @@
 
 static void
 animDrawWindowTexture(CompWindow * w, CompTexture * texture,
-					  const WindowPaintAttrib * attrib, unsigned int mask)
+					  const FragmentAttrib * attrib,
+					  unsigned int mask)
 {
 	ANIM_WINDOW(w);
 	ANIM_SCREEN(w->screen);
@@ -8314,7 +8315,9 @@
 		//printf("%X animDrawWindowTexture, texture: %X\n",
 		//     (unsigned)aw, (unsigned)texture);
 		aw->curTexture = texture;
-		aw->curPaintAttrib = *attrib;
+		aw->curPaintAttrib.opacity = attrib->opacity;
+		aw->curPaintAttrib.saturation = attrib->saturation;
+		aw->curPaintAttrib.brightness = attrib->brightness;
 	}
 
 	UNWRAP(as, w->screen, drawWindowTexture);
Index: beryl-plugins/src/neg.c
===================================================================
--- beryl-plugins/src/neg.c	(Revision 3571)
+++ beryl-plugins/src/neg.c	(Arbeitskopie)
@@ -179,13 +179,15 @@
 static void
 NEGDrawWindowTexture(CompWindow * w,
 					 CompTexture * texture,
-					 const WindowPaintAttrib * attrib, unsigned int mask)
+					 const FragmentAttrib * attrib,
+					 unsigned int mask)
 {
 	int filter;
 
 	NEG_SCREEN(w->screen);
 	NEG_WINDOW(w);
 
+#ifdef FIX_THIS_CODE	
 	/* PAINT_WINDOW_DECORATION_MASK is set when the decorations are being painted
 	 * I didn't want to paint them negative too
 	 */
@@ -484,11 +486,12 @@
 	}
 	else
 	{
+#endif		
 		/* not negative */
 		UNWRAP(ns, w->screen, drawWindowTexture);
 		(*w->screen->drawWindowTexture) (w, texture, attrib, mask);
 		WRAP(ns, w->screen, drawWindowTexture, NEGDrawWindowTexture);
-	}
+//	}
 }
 static Bool NEGDamageWindowRect(CompWindow * w, Bool initial, BoxPtr rect)
 {
Index: beryl-plugins/src/water.c
===================================================================
--- beryl-plugins/src/water.c	(Revision 3571)
+++ beryl-plugins/src/water.c	(Arbeitskopie)
@@ -36,15 +36,17 @@
 
 #define TEXTURE_SIZE 256
 
-#define PROGRAM_BUMP	      0
-#define PROGRAM_BUMP_RECT     1
-#define PROGRAM_BUMP_SAT      2
-#define PROGRAM_BUMP_SAT_RECT 3
-#define PROGRAM_WATER	      4
-#define PROGRAM_NUM	      5
-
 #define TEXTURE_NUM  3
 
+typedef struct _WaterFunction {
+	struct _WaterFunction *next;
+
+	int handle;
+	int target;
+	int param;
+	int unit;
+} WaterFunction;
+
 #define TINDEX(ws, i) (((ws)->tIndex + (i)) % TEXTURE_NUM)
 
 #define CLAMP(v, min, max) \
@@ -135,7 +137,7 @@
 	int grabIndex;
 	int width, height;
 
-	GLuint program[PROGRAM_NUM];
+	GLuint program;
 	GLuint texture[TEXTURE_NUM];
 
 	int tIndex;
@@ -160,6 +162,7 @@
 
 	Window current;
 
+	WaterFunction *bumpMapFunctions;
 } WaterScreen;
 
 #define GET_WATER_DISPLAY(d)				      \
@@ -180,42 +183,6 @@
 
 static Bool waterWiperTimeout(void *closure);
 
-static const char *saturateFpString =
-		"MUL temp, rgb, { 1.0, 1.0, 1.0, 0.0 };"
-		"DP3 temp, temp, program.local[1];"
-		"LRP rgb.xyz, program.local[1].w, rgb, temp;";
-
-static const char *bumpFpString =
-		"!!ARBfp1.0"
-		"PARAM light0color = state.light[0].diffuse;"
-		"TEMP rgb, normal, temp, total, bump, offset;"
-/* get normal from normal map */
-		"TEX normal, fragment.texcoord[1], texture[1], %s;"
-/* save height */
-		"MOV offset, normal;"
-/* remove scale and bias from normal */
-		"SUB normal, normal, 0.5;" "MUL normal, normal, 2.0;"
-/* normalize the normal map */
-		"DP3 temp, normal, normal;"
-		"RSQ temp, temp.x;" "MUL normal, normal, temp;"
-/* scale down normal by height and constant and use as offset in texture */
-		"MUL offset, normal, offset.w;"
-		"MUL offset, offset, program.local[0];"
-		"ADD offset, fragment.texcoord[0].xyzw, offset.yxzz;"
-/* get texture data */
-		"TEX rgb, offset, texture[0], %s;"
-/* normal dot lightdir, this should eventually be changed to a real light
-   vector */
-		"DP3 bump, normal, { 0.707, 0.707, 0.0, 0.0 };"
-		"MUL bump, bump, light0color;"
-/* diffuse per-vertex lighting, opacity and brightness
-   and add lightsource bump color */
-		"MAD rgb, fragment.color, rgb, bump;"
-/* saturation */
-		"%s"
-/* output */
-		"MOV result.color, rgb;" "END";
-
 static const char *waterFpString =
 		"!!ARBfp1.0"
 		"PARAM param = program.local[0];"
@@ -300,57 +267,131 @@
 				"RECT", "RECT",
 				1.0f, 1.0f, 1.0f, 1.0f, "RECT", "RECT", "RECT", "RECT");
 
-	return loadFragmentProgram(s, &ws->program[PROGRAM_WATER], buffer);
+	return loadFragmentProgram(s, &ws->program, buffer);
 }
 
-static int loadBumpMapProgram(CompScreen * s, int program)
+static int
+getBumpMapFragmentFunction (CompScreen  *s,
+                            CompTexture *texture,
+                            int         unit,
+                            int         param)
 {
-	const char *normalTarget = "2D";
-	const char *textureTarget = "2D";
-	const char *saturation = "";
-	char buffer[1024];
+    WaterFunction    *function;
+    CompFunctionData *data;
+    int              target;
 
 	WATER_SCREEN(s);
 
-	if (!s->fragmentProgram)
+	if (texture->target == GL_TEXTURE_2D)
+		target = COMP_FETCH_TARGET_2D;
+	else
+		target = COMP_FETCH_TARGET_RECT;
+
+	for (function = ws->bumpMapFunctions; function; function = function->next)
 	{
-		fprintf(stderr,
-				"%s: water: GL_ARB_fragment_program is missing\n",
-				getProgramName());
-		return 0;
+		if (function->param == param && function->unit == unit &&
+			function->target == target)
+			return function->handle;
 	}
 
-	switch (program)
+	data = createFunctionData ();
+	if (data)
 	{
-	case PROGRAM_BUMP_SAT:
-		saturation = saturateFpString;
-		/* fall-through */
-	case PROGRAM_BUMP:
-		break;
-	case PROGRAM_BUMP_SAT_RECT:
-		saturation = saturateFpString;
-		/* fall-through */
-	case PROGRAM_BUMP_RECT:
-		textureTarget = "RECT";
-		break;
-	}
+		static char *temp[] = { "normal", "temp", "total", "bump", "offset" };
+		int         i, handle = 0;
+		char        str[1024];
 
-	if (ws->target != GL_TEXTURE_2D)
-		normalTarget = "RECT";
+		for (i = 0; i < sizeof (temp) / sizeof (temp[0]); i++)
+		{
+			if (!addTempHeaderOpToFunctionData (data, temp[i]))
+			{
+				destroyFunctionData (data);
+				return 0;
+			}
+		}
 
-	sprintf(buffer, bumpFpString, normalTarget, textureTarget, saturation);
+		snprintf (str, 1024,
+				  /* get normal from normal map */
+                  "TEX normal, fragment.texcoord[%d], texture[%d], %s;"
+                  /* save height */
+                  "MOV offset, normal;"
+	              /* remove scale and bias from normal */
+                  "SUB normal, normal, 0.5;"
+                  "MUL normal, normal, 2.0;"
+                  /* normalize the normal map */
+                  "DP3 temp, normal, normal;"
+                  "RSQ temp, temp.x;"
+                  "MUL normal, normal, temp;"
+                  /* scale down normal by height and constant and use as
+                     offset in texture */
+                  "MUL offset, normal, offset.w;"
+                  "MUL offset, offset, program.env[%d];",
 
-	return loadFragmentProgram(s, &ws->program[program], buffer);
-}
+                  unit, unit,
+                  (ws->target == GL_TEXTURE_2D) ? "2D" : "RECT",
+                  param);
 
-static int ensureBumpMapProgram(CompScreen * s, int program)
-{
-	WATER_SCREEN(s);
+		if (!addDataOpToFunctionData (data, str))
+		{
+			destroyFunctionData (data);
+			return 0;
+		}
 
-	if (!ws->program[program])
-		return loadBumpMapProgram(s, program);
+		if (!addFetchOpToFunctionData (data, "output", "offset.yxzz", target))
+		{
+			destroyFunctionData (data);
+			return 0;
+		}
 
-	return 1;
+		snprintf (str, 1024,
+                  /* normal dot lightdir, this should eventually be
+                     changed to a real light vector */
+                  "DP3 bump, normal, { 0.707, 0.707, 0.0, 0.0 };"
+                  "MUL bump, bump, state.light[0].diffuse;");
+
+		if (!addDataOpToFunctionData (data, str))
+		{
+			destroyFunctionData (data);
+			return 0;
+		}
+
+		if (!addColorOpToFunctionData (data, "output", "output"))
+		{
+			destroyFunctionData (data);
+			return 0;
+		}
+
+		snprintf (str, 1024,
+                  /* diffuse per-vertex lighting, opacity and brightness
+                     and add lightsource bump color */
+                  "ADD output, output, bump;");
+
+		if (!addDataOpToFunctionData (data, str))
+		{
+			destroyFunctionData (data);
+			return 0;
+		}
+
+		function = malloc (sizeof (WaterFunction));
+		if (function)
+		{
+			handle = createFragmentFunction (s, "water", data);
+
+			function->handle = handle;
+			function->target = target;
+			function->param  = param;
+			function->unit   = unit;
+
+			function->next = ws->bumpMapFunctions;
+			ws->bumpMapFunctions = function;
+		}
+
+		destroyFunctionData (data);
+
+		return handle;
+	}
+
+	return 0;
 }
 
 static void allocTexture(CompScreen * s, int index)
@@ -477,7 +518,7 @@
 	glTexParameteri(ws->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
 	glEnable(GL_FRAGMENT_PROGRAM_ARB);
-	(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, ws->program[PROGRAM_WATER]);
+	(*s->bindProgram) (GL_FRAGMENT_PROGRAM_ARB, ws->program);
 
 	(*s->programLocalParameter4f) (GL_FRAGMENT_PROGRAM_ARB, 0,
 								   dt *
@@ -855,7 +896,7 @@
 	WATER_SCREEN(s);
 	WATER_DISPLAY(s->display);
 
-	if (!ensureBumpMapProgram(s, PROGRAM_BUMP))
+	if (!s->fragmentProgram)
 		return;
 
 	scaleVertices(s, p, n);
@@ -931,7 +972,7 @@
 		ws->ty = ws->height;
 	}
 
-	if (!loadBumpMapProgram(s, PROGRAM_BUMP))
+	if (!s->fragmentProgram)
 		return;
 
 	if (s->fbo)
@@ -978,9 +1019,9 @@
 static void
 waterDrawWindowTexture(CompWindow * w,
 					   CompTexture * texture,
-					   const WindowPaintAttrib * attrib, unsigned int mask)
+					   const FragmentAttrib *attrib,
+					   unsigned int mask)
 {
-	WATER_DISPLAY(w->screen->display);
 	WATER_SCREEN(w->screen);
 
 	if (w->id == ws->current)
@@ -994,160 +1035,67 @@
 
 	if (ws->count)
 	{
+		FragmentAttrib fa = *attrib;
 		Bool lighting = w->screen->lighting;
+		int param, function, unit;
 		GLfloat plane[4];
-		int program;
 
-		screenLighting(w->screen, TRUE);
+		WATER_DISPLAY (w->screen->display);
 
-		glPushMatrix();
+		param = allocFragmentParameters (&fa, 1);
+		unit = allocFragmentTextureUnits (&fa, 1);
 
-		enableTexture(w->screen, texture,
-					  w->screen->filter[WINDOW_TRANS_FILTER]);
-
-		(*w->screen->activeTexture) (GL_TEXTURE1_ARB);
-
-		glBindTexture(ws->target, ws->texture[TINDEX(ws, 0)]);
-
-		plane[1] = plane[2] = 0.0f;
-		plane[0] = ws->tx / (GLfloat) w->screen->width;
-		plane[3] = 0.0f;
-
-		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-		glTexGenfv(GL_S, GL_EYE_PLANE, plane);
-		glEnable(GL_TEXTURE_GEN_S);
-
-		plane[0] = plane[2] = 0.0f;
-		plane[1] = ws->ty / (GLfloat) w->screen->height;
-		plane[3] = 0.0f;
-
-		glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
-		glTexGenfv(GL_T, GL_EYE_PLANE, plane);
-		glEnable(GL_TEXTURE_GEN_T);
-
-		if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+		function = getBumpMapFragmentFunction (w->screen, texture, unit, param);
+		if (function)
 		{
-			glTranslatef(w->attrib.x, w->attrib.y, 0.0f);
-			glScalef(attrib->xScale, attrib->yScale, 0.0f);
-			glTranslatef(attrib->xTranslate / attrib->xScale -
-						 w->attrib.x,
-						 attrib->yTranslate / attrib->yScale -
-						 w->attrib.y, 0.0f);
-		}
+			addFragmentFunction (&fa, function);
+			screenLighting (w->screen, TRUE);
 
-		glEnable(GL_FRAGMENT_PROGRAM_ARB);
+			(*w->screen->activeTexture) (GL_TEXTURE0_ARB + unit);
+			glBindTexture (ws->target, ws->texture[TINDEX (ws, 0)]);
 
-		if (w->screen->canDoSaturated && attrib->saturation != COLOR)
-		{
-			if (texture->target == GL_TEXTURE_2D)
-				program = PROGRAM_BUMP_SAT;
-			else
-				program = PROGRAM_BUMP_SAT_RECT;
+			plane[0] = ws->tx / (GLfloat) w->screen->width;
+			plane[1] = plane[2] = plane[3] = 0.0f;
 
-			ensureBumpMapProgram(w->screen, program);
+			glTexGeni (GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+			glTexGenfv (GL_S, GL_EYE_PLANE, plane);
+			glEnable (GL_TEXTURE_GEN_S);
 
-			(*w->screen->bindProgram) (GL_FRAGMENT_PROGRAM_ARB,
-									   ws->program[program]);
+			plane[0] = 0.0f;
+			plane[1] = ws->ty / (GLfloat) w->screen->height;
+			plane[2] = plane[3] = 0.0f;
 
-			(*w->screen->
-			 programLocalParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
-									   0,
-									   texture->matrix.yy *
-									   wd->
-									   opt
-									   [WATER_DISPLAY_OPTION_OFFSET_SCALE].
-									   value.f * 50.0f,
-									   -texture->matrix.xx *
-									   wd->
-									   opt
-									   [WATER_DISPLAY_OPTION_OFFSET_SCALE].
-									   value.f * 50.0f, 0.0f, 0.0f);
+			glTexGeni (GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
+			glTexGenfv (GL_T, GL_EYE_PLANE, plane);
+			glEnable (GL_TEXTURE_GEN_T);
 
-			(*w->screen->
-			 programLocalParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
-									   1,
-									   RED_SATURATION_WEIGHT,
-									   GREEN_SATURATION_WEIGHT,
-									   BLUE_SATURATION_WEIGHT,
-									   attrib->saturation / 65535.0f);
-		}
-		else
-		{
-			if (texture->target == GL_TEXTURE_2D)
-				program = PROGRAM_BUMP;
-			else
-				program = PROGRAM_BUMP_RECT;
+			(*w->screen->activeTexture) (GL_TEXTURE0_ARB);
 
-			ensureBumpMapProgram(w->screen, program);
-
-			(*w->screen->bindProgram) (GL_FRAGMENT_PROGRAM_ARB,
-									   ws->program[program]);
-
-			(*w->screen->
-			 programLocalParameter4f) (GL_FRAGMENT_PROGRAM_ARB,
-									   0,
-									   texture->matrix.yy *
-									   wd->
-									   opt
-									   [WATER_DISPLAY_OPTION_OFFSET_SCALE].
-									   value.f * 50.0f,
-									   -texture->matrix.xx *
-									   wd->
-									   opt
-									   [WATER_DISPLAY_OPTION_OFFSET_SCALE].
-									   value.f * 50.0f, 0.0f, 0.0f);
+			(*w->screen->programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB, 
+					param, texture->matrix.yy * 
+					wd->opt[WATER_DISPLAY_OPTION_OFFSET_SCALE].value.f,
+					-texture->matrix.xx *
+					wd->opt[WATER_DISPLAY_OPTION_OFFSET_SCALE].value.f,
+					0.0f, 0.0f);
 		}
 
-		if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
-		{
-			glEnable(GL_BLEND);
-			if (attrib->opacity != OPAQUE || attrib->brightness != BRIGHT)
-			{
-				GLushort color;
+		/* to get appropriate texture filtering */
+		mask |= PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK;
 
-				color = (attrib->opacity * attrib->brightness) >> 16;
+		UNWRAP (ws, w->screen, drawWindowTexture);
+		(*w->screen->drawWindowTexture) (w, texture, &fa, mask);
+		WRAP (ws, w->screen, drawWindowTexture, waterDrawWindowTexture);
 
-				glColor4us(color, color, color, attrib->opacity);
-
-				(*w->screen->drawWindowGeometry) (w);
-
-				glColor4usv(defaultColor);
-			}
-			else
-			{
-				(*w->screen->drawWindowGeometry) (w);
-			}
-
-			glDisable(GL_BLEND);
-		}
-		else if (attrib->brightness != BRIGHT)
+		if (function)
 		{
-			screenTexEnvMode(w->screen, GL_MODULATE);
-			glColor4us(attrib->brightness, attrib->brightness,
-					   attrib->brightness, BRIGHT);
+		    (*w->screen->activeTexture) (GL_TEXTURE0_ARB + unit);
+			glDisable (GL_TEXTURE_GEN_T);
+		    glDisable (GL_TEXTURE_GEN_S);
+		    glBindTexture (ws->target, 0);
+			(*w->screen->activeTexture) (GL_TEXTURE0_ARB);
 
-			(*w->screen->drawWindowGeometry) (w);
-
-			glColor4usv(defaultColor);
-			screenTexEnvMode(w->screen, GL_REPLACE);
+		    screenLighting (w->screen, lighting);
 		}
-		else
-		{
-			(*w->screen->drawWindowGeometry) (w);
-		}
-
-		glDisable(GL_FRAGMENT_PROGRAM_ARB);
-
-		glDisable(GL_TEXTURE_GEN_T);
-		glDisable(GL_TEXTURE_GEN_S);
-
-		glBindTexture(ws->target, 0);
-		(*w->screen->activeTexture) (GL_TEXTURE0_ARB);
-		disableTexture(w->screen, texture);
-
-		glPopMatrix();
-
-		screenLighting(w->screen, lighting);
 	}
 	else
 	{
@@ -2132,6 +2080,7 @@
 
 static void waterFiniScreen(CompPlugin * p, CompScreen * s)
 {
+	WaterFunction *function, *next;
 	int i;
 
 	WATER_SCREEN(s);
@@ -2152,15 +2101,23 @@
 			glDeleteTextures(1, &ws->texture[i]);
 	}
 
-	for (i = 0; i < PROGRAM_NUM; i++)
-	{
-		if (ws->program[i])
-			(*s->deletePrograms) (1, &ws->program[i]);
-	}
+	if (ws->program)
+		(*s->deletePrograms) (1, &ws->program);
 
 	if (ws->data)
 		free(ws->data);
 
+	function = ws->bumpMapFunctions;
+	while (function)
+	{
+		destroyFragmentFunction (s, function->handle);
+
+		next = function->next;
+		free (function);
+
+		function = next;
+	}
+
 	UNWRAP(ws, s, preparePaintScreen);
 	UNWRAP(ws, s, donePaintScreen);
 	UNWRAP(ws, s, drawWindowTexture);
Index: beryl-plugins/src/scale.c
===================================================================
--- beryl-plugins/src/scale.c	(Revision 3571)
+++ beryl-plugins/src/scale.c	(Arbeitskopie)
@@ -982,13 +982,20 @@
 
 		if (scaled)
 		{
+			FragmentAttrib fragment;
+
 			sAttrib.xScale = sw->scale;
 			sAttrib.yScale = sw->scale;
 			sAttrib.xTranslate = sw->tx;
 			sAttrib.yTranslate = sw->ty;
 
-			(*s->drawWindow) (w, &sAttrib, region,
+			initFragmentAttrib (&fragment, &sAttrib);
+			pushWindowTransform (w, &sAttrib);
+
+			(*s->drawWindow) (w, &fragment, region,
 							  mask | PAINT_WINDOW_TRANSFORMED_MASK);
+
+			glPopMatrix ();
 		}
 
 		if ((ss->iconOverlay != ScaleIconNone) && scaled)
@@ -1153,9 +1160,21 @@
 													 &iconReg);
 
 				if (w->vCount)
+				{
+					FragmentAttrib fAttrib;
+
+					initFragmentAttrib (&fAttrib, &sAttrib);
+
+					if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+						pushWindowTransform (w, &sAttrib);
+
 					(*w->screen->drawWindowTexture) (w,
-													 &icon->texture, &sAttrib,
-													 mask);
+													 &icon->texture, 
+													 &fAttrib, mask);
+
+					if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+						glPopMatrix ();
+				}
 			}
 		}
 	}
Index: beryl-plugins/src/decoration.c
===================================================================
--- beryl-plugins/src/decoration.c	(Revision 3571)
+++ beryl-plugins/src/decoration.c	(Arbeitskopie)
@@ -315,7 +315,7 @@
 
 static Bool
 decorDrawWindow(CompWindow * w,
-				const WindowPaintAttrib * attrib,
+				const FragmentAttrib *attrib,
 				Region region, unsigned int mask)
 {
 	Bool status;
@@ -327,6 +327,10 @@
 	DECOR_SCREEN(w->screen);
 	DECOR_DISPLAY(w->screen->display);
 
+	UNWRAP(ds, w->screen, drawWindow);
+	status = (*w->screen->drawWindow) (w, attrib, region, mask);
+	WRAP(ds, w->screen, drawWindow, decorDrawWindow);
+
 	if (!(mask & PAINT_WINDOW_SOLID_MASK))
 	{
 		DECOR_WINDOW(w);
@@ -337,7 +341,7 @@
 		if (dw->wd && region->numRects)
 		{
 			WindowDecoration *wd = dw->wd;
-			WindowPaintAttrib sAttrib = *attrib;
+			FragmentAttrib fAttrib = *attrib;
 			REGION box;
 			int i;
 
@@ -363,28 +367,21 @@
 
 			if (!dd->opt[DECOR_DISPLAY_OPTION_APPLY_PAINT_MODIFIERS].value.b)
 			{
-				sAttrib.opacity = OPAQUE;
-				sAttrib.saturation = COLOR;
-				sAttrib.brightness = BRIGHT;
+				fAttrib.opacity = OPAQUE;
+				fAttrib.saturation = COLOR;
+				fAttrib.brightness = BRIGHT;
 			}
 
 			if (w->vCount)
 			{
 				(*w->screen->drawWindowTexture) (w,
-												 &wd->decor->texture->texture,
-												 &sAttrib,
-												 mask |
-												 PAINT_WINDOW_TRANSLUCENT_MASK
-												 |
-												 PAINT_WINDOW_DECORATION_MASK);
+						&wd->decor->texture->texture, &fAttrib,
+						mask | PAINT_WINDOW_TRANSLUCENT_MASK |
+						PAINT_WINDOW_DECORATION_MASK);
 			}
 		}
 	}
 
-	UNWRAP(ds, w->screen, drawWindow);
-	status = (*w->screen->drawWindow) (w, attrib, region, mask);
-	WRAP(ds, w->screen, drawWindow, decorDrawWindow);
-
 	return status;
 }
 
Index: beryl-plugins/src/switcher.c
===================================================================
--- beryl-plugins/src/switcher.c	(Revision 3571)
+++ beryl-plugins/src/switcher.c	(Arbeitskopie)
@@ -1866,6 +1866,7 @@
 	if (w->mapNum || w->thumbPixmap)
 	{
 		int ww, wh;
+		FragmentAttrib fragment;
 
 		if (ss->switchMode == RingSwitcher)
 		{
@@ -1919,8 +1920,13 @@
 				wx - w->attrib.x + w->input.left * sAttrib.xScale;
 		sAttrib.yTranslate = wy - w->attrib.y + w->input.top * sAttrib.yScale;
 
-		(w->screen->drawWindow) (w, &sAttrib, getInfiniteRegion(), mask);
+		initFragmentAttrib (&fragment, &sAttrib);
+		pushWindowTransform (w, &sAttrib);
 
+		(w->screen->drawWindow) (w, &fragment, getInfiniteRegion(), mask);
+
+		glPopMatrix ();
+
 		if (ss->opt[SWITCH_SCREEN_OPTION_ICON].value.b)
 		{
 			icon = getWindowIcon(w, 96, 96);
@@ -2076,8 +2082,17 @@
 		addWindowGeometry(w, &matrix, 1, &iconReg, getInfiniteRegion());
 
 		if (w->vCount)
+		{
+			FragmentAttrib fAttrib;
+
+			initFragmentAttrib (&fAttrib, &sAttrib);
+			pushWindowTransform (w, &sAttrib);
+
 			(*w->screen->drawWindowTexture) (w,
-											 &icon->texture, &sAttrib, mask);
+					&icon->texture, &fAttrib, mask);
+
+			glPopMatrix ();
+		}
 	}
 
 	w->screen->drawWindowGeometry = oldDrawWindowGeometry;
Index: beryl-core/include/beryl.h
===================================================================
--- beryl-core/include/beryl.h	(Revision 3571)
+++ beryl-core/include/beryl.h	(Arbeitskopie)
@@ -26,7 +26,7 @@
 #ifndef _BERYL_H
 #define _BERYL_H
 
-#define BERYL_VERSION 50
+#define BERYL_VERSION 51
 
 #define BERYL_ABI_INFO \
     BERYL_VERSION, \
@@ -91,13 +91,17 @@
 #define N_(x) x
 #endif
 
-typedef struct _CompPlugin	    CompPlugin;
-typedef struct _CompDisplay	    CompDisplay;
-typedef struct _CompScreen	    CompScreen;
-typedef struct _CompWindow	    CompWindow;
-typedef struct _CompTexture	    CompTexture;
-typedef struct _CompIcon	    CompIcon;
+typedef struct _CompPlugin			CompPlugin;
+typedef struct _CompDisplay			CompDisplay;
+typedef struct _CompScreen			CompScreen;
+typedef struct _CompWindow			CompWindow;
+typedef struct _CompTexture			CompTexture;
+typedef struct _CompIcon			CompIcon;
 typedef struct _CompWindowExtents   CompWindowExtents;
+typedef struct _CompProgram			CompProgram;
+typedef struct _CompFunction		CompFunction;
+typedef struct _CompFunctionData	CompFunctionData;
+typedef struct _FragmentAttrib		FragmentAttrib;
 
 /* virtual modifiers */
 
@@ -1206,10 +1210,10 @@
         Region                   region,
         unsigned int             mask);
 
-typedef Bool (*DrawWindowProc) (CompWindow              *window,
-                                const WindowPaintAttrib *attrib,
-                                Region                  region,
-                                unsigned int            mask);
+typedef Bool (*DrawWindowProc) (CompWindow           *window,
+                                const FragmentAttrib *attrib,
+                                Region               region,
+                                unsigned int         mask);
 
 typedef void (*AddWindowGeometryProc) (CompWindow *window,
         CompMatrix *matrix,
@@ -1217,9 +1221,9 @@
         Region    region,
         Region    clip);
 
-typedef void (*DrawWindowTextureProc) (CompWindow              *w,
+typedef void (*DrawWindowTextureProc) (CompWindow *w,
         CompTexture            *texture,
-        const WindowPaintAttrib *attrib,
+		const FragmentAttrib	*fragment,
         unsigned int           mask);
 
 typedef void (*DrawWindowGeometryProc) (CompWindow *window);
@@ -1290,14 +1294,14 @@
 void
 drawWindowTexture (CompWindow              *w,
         CompTexture                *texture,
-        const WindowPaintAttrib *attrib,
+		const FragmentAttrib *fragment,
         unsigned int               mask);
 
 Bool
-drawWindow (CompWindow              *w,
-            const WindowPaintAttrib *attrib,
-            Region                  region,
-            unsigned int            mask);
+drawWindow (CompWindow           *w,
+            const FragmentAttrib *attrib,
+            Region               region,
+            unsigned int         mask);
 
 Bool
 paintWindow (CompWindow              *w,
@@ -1310,6 +1314,9 @@
         Region        region,
         unsigned int mask);
 
+void
+pushWindowTransform (CompWindow       *w,
+                     const WindowPaintAttrib *attrib);
 
 /* texture.c */
 
@@ -1526,7 +1533,7 @@
         GLenum    format,
         GLsizei   len,
         const GLvoid *string);
-typedef void (*GLProgramLocalParameter4fProc) (GLenum  target,
+typedef void (*GLProgramParameter4fProc) (GLenum  target,
         GLuint  index,
         GLfloat x,
         GLfloat y,
@@ -1798,6 +1805,13 @@
     int            timeLeft;
     Bool           pendingCommands;
 
+	int lastFunctionId;
+
+	CompFunction *fragmentFunctions;
+	CompProgram *fragmentPrograms;
+
+	int saturateFunction[2][64];
+
     Bool cleared;
 
     Bool lighting;
@@ -1828,11 +1842,12 @@
     GLActiveTextureProc       activeTexture;
     GLClientActiveTextureProc clientActiveTexture;
 
-    GLGenProgramsProc             genPrograms;
-    GLDeleteProgramsProc          deletePrograms;
-    GLBindProgramProc             bindProgram;
-    GLProgramStringProc           programString;
-    GLProgramLocalParameter4fProc programLocalParameter4f;
+    GLGenProgramsProc        genPrograms;
+    GLDeleteProgramsProc     deletePrograms;
+    GLBindProgramProc        bindProgram;
+    GLProgramStringProc      programString;
+    GLProgramParameter4fProc programEnvParameter4f;
+    GLProgramParameter4fProc programLocalParameter4f;
 
     GLGenFramebuffersProc        genFramebuffers;
     GLDeleteFramebuffersProc     deleteFramebuffers;
@@ -2851,6 +2866,104 @@
 void
 closeSession (void);
 
+
+/* fragment.c */
+
+#define MAX_FRAGMENT_FUNCTIONS 16
+
+struct _FragmentAttrib {
+	GLushort opacity;
+	GLushort brightness;
+	GLushort saturation;
+	int nTexture;
+	int function[MAX_FRAGMENT_FUNCTIONS];
+	int nFunction;
+	int nParam;
+};
+
+CompFunctionData * 
+createFunctionData (void);
+
+void
+destroyFunctionData (CompFunctionData *data);
+
+Bool
+addTempHeaderOpToFunctionData (CompFunctionData *data,
+                               char             *name);
+
+Bool
+addParamHeaderOpToFunctionData (CompFunctionData *data,
+                                char             *name);
+
+Bool
+addAttribHeaderOpToFunctionData (CompFunctionData *data,
+                                 char             *name);
+
+#define COMP_FETCH_TARGET_2D   0
+#define COMP_FETCH_TARGET_RECT 1
+#define COMP_FETCH_TARGET_NUM  2
+
+Bool
+addFetchOpToFunctionData (CompFunctionData *data,
+                          char             *dst,
+                          char             *offset,
+                          int              target);
+
+Bool
+addColorOpToFunctionData (CompFunctionData *data,
+                          char             *dst,
+                          char             *src);
+
+Bool
+addDataOpToFunctionData (CompFunctionData *data,
+                         char             *str);
+
+Bool
+addBlendOpToFunctionData (CompFunctionData *data,
+                          char             *str);
+
+int
+createFragmentFunction (CompScreen       *s,
+                        char             *name,
+                        CompFunctionData *data);
+
+void
+destroyFragmentFunction (CompScreen *s,
+                         int        id);
+
+int
+getSaturateFragmentFunction (CompScreen  *s,
+                             CompTexture *texture,
+                             int         param);
+
+int
+allocFragmentTextureUnits (FragmentAttrib *attrib,
+						  int			 nTexture);
+
+int
+allocFragmentParameters (FragmentAttrib *attrib,
+						 int			nParam);
+
+void
+addFragmentFunction (FragmentAttrib *attrib,
+                     int            function);
+
+void
+initFragmentAttrib (FragmentAttrib			*attrib,
+					const WindowPaintAttrib *paint);
+Bool
+enableFragmentAttrib (CompScreen     *s,
+                      FragmentAttrib *attrib,
+                      Bool           *blending);
+
+void
+disableFragmentAttrib (CompScreen     *s,
+                       FragmentAttrib *attrib);
+
+
 /* activation.c */
-Bool shouldFocusWindow(CompWindow * w, Time t);
+
+Bool 
+shouldFocusWindow(CompWindow * w, Time t);
+
 #endif
Index: beryl-core/src/paint.c
===================================================================
--- beryl-core/src/paint.c	(Revision 3571)
+++ beryl-core/src/paint.c	(Arbeitskopie)
@@ -888,42 +888,105 @@
 	}
 }
 
-void
-drawWindowTexture(CompWindow * w,
-				  CompTexture * texture,
-				  const WindowPaintAttrib * attrib, unsigned int mask)
+static Bool
+enableFragmentProgramAndDrawGeometry (CompWindow              *w,
+                                      CompTexture             *texture,
+                                      const FragmentAttrib    *attrib,
+                                      int                     filter,
+                                      unsigned int            mask)
 {
-	int filter;
+	FragmentAttrib fa = *attrib;
+	CompScreen     *s = w->screen;
+	Bool           blending;
 
-	glPushMatrix();
+	if (s->canDoSaturated && attrib->saturation != COLOR)
+	{
+		int param, function;
 
-	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+		param    = allocFragmentParameters (&fa, 1);
+		function = getSaturateFragmentFunction (s, texture, param);
+
+		addFragmentFunction (&fa, function);
+
+		(*s->programEnvParameter4f) (GL_FRAGMENT_PROGRAM_ARB, param,
+                                     RED_SATURATION_WEIGHT,
+                                     GREEN_SATURATION_WEIGHT,
+                                     BLUE_SATURATION_WEIGHT,
+                                     attrib->saturation / 65535.0f);
+	}
+
+	if (!enableFragmentAttrib (s, &fa, &blending))
+		return FALSE;
+
+	enableTexture (s, texture, filter);
+
+	if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
 	{
-		glTranslatef(w->attrib.x, w->attrib.y, 0.0f);
-		glScalef(attrib->xScale, attrib->yScale, 1.0f);
-		glTranslatef(attrib->xTranslate / attrib->xScale -
-					 w->attrib.x,
-					 attrib->yTranslate / attrib->yScale - w->attrib.y, 0.0f);
+		if (blending)
+			glEnable (GL_BLEND);
 
-		filter = w->screen->filter[WINDOW_TRANS_FILTER];
+		if (attrib->opacity != OPAQUE || attrib->brightness != BRIGHT)
+		{
+			GLushort color;
+
+			color = (attrib->opacity * attrib->brightness) >> 16;
+
+			screenTexEnvMode (s, GL_MODULATE);
+			glColor4us (color, color, color, attrib->opacity);
+
+			(*s->drawWindowGeometry) (w);
+
+			glColor4usv (defaultColor);
+			screenTexEnvMode (s, GL_REPLACE);
+		}
+		else
+		{
+			(*s->drawWindowGeometry) (w);
+		}
+			
+		if (blending)
+			glDisable (GL_BLEND);
 	}
-	else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
+	else if (attrib->brightness != BRIGHT)
 	{
-		filter = w->screen->filter[SCREEN_TRANS_FILTER];
+		screenTexEnvMode (s, GL_MODULATE);
+		glColor4us (attrib->brightness, attrib->brightness,
+					attrib->brightness, BRIGHT);
+
+		(*w->screen->drawWindowGeometry) (w);
+
+		glColor4usv (defaultColor);
+		screenTexEnvMode (s, GL_REPLACE);
 	}
 	else
 	{
-		filter = w->screen->filter[NOTHING_TRANS_FILTER];
+		(*w->screen->drawWindowGeometry) (w);
 	}
 
-	if (w->screen->canDoSaturated && attrib->saturation != COLOR)
+	disableTexture (w->screen, texture);
+
+	disableFragmentAttrib (s, &fa);
+
+	return TRUE;
+}
+
+static void
+enableFragmentOperationsAndDrawGeometry (CompWindow              *w,
+                                         CompTexture             *texture,
+                                         const FragmentAttrib    *attrib,
+                                         int                     filter,
+                                         unsigned int            mask)
+{
+	CompScreen *s = w->screen;
+
+	if (s->canDoSaturated && attrib->saturation != COLOR)
 	{
 		GLfloat constant[4];
 
 		if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
 			glEnable(GL_BLEND);
 
-		enableTexture(w->screen, texture, filter);
+		enableTexture(s, texture, filter);
 
 		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
 
@@ -941,9 +1004,9 @@
 
 		glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
 
-		w->screen->activeTexture(GL_TEXTURE1_ARB);
+		s->activeTexture(GL_TEXTURE1_ARB);
 
-		enableTexture(w->screen, texture, filter);
+		enableTexture(s, texture, filter);
 
 		glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
 
@@ -953,7 +1016,7 @@
 		glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR);
 		glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR);
 
-		if (w->screen->canDoSlightlySaturated && attrib->saturation > 0)
+		if (s->canDoSlightlySaturated && attrib->saturation > 0)
 		{
 			glTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
 			glTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS);
@@ -966,9 +1029,9 @@
 
 			glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
 
-			w->screen->activeTexture(GL_TEXTURE2_ARB);
+			s->activeTexture(GL_TEXTURE2_ARB);
 
-			enableTexture(w->screen, texture, filter);
+			enableTexture(s, texture, filter);
 
 			glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
 
@@ -990,9 +1053,9 @@
 
 			if (attrib->opacity < OPAQUE || attrib->brightness != BRIGHT)
 			{
-				w->screen->activeTexture(GL_TEXTURE3_ARB);
+				s->activeTexture(GL_TEXTURE3_ARB);
 
-				enableTexture(w->screen, texture, filter);
+				enableTexture(s, texture, filter);
 
 				constant[3] = attrib->opacity / 65535.0f;
 				constant[0] = constant[1] = constant[2] =
@@ -1014,24 +1077,24 @@
 				glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA);
 				glTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA);
 
-				(*w->screen->drawWindowGeometry) (w);
+				(*s->drawWindowGeometry) (w);
 
-				disableTexture(w->screen, texture);
+				disableTexture(s, texture);
 
 				glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
-				w->screen->activeTexture(GL_TEXTURE2_ARB);
+				s->activeTexture(GL_TEXTURE2_ARB);
 			}
 			else
 			{
-				(*w->screen->drawWindowGeometry) (w);
+				(*s->drawWindowGeometry) (w);
 			}
 
-			disableTexture(w->screen, texture);
+			disableTexture(s, texture);
 
 			glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
-			w->screen->activeTexture(GL_TEXTURE1_ARB);
+			s->activeTexture(GL_TEXTURE1_ARB);
 		}
 		else
 		{
@@ -1051,26 +1114,26 @@
 
 			glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, constant);
 
-			(*w->screen->drawWindowGeometry) (w);
+			(*s->drawWindowGeometry) (w);
 		}
 
-		disableTexture(w->screen, texture);
+		disableTexture(s, texture);
 
 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
 
-		w->screen->activeTexture(GL_TEXTURE0_ARB);
+		s->activeTexture(GL_TEXTURE0_ARB);
 
-		disableTexture(w->screen, texture);
+		disableTexture(s, texture);
 
 		glColor4usv(defaultColor);
-		screenTexEnvMode(w->screen, GL_REPLACE);
+		screenTexEnvMode(s, GL_REPLACE);
 
 		if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
 			glDisable(GL_BLEND);
 	}
 	else
 	{
-		enableTexture(w->screen, texture, filter);
+		enableTexture(s, texture, filter);
 
 		if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
 		{
@@ -1081,31 +1144,31 @@
 
 				color = (attrib->opacity * attrib->brightness) >> 16;
 
-				screenTexEnvMode(w->screen, GL_MODULATE);
+				screenTexEnvMode(s, GL_MODULATE);
 				glColor4us(color, color, color, attrib->opacity);
 
-				(*w->screen->drawWindowGeometry) (w);
+				(*s->drawWindowGeometry) (w);
 
 				glColor4usv(defaultColor);
-				screenTexEnvMode(w->screen, GL_REPLACE);
+				screenTexEnvMode(s, GL_REPLACE);
 			}
 			else
 			{
-				(*w->screen->drawWindowGeometry) (w);
+				(*s->drawWindowGeometry) (w);
 			}
 
 			glDisable(GL_BLEND);
 		}
 		else if (attrib->brightness != BRIGHT)
 		{
-			screenTexEnvMode(w->screen, GL_MODULATE);
+			screenTexEnvMode(s, GL_MODULATE);
 			glColor4us(attrib->brightness, attrib->brightness,
 					   attrib->brightness, BRIGHT);
 
-			(*w->screen->drawWindowGeometry) (w);
+			(*s->drawWindowGeometry) (w);
 
 			glColor4usv(defaultColor);
-			screenTexEnvMode(w->screen, GL_REPLACE);
+			screenTexEnvMode(s, GL_REPLACE);
 		}
 		else
 		{
@@ -1114,14 +1177,43 @@
 
 		disableTexture(w->screen, texture);
 	}
+}
 
-	glPopMatrix();
+void
+drawWindowTexture (CompWindow              *w,
+                   CompTexture             *texture,
+                   const FragmentAttrib    *attrib,
+                   unsigned int            mask)
+{
+	int filter;
+
+	glPushMatrix ();
+
+	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+	{
+		filter = w->screen->filter[WINDOW_TRANS_FILTER];
+	}
+	else if (mask & PAINT_WINDOW_ON_TRANSFORMED_SCREEN_MASK)
+	{
+		filter = w->screen->filter[SCREEN_TRANS_FILTER];
+	}
+	else
+	{
+		filter = w->screen->filter[NOTHING_TRANS_FILTER];
+	}
+
+	if (!attrib->nFunction || !enableFragmentProgramAndDrawGeometry (w,
+				texture, attrib, filter, mask))
+	{
+		enableFragmentOperationsAndDrawGeometry (w,texture,
+				attrib, filter, mask);
+	}
 }
 
 
 Bool
-drawWindow(CompWindow * w,
-		   const WindowPaintAttrib * attrib, Region region, unsigned int mask)
+drawWindow(CompWindow * w, const FragmentAttrib *fragment,
+		   Region region, unsigned int mask)
 {
 	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
 		region = &infiniteRegion;
@@ -1137,12 +1229,12 @@
 		if (w->alpha)
 			return FALSE;
 
-		if (attrib->opacity != OPAQUE)
+		if (fragment->opacity != OPAQUE)
 			return FALSE;
 	}
 	else if (mask & PAINT_WINDOW_TRANSLUCENT_MASK)
 	{
-		if (!w->alpha && attrib->opacity == OPAQUE)
+		if (!w->alpha && fragment->opacity == OPAQUE)
 			return FALSE;
 	}
 	else
@@ -1150,7 +1242,7 @@
 		if (w->attrib.map_state != IsViewable && !w->thumbPixmap)
 			return TRUE;
 
-		if (w->alpha || attrib->opacity != OPAQUE)
+		if (w->alpha || fragment->opacity != OPAQUE)
 			mask |= PAINT_WINDOW_TRANSLUCENT_MASK;
 		else
 			mask |= PAINT_WINDOW_SOLID_MASK;
@@ -1165,7 +1257,8 @@
 		(*w->screen->addWindowGeometry) (w, &w->thumbMatrix, 1, w->region, region);
 		if (w->vCount)
 		{
-			(*w->screen->drawWindowTexture) (w, w->thumbTexture, attrib, mask);
+			(*w->screen->drawWindowTexture) (w, w->thumbTexture, 
+					fragment, mask);
 		}
 		return TRUE;
 	}
@@ -1180,7 +1273,7 @@
 	(*w->screen->addWindowGeometry) (w, &w->matrix, 1, w->region, region);
 	if (w->vCount)
 	{
-		(*w->screen->drawWindowTexture) (w, w->texture, attrib, mask);
+		(*w->screen->drawWindowTexture) (w, w->texture, fragment, mask);
 	}
 
 	return TRUE;
@@ -1190,6 +1283,9 @@
 paintWindow(CompWindow * w, const WindowPaintAttrib * attrib,
 			Region region, unsigned int mask)
 {
+	FragmentAttrib fragment;
+	Bool status;
+
 	w->lastPaint = *attrib;
 
 	if (w->state & CompWindowStateOffscreenMask)
@@ -1203,7 +1299,17 @@
 		return TRUE;
 	}
 
-	return (*w->screen->drawWindow) (w, attrib, region, mask);
+	initFragmentAttrib (&fragment, attrib);
+
+	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+		pushWindowTransform (w, attrib);
+
+	status = (*w->screen->drawWindow) (w, &fragment, region, mask);
+
+	if (mask & PAINT_WINDOW_TRANSFORMED_MASK)
+		glPopMatrix ();
+
+	return status;
 }
 
 void paintBackground(CompScreen * s, Region region, unsigned int mask)
@@ -1287,3 +1393,16 @@
 
 	free(data);
 }
+
+void
+pushWindowTransform (CompWindow       *w,
+                     const WindowPaintAttrib *attrib)
+{
+	glPushMatrix ();
+
+	glTranslatef (w->attrib.x, w->attrib.y, 0.0f);
+	glScalef (attrib->xScale, attrib->yScale, 0.0f);
+	glTranslatef (attrib->xTranslate / attrib->xScale - w->attrib.x,
+                  attrib->yTranslate / attrib->yScale - w->attrib.y,
+                  0.0f);
+}
Index: beryl-core/src/screen.c
===================================================================
--- beryl-core/src/screen.c	(Revision 3571)
+++ beryl-core/src/screen.c	(Arbeitskopie)
@@ -1298,6 +1298,13 @@
 
 	s->pendingCommands = TRUE;
 
+	s->lastFunctionId = 0;
+
+	s->fragmentFunctions = NULL;
+	s->fragmentPrograms = NULL;
+
+	memset (s->saturateFunction, 0, sizeof (s->saturateFunction));
+
 	s->showingDesktopMask = 0;
 
 	s->overlayWindowCount = 0;
@@ -1586,13 +1593,14 @@
 				getProcAddress(s, "glBindProgramARB");
 		s->programString = (GLProgramStringProc)
 				getProcAddress(s, "glProgramStringARB");
-		s->programLocalParameter4f =
-				(GLProgramLocalParameter4fProc)
+		s->programEnvParameter4f = (GLProgramParameter4fProc)
+				getProcAddress(s, "glProgramEnvParameter4fARB");
+		s->programLocalParameter4f = (GLProgramParameter4fProc)
 				getProcAddress(s, "glProgramLocalParameter4fARB");
 
-		if (s->genPrograms &&
-			s->deletePrograms &&
-			s->bindProgram && s->programString && s->programLocalParameter4f)
+		if (s->genPrograms && s->deletePrograms &&
+			s->bindProgram && s->programString && 
+			s->programEnvParameter4f && s->programLocalParameter4f)
 			s->fragmentProgram = 1;
 	}
 
Index: beryl-core/src/Makefile.am
===================================================================
--- beryl-core/src/Makefile.am	(Revision 3571)
+++ beryl-core/src/Makefile.am	(Arbeitskopie)
@@ -29,6 +29,7 @@
 	option.c            \
 	plugin.c            \
 	session.c           \
+	fragment.c	    \
 	screen_options.c    \
 	display_options.c   \
 	type_mask.c         \