Index: uspace/lib/softrend/filter.c
===================================================================
--- uspace/lib/softrend/filter.c	(revision 071fefec5f0bb65ab129bc513b289e3e9d6700df)
+++ uspace/lib/softrend/filter.c	(revision 8d3512f119e2a44f134b45bad386692c49984b5b)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2012 Petr Koupy
+ * Copyright (c) 2014 Martin Sucha
  * All rights reserved.
  *
@@ -35,22 +36,85 @@
 
 #include "filter.h"
+#include <io/pixel.h>
+
+static long round(double val)
+{
+	return val > 0 ? (long) (val + 0.5) : (long) (val - 0.5);
+}
+
+static long floor(double val)
+{
+	long lval = (long) val;
+	if (val < 0 && lval != val)
+		return lval - 1;
+	return lval;
+}
+
+static long ceil(double val)
+{
+	long lval = (long) val;
+	if (val > 0 && lval != val)
+		return lval + 1;
+	return lval;
+}
+
+static pixel_t get_pixel(pixelmap_t *pixmap, sysarg_t x, sysarg_t y, bool tile)
+{
+	if (tile) {
+		x %= pixmap->width;
+		y %= pixmap->height;
+	}
+
+	return pixelmap_get_pixel(pixmap, (sysarg_t) x, (sysarg_t) y);
+}
+
+static inline pixel_t blend_pixels(size_t count, float *weights,
+    pixel_t *pixels)
+{
+	float alpha = 0, red = 0, green = 0, blue = 0;
+	for (size_t index = 0; index < count; index++) {
+		alpha += weights[index] * ALPHA(pixels[index]);
+		red   += weights[index] *   RED(pixels[index]);
+		green += weights[index] * GREEN(pixels[index]);
+		blue  += weights[index] *  BLUE(pixels[index]);
+	}
+	
+	return PIXEL((uint8_t) alpha, (uint8_t) red, (uint8_t) green,
+	    (uint8_t) blue);
+}
 
 pixel_t filter_nearest(pixelmap_t *pixmap, double x, double y, bool tile)
 {
-	long _x = x > 0 ? (long) (x + 0.5) : (long) (x - 0.5);
-	long _y = y > 0 ? (long) (y + 0.5) : (long) (y - 0.5);
-
-	if (tile) {
-		_x %= pixmap->width;
-		_y %= pixmap->height;
-	}
-
-	return pixelmap_get_pixel(pixmap, (sysarg_t) _x, (sysarg_t) _y);
+	return get_pixel(pixmap, round(x), round(y), tile);
 }
 
 pixel_t filter_bilinear(pixelmap_t *pixmap, double x, double y, bool tile)
 {
-	// TODO
-	return 0;
+	long x1 = floor(x);
+	long x2 = ceil(x);
+	long y1 = floor(y);
+	long y2 = ceil(y);
+	
+	if (y1 == y2 && x1 == x2) {
+		return get_pixel(pixmap, (sysarg_t) x1, (sysarg_t) y1,
+		    tile);
+	}
+	
+	double x_delta = x - x1;
+	double y_delta = y - y1;
+	
+	pixel_t pixels[4];
+	pixels[0] = get_pixel(pixmap, x1, y1, tile);
+	pixels[1] = get_pixel(pixmap, x2, y1, tile);
+	pixels[2] = get_pixel(pixmap, x1, y2, tile);
+	pixels[3] = get_pixel(pixmap, x2, y2, tile);
+	
+	float weights[4];
+	weights[0] = (1 - x_delta) * (1 - y_delta);
+	weights[1] = (    x_delta) * (1 - y_delta);
+	weights[2] = (1 - x_delta) * (    y_delta);
+	weights[3] = (    x_delta) * (    y_delta);
+	
+	return blend_pixels(4, weights, pixels);
 }
 
