--- libmatchbox/libmb/mbpixbuf.c.orig	2007-05-04 14:41:55.000000000 +0100
+++ libmatchbox/libmb/mbpixbuf.c	2007-05-04 14:41:55.000000000 +0100
@@ -710,46 +710,19 @@
   return colnum;
 }
 
-
-static unsigned long
-mb_pixbuf_get_pixel(MBPixbuf *pb, int r, int g, int b, int a)
+/*
+ * Split the mb_pixbuf_get_pixel() function into several specialized
+ * functions which we will inline; this allows us to optimize
+ * mb_pixbuf_img_render_to_drawable_with_gc () by taking some of the
+ * decision taking outside of the double loop
+ */
+
+/*
+ * Get pixel value for rgb values and pixel depth <= 8
+ */
+static inline unsigned long
+mb_pixbuf_get_pixel_le8_rgb (MBPixbuf *pb, int r, int g, int b)
 {
-  if (pb->depth > 8)
-    {
-      switch (pb->depth)
-	{
-	case 15:
-	  return ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
-	case 16:
-	  return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
-	case 24:
-	case 32:
-	  switch (pb->byte_order)
-	    {
-	    case BYTE_ORD_24_RGB:
-	      return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
-	    case BYTE_ORD_24_RBG:
-	      return ((r & 0xff) << 16) | ((b & 0xff) << 8) | (g & 0xff);
-	    case BYTE_ORD_24_BRG:
-	      return ((b & 0xff) << 16) | ((r & 0xff) << 8) | (g & 0xff);
-	    case BYTE_ORD_24_BGR:
-	      return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
-	    case BYTE_ORD_24_GRB:
-	      return ((g & 0xff) << 16) | ((r & 0xff) << 8) | (b & 0xff);
-	    case BYTE_ORD_24_GBR:
-	      return ((g & 0xff) << 16) | ((b & 0xff) << 8) | (r & 0xff);
-	    case BYTE_ORD_32_ARGB:
-	      return  (a << 24) | (r << 16) | (g << 8) | b;
-	    default:
-	      return 0;
-	    }
-	default:
-	  return 0;
-	}
-      return 0;
-    }
-
-  /* pb->depth <= 8 */
   switch(pb->vis->class)
     {
     case PseudoColor:
@@ -794,6 +767,111 @@
   return 0;
 }
 
+/*
+ * Get pixel value from a pointer to 16bbp value for pixel depth <= 8
+ * and advance the pointer
+ */
+static inline unsigned long
+mb_pixbuf_get_pixel_le8_16bpp_advance (MBPixbuf *pb, unsigned char ** p)
+{
+  unsigned short s = SHORT_FROM_2BYTES(*p);
+  int r, b, g;
+
+  r = (s & 0xf800) >> 8;
+  g = (s & 0x07e0) >> 3;
+  b = (s & 0x001f) << 3;
+
+  *p += 2;
+  
+  return mb_pixbuf_get_pixel_le8_rgb (pb, r, g, b);
+}
+
+/*
+ * Get pixel value for rgba values and pixel depth > 8
+ *
+ */
+static inline unsigned long
+mb_pixbuf_get_pixel_gt8_rgba (MBPixbuf *pb, int r, int g, int b, int a)
+{
+  switch (pb->depth)
+    {
+    case 15:
+      switch (pb->byte_order)
+	{
+	case BYTE_ORD_24_RGB:
+	  return ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3);
+	case BYTE_ORD_24_BGR:
+	  return ((b & 0xf8) << 7) | ((g & 0xf8) << 2) | ((r & 0xf8) >> 3);
+	}
+    case 16:
+      switch (pb->byte_order)
+	{
+	case BYTE_ORD_24_RGB:
+	  return ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3);
+	case BYTE_ORD_24_BGR:
+	  return ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3);
+	}
+    case 24:
+    case 32:
+      switch (pb->byte_order)
+	{
+	case BYTE_ORD_24_RGB:
+	  return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
+	case BYTE_ORD_24_RBG:
+	  return ((r & 0xff) << 16) | ((b & 0xff) << 8) | (g & 0xff);
+	case BYTE_ORD_24_BRG:
+	  return ((b & 0xff) << 16) | ((r & 0xff) << 8) | (g & 0xff);
+	case BYTE_ORD_24_BGR:
+	  return ((b & 0xff) << 16) | ((g & 0xff) << 8) | (r & 0xff);
+	case BYTE_ORD_24_GRB:
+	  return ((g & 0xff) << 16) | ((r & 0xff) << 8) | (b & 0xff);
+	case BYTE_ORD_24_GBR:
+	  return ((g & 0xff) << 16) | ((b & 0xff) << 8) | (r & 0xff);
+	case BYTE_ORD_32_ARGB:
+	  return  (a << 24) | (r << 16) | (g << 8) | b;
+	default:
+	  return 0;
+	}
+    default:
+      return 0;
+    }
+}
+
+/*
+ * Get pixel value from pointer to 16bpp data for pixel depth > 8
+ * and advance the pointer
+ *
+ * TODO ? We could take the 32bit case out of here, which would allow
+ * to ignore the alpha value for <15, 24>, but we might not gain that
+ * much by this on arm due to the conditional execution.
+ */
+static inline unsigned long
+mb_pixbuf_get_pixel_gt8_16bpp_advance (MBPixbuf *pb, unsigned char ** p,
+				       int has_alpha)
+{
+  unsigned short s = SHORT_FROM_2BYTES(*p);
+  int r, b, g, a;
+
+  r = (s & 0xf800) >> 8;
+  g = (s & 0x07e0) >> 3;
+  b = (s & 0x001f) << 3;
+
+  *p += 2;
+  
+  a = has_alpha ?  *(*p)++ : 0xff;
+
+  return mb_pixbuf_get_pixel_gt8_rgba (pb, r, g, b, a);
+}
+
+static inline unsigned long
+mb_pixbuf_get_pixel(MBPixbuf *pb, int r, int g, int b, int a)
+{
+  if (pb->depth > 8)
+    return mb_pixbuf_get_pixel_gt8_rgba (pb, r, g, b, a);
+
+  return mb_pixbuf_get_pixel_le8_rgb (pb, r, g, b);
+}
+
 unsigned long
 mb_pixbuf_lookup_x_pixel(MBPixbuf *pb, int r, int g, int b, int a)
 {
@@ -1825,7 +1903,6 @@
   mb_pixbuf_img_render_to_drawable_with_gc(pb, img, drw, drw_x, drw_y, pb->gc);
 }
 
