diff --git a/src/org/oscim/renderer/BaseMap.java b/src/org/oscim/renderer/BaseMap.java
index a4c4c3a7..1c284224 100644
--- a/src/org/oscim/renderer/BaseMap.java
+++ b/src/org/oscim/renderer/BaseMap.java
@@ -103,7 +103,7 @@ public class BaseMap {
 		if (t.holder != null)
 			t = t.holder;
 
-		if (t.layers == null)
+		if (t.layers == null || t.vbo == null)
 			return;
 
 		// set Model matrix for tile
@@ -149,15 +149,6 @@ public class BaseMap {
 					break;
 			}
 		}
-
-		//		if (tile.layers.textureLayers != null) {
-		//			setMatrix(mvp, tile, div, false);
-		//
-		//			for (Layer l = tile.layers.textureLayers; l != null;) {
-		//				l = TextureRenderer.draw(l, 1, mProjMatrix, mvp,
-		//						tile.layers.texOffset);
-		//			}
-		//		}
 	}
 
 	private static int drawProxyChild(MapTile tile, MapPosition pos) {
diff --git a/src/org/oscim/renderer/BufferObject.java b/src/org/oscim/renderer/BufferObject.java
index 079b84a7..27cd22f1 100644
--- a/src/org/oscim/renderer/BufferObject.java
+++ b/src/org/oscim/renderer/BufferObject.java
@@ -16,17 +16,42 @@
 package org.oscim.renderer;
 
 import android.opengl.GLES20;
+import android.util.Log;
 
 public final class BufferObject {
+	private final static String TAG = BufferObject.class.getName();
+
 	private static BufferObject pool;
-	static int counter;
+	static int counter = 0;
 
-	static synchronized BufferObject get() {
+	public static synchronized BufferObject get(int size) {
 
-		if (pool == null)
-			return null;
+		if (pool == null) {
+			if (counter != 0)
+				Log.d(TAG, "missing BufferObjects: " + counter);
+
+			createBuffers(10);
+			counter += 10;
+		}
 		counter--;
 
+		if (size != 0) {
+			// sort so that items larger than requested size are promoted in the list
+			BufferObject prev = null;
+			for (BufferObject bo = pool; bo != null; bo = bo.next) {
+				if (bo.size > size) {
+					if (prev == null)
+						pool = bo.next;
+					else
+						prev.next = bo.next;
+
+					bo.next = null;
+					Log.d(TAG, "requested: " + size + " got " + bo.size);
+					return bo;
+				}
+				prev = bo;
+			}
+		}
 		BufferObject bo = pool;
 		pool = pool.next;
 		bo.next = null;
@@ -61,7 +86,11 @@ public final class BufferObject {
 	// return bo;
 	// }
 
-	static synchronized void release(BufferObject bo) {
+	public static synchronized void release(BufferObject bo) {
+		if (counter > 200) {
+			Log.d(TAG, "should clear some buffers " + counter);
+		}
+
 		bo.next = pool;
 		pool = bo;
 		counter++;
@@ -69,49 +98,56 @@ public final class BufferObject {
 
 	// Note: only call from GL-Thread
 	static synchronized int limitUsage(int reduce) {
+		if (pool == null) {
+			Log.d(TAG, "nothing to free");
+			return 0;
+		}
 		int vboIds[] = new int[10];
-		BufferObject[] tmp = new BufferObject[10];
 		int removed = 0;
 		int freed = 0;
+		BufferObject prev = pool;
 
-		for (BufferObject bo = pool; bo != null; bo = bo.next) {
+		for (BufferObject bo = pool.next; bo != null;) {
 			if (bo.size > 0) {
 				freed += bo.size;
 				bo.size = 0;
-				vboIds[removed] = bo.id;
-				tmp[removed++] = bo;
-
+				vboIds[removed++] = bo.id;
+				prev.next = bo.next;
+				bo = bo.next;
 				if (removed == 10 || reduce < freed)
 					break;
+
+			} else {
+				prev = bo;
+				bo = bo.next;
 			}
 		}
 		if (removed > 0) {
 			GLES20.glDeleteBuffers(removed, vboIds, 0);
-			GLES20.glGenBuffers(removed, vboIds, 0);
-
-			for (int i = 0; i < removed; i++)
-				tmp[i].id = vboIds[i];
+			counter -= removed;
 		}
 
 		return freed;
 	}
 
-	static void init(int num) {
+	static void createBuffers(int num) {
 		int[] mVboIds = new int[num];
 		GLES20.glGenBuffers(num, mVboIds, 0);
 
-		BufferObject bo;
-
-		for (int i = 1; i < num; i++) {
-			bo = new BufferObject(mVboIds[i]);
+		for (int i = 0; i < num; i++) {
+			BufferObject bo = new BufferObject(mVboIds[i]);
 			bo.next = pool;
 			pool = bo;
 		}
-		counter = num;
+	}
+
+	static synchronized void init(int num) {
+		//createBuffers(num);
+		//counter = num;
 	}
 
 	public int id;
-	int size;
+	public int size;
 	BufferObject next;
 
 	BufferObject(int id) {
diff --git a/src/org/oscim/renderer/GLRenderer.java b/src/org/oscim/renderer/GLRenderer.java
index 495292e8..b3cc60f0 100644
--- a/src/org/oscim/renderer/GLRenderer.java
+++ b/src/org/oscim/renderer/GLRenderer.java
@@ -208,13 +208,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 
 	private static int uploadCnt = 0;
 
-	private static boolean uploadLayers(Layers layers, BufferObject vbo, boolean addFill) {
-
-		int newSize = layers.getSize();
-		if (newSize == 0) {
-			// Log.d(TAG, "empty");
-			return true;
-		}
+	private static boolean uploadLayers(Layers layers, BufferObject vbo, int newSize,
+			boolean addFill) {
 
 		GLES20.glBindBuffer(GL_ARRAY_BUFFER, vbo.id);
 
@@ -278,24 +273,34 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		if (tile.layers == null) {
 			BufferObject.release(tile.vbo);
 			tile.vbo = null;
-		} else if (!uploadLayers(tile.layers, tile.vbo, true)) {
-			Log.d(TAG, "uploadTileData " + tile + " failed!");
-			tile.layers.clear();
-			tile.layers = null;
-			BufferObject.release(tile.vbo);
-			tile.vbo = null;
-		}
+		} else {
+			int newSize = tile.layers.getSize();
 
+			if (newSize > 0) {
+
+				if (tile.vbo == null)
+					tile.vbo = BufferObject.get(newSize);
+
+				if (!uploadLayers(tile.layers, tile.vbo, newSize, true)) {
+					Log.d(TAG, "uploadTileData " + tile + " failed!");
+					tile.layers.clear();
+					tile.layers = null;
+					BufferObject.release(tile.vbo);
+					tile.vbo = null;
+				}
+			}
+		}
 		tile.state = STATE_READY;
 	}
 
 	private static boolean uploadOverlayData(RenderOverlay renderOverlay) {
+		int newSize = renderOverlay.layers.getSize();
+		if (newSize > 0) {
+			if (uploadLayers(renderOverlay.layers, renderOverlay.vbo, newSize, true))
+				renderOverlay.isReady = true;
 
-		if (uploadLayers(renderOverlay.layers, renderOverlay.vbo, true))
-			renderOverlay.isReady = true;
-
-		renderOverlay.newData = false;
-
+			renderOverlay.newData = false;
+		}
 		return renderOverlay.isReady;
 	}
 
@@ -476,7 +481,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 			// helper to compile layers into single vbo
 			if (renderOverlay.newData) {
 				if (renderOverlay.vbo == null) {
-					renderOverlay.vbo = BufferObject.get();
+					renderOverlay.vbo = BufferObject.get(0);
 
 					if (renderOverlay.vbo == null)
 						continue;
diff --git a/src/org/oscim/renderer/TileManager.java b/src/org/oscim/renderer/TileManager.java
index 5c8ed93d..367ffcef 100644
--- a/src/org/oscim/renderer/TileManager.java
+++ b/src/org/oscim/renderer/TileManager.java
@@ -660,13 +660,13 @@ public class TileManager {
 			return true;
 		}
 
-		tile.vbo = BufferObject.get();
-
-		if (tile.vbo == null) {
-			Log.d(TAG, "no VBOs left for " + tile);
-			clearTile(tile);
-			return true;
-		}
+		//		tile.vbo = BufferObject.get(false);
+		//
+		//		if (tile.vbo == null) {
+		//			Log.d(TAG, "no VBOs left for " + tile);
+		//			//clearTile(tile);
+		//			//return true;
+		//		}
 
 		tile.state = STATE_NEW_DATA;
 
diff --git a/src/org/oscim/renderer/layer/ExtrusionLayer.java b/src/org/oscim/renderer/layer/ExtrusionLayer.java
index 78ff4f00..deb36f6c 100644
--- a/src/org/oscim/renderer/layer/ExtrusionLayer.java
+++ b/src/org/oscim/renderer/layer/ExtrusionLayer.java
@@ -20,6 +20,7 @@ import java.nio.FloatBuffer;
 import java.nio.ShortBuffer;
 
 import org.oscim.core.Tile;
+import org.oscim.renderer.BufferObject;
 import org.oscim.renderer.GLRenderer;
 import org.oscim.utils.LineClipper;
 import org.oscim.view.MapView;
@@ -31,7 +32,7 @@ import android.util.Log;
 /**
  * @author Hannes Janetzek
  *         FIXME check if polygon has self intersections or 0/180 degree
- *         angles!!!
+ *         angles!
  */
 public class ExtrusionLayer extends Layer {
 	private final static String TAG = ExtrusionLayer.class.getName();
@@ -44,9 +45,12 @@ public class ExtrusionLayer extends Layer {
 	// indices for:
 	// 0. even sides, 1. odd sides, 2. roof, 3. roof outline
 	public int mIndiceCnt[] = { 0, 0, 0, 0 };
+	public int mNumIndices = 0;
+
 	public int mIndicesBufferID;
 	public int mVertexBufferID;
-	public int mNumIndices = 0;
+	private BufferObject mIndiceBO;
+	private BufferObject mVertexBO;
 
 	//private final static int IND_EVEN_SIDE = 0;
 	//private final static int IND_ODD_SIDE = 1;
@@ -54,7 +58,8 @@ public class ExtrusionLayer extends Layer {
 	private final static int IND_OUTLINE = 3;
 
 	public boolean compiled = false;
-	private int[] mVboIds;
+
+	//private int[] mVboIds;
 
 	public ExtrusionLayer(int level) {
 		this.type = Layer.EXTRUSION;
@@ -345,13 +350,18 @@ public class ExtrusionLayer extends Layer {
 		if (mNumVertices == 0 || compiled)
 			return;
 
-		mVboIds = new int[2];
-		GLES20.glGenBuffers(2, mVboIds, 0);
-		mIndicesBufferID = mVboIds[0];
-		mVertexBufferID = mVboIds[1];
+		//		mVboIds = new int[2];
+		//		GLES20.glGenBuffers(2, mVboIds, 0);
+		//		mIndicesBufferID = mVboIds[0];
+		//		mVertexBufferID = mVboIds[1];
+
+		// FIXME add in_gl_thread param to make sure we get something here
+		mVertexBO = BufferObject.get(0);
+		mIndiceBO = BufferObject.get(0);
+		mIndicesBufferID = mIndiceBO.id;
+		mVertexBufferID = mVertexBO.id;
 
 		// upload indices
-
 		sbuf.clear();
 		mNumIndices = 0;
 		for (int i = 0; i < 4; i++) {
@@ -363,9 +373,10 @@ public class ExtrusionLayer extends Layer {
 		}
 
 		sbuf.flip();
+		mIndiceBO.size = mNumIndices * 2;
 		GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, mIndicesBufferID);
 		GLES20.glBufferData(GLES20.GL_ELEMENT_ARRAY_BUFFER,
-				mNumIndices * 2, sbuf, GLES20.GL_DYNAMIC_DRAW);
+				mIndiceBO.size, sbuf, GLES20.GL_DYNAMIC_DRAW);
 
 		// upload vertices
 		sbuf.clear();
@@ -373,9 +384,10 @@ public class ExtrusionLayer extends Layer {
 			sbuf.put(vi.vertices, 0, vi.used);
 
 		sbuf.flip();
+		mVertexBO.size = mNumVertices * 4 * 2;
 		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mVertexBufferID);
 		GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER,
-				mNumVertices * 4 * 2, sbuf, GLES20.GL_DYNAMIC_DRAW);
+				mVertexBO.size, sbuf, GLES20.GL_DYNAMIC_DRAW);
 
 		GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
 		GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
@@ -393,7 +405,11 @@ public class ExtrusionLayer extends Layer {
 	@Override
 	protected void clear() {
 		if (compiled) {
-			GLES20.glDeleteBuffers(2, mVboIds, 0);
+			BufferObject.release(mIndiceBO);
+			BufferObject.release(mVertexBO);
+			mIndiceBO = null;
+			mVertexBO = null;
+			//GLES20.glDeleteBuffers(2, mVboIds, 0);
 		} else {
 			VertexPool.release(mVertices);
 			for (VertexPoolItem i : mIndices)