Index: uspace/srv/hid/fb/fb.c
===================================================================
--- uspace/srv/hid/fb/fb.c	(revision 67b05ff8a6156c062aa30c1388fc37fc148a7ea2)
+++ uspace/srv/hid/fb/fb.c	(revision 1d2a1a9d0629e94f79fea839c32f4125989ecafc)
@@ -59,8 +59,8 @@
 #include <byteorder.h>
 #include <io/screenbuffer.h>
+#include <imgmap.h>
 #include "font-8x16.h"
 #include "fb.h"
 #include "main.h"
-#include "ppm.h"
 #include "pointer.xbm"
 #include "pointer_mask.xbm"
@@ -76,5 +76,5 @@
 #define MAX_ANIM_LEN    8
 #define MAX_ANIMATIONS  4
-#define MAX_PIXMAPS     256  /**< Maximum number of saved pixmaps */
+#define MAX_IMGMAPS     256  /**< Maximum number of saved image maps */
 #define MAX_VIEWPORTS   128  /**< Viewport is a rectangular area on the screen */
 
@@ -160,5 +160,5 @@
 	unsigned int pos;
 	unsigned int animlen;
-	unsigned int pixmaps[MAX_ANIM_LEN];
+	unsigned int imgmaps[MAX_ANIM_LEN];
 } animation_t;
 
@@ -166,11 +166,5 @@
 static bool anims_enabled;
 
-typedef struct {
-	unsigned int width;
-	unsigned int height;
-	uint8_t *data;
-} pixmap_t;
-
-static pixmap_t pixmaps[MAX_PIXMAPS];
+static imgmap_t *imgmaps[MAX_IMGMAPS];
 static viewport_t viewports[128];
 
@@ -212,5 +206,4 @@
 static void draw_vp_glyph(viewport_t *vport, bool cursor, unsigned int col,
     unsigned int row);
-
 
 #define RED(x, bits)                 (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1))
@@ -875,5 +868,4 @@
 }
 