-
 void
 mb_pixbuf_img_render_to_drawable_with_gc(MBPixbuf    *pb,
 					 MBPixbufImage *img,
@@ -1883,31 +1960,57 @@
 
       if (pb->internal_bytespp == 2)
 	{
-	  for(y=0; y<img->height; y++)
-	    for(x=0; x<img->width; x++)
-	      {
-		/* Below is potentially dangerous.  
-		 */
-		pixel =  ( *p | (*(p+1) << 8)); 
-
-		p +=  ((img->has_alpha) ?  3 : 2);
-		
-		XPutPixel(img->ximg, x, y, pixel);
-	      }
+	  if (pb->depth > 8)
+	    {
+	      for(y=0; y<img->height; y++)
+		for(x=0; x<img->width; x++)
+		  {
+		    pixel = mb_pixbuf_get_pixel_gt8_16bpp_advance(pb, &p,
+								  img->has_alpha);
+		    XPutPixel(img->ximg, x, y, pixel);
+		  }
+	    }
+	  else
+	    {
+	      for(y=0; y<img->height; y++)
+		for(x=0; x<img->width; x++)
+		  {
+		    pixel = mb_pixbuf_get_pixel_le8_16bpp_advance(pb, &p);
+		    XPutPixel(img->ximg, x, y, pixel);
+		  }
+	    }
 	}
       else
 	{
-	  for(y=0; y<img->height; y++)
+	  if (pb->depth > 8)
 	    {
-	      for(x=0; x<img->width; x++)
+	      for(y=0; y<img->height; y++)
 		{
-		  r = ( *p++ );
-		  g = ( *p++ );
-		  b = ( *p++ );
-		  a = ((img->has_alpha) ?  *p++ : 0xff);
+		  for(x=0; x<img->width; x++)
+		    {
+		      r = ( *p++ );
+		      g = ( *p++ );
+		      b = ( *p++ );
+		      a = ((img->has_alpha) ?  *p++ : 0xff);
 		  
-		  pixel = mb_pixbuf_get_pixel(pb, r, g, b, a);
-		  XPutPixel(img->ximg, x, y, pixel);
+		      pixel = mb_pixbuf_get_pixel_gt8_rgba(pb, r, g, b, a);
+		      XPutPixel(img->ximg, x, y, pixel);
+		    }
+		}
+	    }
+	  else
+	    {
+	      for(y=0; y<img->height; y++)
+		{
+		  for(x=0; x<img->width; x++)
+		    {
+		      r = ( *p++ );
+		      g = ( *p++ );
+		      b = ( *p++ );
+		  
+		      pixel = mb_pixbuf_get_pixel_le8_rgb(pb, r, g, b);
+		      XPutPixel(img->ximg, x, y, pixel);
+		    }
 		}
 	    }
 	}