-
 /** Show cursor if cursor showing is enabled
  *
@@ -888,5 +880,4 @@
 }
 
-
 /** Invert cursor, if it is enabled
  *
@@ -899,5 +890,4 @@
 		cursor_show(vport);
 }
-
 
 /** Draw character at given position relative to viewport
@@ -981,18 +971,7 @@
 }
 
-
-static void putpixel_pixmap(void *data, unsigned int x, unsigned int y, uint32_t color)
-{
-	int pm = *((int *) data);
-	pixmap_t *pmap = &pixmaps[pm];
-	unsigned int pos = (y * pmap->width + x) * screen.pixelbytes;
-	
-	screen.rgb_conv(&pmap->data[pos], color);
-}
-
-
-static void putpixel(void *data, unsigned int x, unsigned int y, uint32_t color)
-{
-	viewport_t *vport = (viewport_t *) data;
+static void putpixel(viewport_t *vport, unsigned int x, unsigned int y,
+    uint32_t color)
+{
 	unsigned int dx = vport->x + x;
 	unsigned int dy = vport->y + y;
@@ -1001,14 +980,50 @@
 }
 
-
-/** Return first free pixmap
- *
- */
-static int find_free_pixmap(void)
+/** Draw image map
+ *
+ * @param[in] img       Image map.
+ * @param[in] sx        Coordinate of upper left corner.
+ * @param[in] sy        Coordinate of upper left corner.
+ * @param[in] maxwidth  Maximum allowed width for picture.
+ * @param[in] maxheight Maximum allowed height for picture.
+ * @param[in] vport     Viewport.
+ *
+ * @return EOK on success.
+ *
+ */
+static int imgmap_draw(imgmap_t *img, unsigned int sx, unsigned int sy,
+    unsigned int maxwidth, unsigned int maxheight, void *vport)
+{
+	if (img->visual != VISUAL_BGR_8_8_8)
+		return EINVAL;
+	
+	uint8_t *data = (uint8_t *) img->data;
+	
+	for (sysarg_t y = 0; y < img->height; y++) {
+		for (sysarg_t x = 0; x < img->width; x++) {
+			if ((x > maxwidth) || (y > maxheight)) {
+				data += 3;
+				continue;
+			}
+			
+			uint32_t color = (data[2] << 16) + (data[1] << 8) + data[0];
+			
+			putpixel(vport, sx + x, sy + y, color);
+			data += 3;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Return first free image map
+ *
+ */
+static int find_free_imgmap(void)
 {
 	unsigned int i;
 	
-	for (i = 0; i < MAX_PIXMAPS; i++)
-		if (!pixmaps[i].data)
+	for (i = 0; i < MAX_IMGMAPS; i++)
+		if (!imgmaps[i])
 			return i;
 	
@@ -1016,38 +1031,28 @@
 }
 
-
-/** Create a new pixmap and return appropriate ID
- *
- */
-static int shm2pixmap(unsigned char *shm, size_t size)
-{
-	int pm;
-	pixmap_t *pmap;
-	
-	pm = find_free_pixmap();
-	if (pm == -1)
+/** Create a new image map and return appropriate ID
+ *
+ */
+static int shm2imgmap(imgmap_t *shm, size_t size)
+{
+	int im = find_free_imgmap();
+	if (im == -1)
 		return ELIMIT;
 	
-	pmap = &pixmaps[pm];
-	
-	if (ppm_get_data(shm, size, &pmap->width, &pmap->height))
-		return EINVAL;
-	
-	pmap->data = malloc(pmap->width * pmap->height * screen.pixelbytes);
-	if (!pmap->data)
+	imgmap_t *imap = malloc(size);
+	if (!imap)
 		return ENOMEM;
 	
-	ppm_draw(shm, size, 0, 0, pmap->width, pmap->height, putpixel_pixmap, (void *) &pm);
-	
-	return pm;
-}
-
+	memcpy(imap, shm, size);
+	imgmaps[im] = imap;
+	return im;
+}
 
 /** Handle shared memory communication calls
  *
- * Protocol for drawing pixmaps:
+ * Protocol for drawing image maps:
  * - FB_PREPARE_SHM(client shm identification)
  * - IPC_M_AS_AREA_SEND
- * - FB_DRAW_PPM(startx, starty)
+ * - FB_DRAW_IMGMAP(startx, starty)
  * - FB_DROP_SHM
  *
@@ -1071,5 +1076,5 @@
 	static size_t intersize = 0;
 	
-	static unsigned char *shm = NULL;
+	static imgmap_t *shm = NULL;
 	static sysarg_t shm_id = 0;
 	static size_t shm_size;
@@ -1093,9 +1098,6 @@
 				return false;
 			}
+			
 			shm = dest;
-			
-			if ((shm[0] != 'P') || (shm[0] != 'I'))
-				return false;
-			
 			return true;
 		} else {
@@ -1107,8 +1109,7 @@
 		if (shm_id)
 			retval = EBUSY;
-		else 
+		else
 			shm_id = IPC_GET_ARG1(*call);
 		break;
-		
 	case FB_DROP_SHM:
 		if (shm) {
@@ -1118,17 +1119,17 @@
 		shm_id = 0;
 		break;
-		
-	case FB_SHM2PIXMAP:
+	case FB_SHM2IMGMAP:
 		if (!shm) {
 			retval = EINVAL;
 			break;
 		}
-		retval = shm2pixmap(shm, shm_size);
-		break;
-	case FB_DRAW_PPM:
+		retval = shm2imgmap(shm, shm_size);
+		break;
+	case FB_DRAW_IMGMAP:
 		if (!shm) {
 			retval = EINVAL;
 			break;
 		}
+		
 		x = IPC_GET_ARG1(*call);
 		y = IPC_GET_ARG2(*call);
@@ -1139,6 +1140,6 @@
 		}
 		
-		ppm_draw(shm, shm_size, IPC_GET_ARG1(*call),
-		    IPC_GET_ARG2(*call), vport->width - x, vport->height - y, putpixel, (void *) vport);
+		imgmap_draw(shm, IPC_GET_ARG1(*call), IPC_GET_ARG2(*call),
+		    vport->width - x, vport->height - y, vport);
 		break;
 	case FB_DRAW_TEXT_DATA:
@@ -1167,9 +1168,9 @@
 	if (handled)
 		async_answer_0(callid, retval);
+	
 	return handled;
 }
 
-
-static void copy_vp_to_pixmap(viewport_t *vport, pixmap_t *pmap)
+static void copy_vp_to_imgmap(viewport_t *vport, imgmap_t *imap)
 {
 	unsigned int width = vport->width;
@@ -1178,9 +1179,10 @@
 	if (width + vport->x > screen.xres)
 		width = screen.xres - vport->x;
+	
 	if (height + vport->y > screen.yres)
 		height = screen.yres - vport->y;
 	
-	unsigned int realwidth = pmap->width <= width ? pmap->width : width;
-	unsigned int realheight = pmap->height <= height ? pmap->height : height;
+	unsigned int realwidth = imap->width <= width ? imap->width : width;
+	unsigned int realheight = imap->height <= height ? imap->height : height;
 	
 	unsigned int srcrowsize = vport->width * screen.pixelbytes;
@@ -1190,44 +1192,44 @@
 	for (y = 0; y < realheight; y++) {
 		unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
-		memcpy(pmap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
-	}
-}
-
-
-/** Save viewport to pixmap
- *
- */
-static int save_vp_to_pixmap(viewport_t *vport)
-{
-	int pm;
-	pixmap_t *pmap;
-	
-	pm = find_free_pixmap();
-	if (pm == -1)
+		memcpy(imap->data + srcrowsize * y, screen.fb_addr + tmp, realrowsize);
+	}
+}
+
+/** Save viewport to image map
+ *
+ */
+static int save_vp_to_imgmap(viewport_t *vport)
+{
+	int im = find_free_imgmap();
+	if (im == -1)
 		return ELIMIT;
 	
-	pmap = &pixmaps[pm];
-	pmap->data = malloc(screen.pixelbytes * vport->width * vport->height);
-	if (!pmap->data)
+	size_t size = screen.pixelbytes * vport->width * vport->height;
+	imgmap_t *imap = malloc(sizeof(imgmap_t) + size);
+	if (!imap)
 		return ENOMEM;
 	
-	pmap->width = vport->width;
-	pmap->height = vport->height;
-	
-	copy_vp_to_pixmap(vport, pmap);
-	
-	return pm;
-}
-
-
-/** Draw pixmap on screen
- *
- * @param vp Viewport to draw on
- * @param pm Pixmap identifier
- *
- */
-static int draw_pixmap(int vp, int pm)
-{
-	pixmap_t *pmap = &pixmaps[pm];
+	imap->size = sizeof(imgmap_t) + size;
+	imap->width = vport->width;
+	imap->height = vport->height;
+	imap->visual = (visual_t) -1;
+	
+	copy_vp_to_imgmap(vport, imap);
+	imgmaps[im] = imap;
+	return im;
+}
+
+/** Draw image map to screen
+ *
+ * @param vp Viewport to draw to
+ * @param im Image map identifier
+ *
+ */
+static int draw_imgmap(int vp, int im)
+{
+	imgmap_t *imap = imgmaps[im];
+	if (!imap)
+		return EINVAL;
+	
 	viewport_t *vport = &viewports[vp];
 	
@@ -1237,25 +1239,25 @@
 	if (width + vport->x > screen.xres)
 		width = screen.xres - vport->x;
+	
 	if (height + vport->y > screen.yres)
 		height = screen.yres - vport->y;
 	
-	if (!pmap->data)
-		return EINVAL;
-	
-	unsigned int realwidth = pmap->width <= width ? pmap->width : width;
-	unsigned int realheight = pmap->height <= height ? pmap->height : height;
-	
-	unsigned int srcrowsize = vport->width * screen.pixelbytes;
-	unsigned int realrowsize = realwidth * screen.pixelbytes;
-	
-	unsigned int y;
-	for (y = 0; y < realheight; y++) {
-		unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
-		memcpy(screen.fb_addr + tmp, pmap->data + y * srcrowsize, realrowsize);
-	}
+	unsigned int realwidth = imap->width <= width ? imap->width : width;
+	unsigned int realheight = imap->height <= height ? imap->height : height;
+	
+	if (imap->visual == (visual_t) -1) {
+		unsigned int srcrowsize = vport->width * screen.pixelbytes;
+		unsigned int realrowsize = realwidth * screen.pixelbytes;
+		
+		unsigned int y;
+		for (y = 0; y < realheight; y++) {
+			unsigned int tmp = (vport->y + y) * screen.scanline + vport->x * screen.pixelbytes;
+			memcpy(screen.fb_addr + tmp, imap->data + y * srcrowsize, realrowsize);
+		}
+	} else
+		imgmap_draw(imap, 0, 0, realwidth, realheight, vport);
 	
 	return EOK;
 }
-
 
 /** Tick animation one step forward
@@ -1277,5 +1279,5 @@
 			continue;
 		
-		draw_pixmap(animations[i].vp, animations[i].pixmaps[animations[i].pos]);
+		draw_imgmap(animations[i].vp, animations[i].imgmaps[animations[i].pos]);
 		animations[i].pos = (animations[i].pos + 1) % animations[i].animlen;
 	}
@@ -1287,5 +1289,5 @@
 static bool pointer_shown, pointer_enabled;
 static int pointer_vport = -1;
-static int pointer_pixmap = -1;
+static int pointer_imgmap = -1;
 
 
@@ -1310,8 +1312,8 @@
 	}
 	
-	if (pointer_pixmap == -1)
-		pointer_pixmap = save_vp_to_pixmap(&viewports[pointer_vport]);
+	if (pointer_imgmap == -1)
+		pointer_imgmap = save_vp_to_imgmap(&viewports[pointer_vport]);
 	else
-		copy_vp_to_pixmap(&viewports[pointer_vport], &pixmaps[pointer_pixmap]);
+		copy_vp_to_imgmap(&viewports[pointer_vport], imgmaps[pointer_imgmap]);
 	
 	/* Draw mouse pointer. */
@@ -1338,5 +1340,5 @@
 	/* Restore image under the pointer. */
 	if (pointer_shown) {
-		draw_pixmap(pointer_vport, pointer_pixmap);
+		draw_imgmap(pointer_vport, pointer_imgmap);
 		pointer_shown = 0;
 	}
@@ -1393,5 +1395,5 @@
 		animations[i].initialized = 0;
 		break;
-	case FB_ANIM_ADDPIXMAP:
+	case FB_ANIM_ADDIMGMAP:
 		i = IPC_GET_ARG1(*call);
 		if (i >= MAX_ANIMATIONS || i < 0 ||
@@ -1405,10 +1407,10 @@
 		}
 		newval = IPC_GET_ARG2(*call);
-		if (newval < 0 || newval > MAX_PIXMAPS ||
-			!pixmaps[newval].data) {
+		if (newval < 0 || newval > MAX_IMGMAPS ||
+			!imgmaps[newval]) {
 			retval = EINVAL;
 			break;
 		}
-		animations[i].pixmaps[animations[i].animlen++] = newval;
+		animations[i].imgmaps[animations[i].animlen++] = newval;
 		break;
 	case FB_ANIM_CHGVP:
@@ -1449,9 +1451,8 @@
 }
 
-
-/** Handler for messages concerning pixmap handling
- *
- */
-static int pixmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
+/** Handler for messages concerning image map handling
+ *
+ */
+static int imgmap_handle(ipc_callid_t callid, ipc_call_t *call, int vp)
 {
 	bool handled = true;
@@ -1460,36 +1461,43 @@
 	
 	switch (IPC_GET_IMETHOD(*call)) {
-	case FB_VP_DRAW_PIXMAP:
+	case FB_VP_DRAW_IMGMAP:
 		nvp = IPC_GET_ARG1(*call);
 		if (nvp == -1)
 			nvp = vp;
+		
 		if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
-			!viewports[nvp].initialized) {
+		    !viewports[nvp].initialized) {
 			retval = EINVAL;
 			break;
 		}
+		
 		i = IPC_GET_ARG2(*call);
-		retval = draw_pixmap(nvp, i);
-		break;
-	case FB_VP2PIXMAP:
+		retval = draw_imgmap(nvp, i);
+		break;
+	case FB_VP2IMGMAP:
 		nvp = IPC_GET_ARG1(*call);
 		if (nvp == -1)
 			nvp = vp;
+		
 		if (nvp < 0 || nvp >= MAX_VIEWPORTS ||
-			!viewports[nvp].initialized)
+		    !viewports[nvp].initialized) {
 			retval = EINVAL;
-		else
-			retval = save_vp_to_pixmap(&viewports[nvp]);
-		break;
-	case FB_DROP_PIXMAP:
+			break;
+		}
+		
+		retval = save_vp_to_imgmap(&viewports[nvp]);
+		break;
+	case FB_DROP_IMGMAP:
 		i = IPC_GET_ARG1(*call);
-		if (i >= MAX_PIXMAPS) {
+		if (i >= MAX_IMGMAPS) {
 			retval = EINVAL;
 			break;
 		}
-		if (pixmaps[i].data) {
-			free(pixmaps[i].data);
-			pixmaps[i].data = NULL;
-		}
+		
+		if (imgmaps[i]) {
+			free(imgmaps[i]);
+			imgmaps[i] = NULL;
+		}
+		
 		break;
 	default:
@@ -1616,5 +1624,5 @@
 			continue;
 		
-		if (pixmap_handle(callid, &call, vp))
+		if (imgmap_handle(callid, &call, vp))
 			continue;
 		
