diff --git a/vtm/src/org/oscim/layers/tile/MapTile.java b/vtm/src/org/oscim/layers/tile/MapTile.java
index 999b9ebd..00f56d2c 100644
--- a/vtm/src/org/oscim/layers/tile/MapTile.java
+++ b/vtm/src/org/oscim/layers/tile/MapTile.java
@@ -16,13 +16,19 @@
  */
 package org.oscim.layers.tile;
 
+import static org.oscim.layers.tile.MapTile.State.DEADBEEF;
+import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
+import static org.oscim.layers.tile.MapTile.State.READY;
+
 import org.oscim.core.Tile;
 import org.oscim.layers.tile.vector.VectorTileLoader;
 import org.oscim.layers.tile.vector.labeling.LabelTileLoaderHook;
 import org.oscim.renderer.elements.ElementLayers;
 import org.oscim.utils.pool.Inlist;
-import org.oscim.utils.quadtree.TreeNode;
 import org.oscim.utils.quadtree.TileIndex;
+import org.oscim.utils.quadtree.TreeNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Extends Tile class to hold state and data.
@@ -32,8 +38,9 @@ import org.oscim.utils.quadtree.TileIndex;
  */
 public class MapTile extends Tile {
 
-	public static class TileNode extends TreeNode<TileNode, MapTile> {
+	static final Logger log = LoggerFactory.getLogger(MapTile.class);
 
+	public static class TileNode extends TreeNode<TileNode, MapTile> {
 	}
 
 	public static final class State {
@@ -43,49 +50,46 @@ public class MapTile extends Tile {
 		 * STATE_LOADING means the tile is about to be loaded / loading.
 		 * Tile belongs to TileLoader thread.
 		 */
-		public final static byte LOADING = 1 << 0;
+		public final static byte LOADING = (1 << 0);
 
 		/**
 		 * STATE_NEW_DATA: tile data is prepared for rendering.
 		 * While 'locked' it belongs to GL Thread.
 		 */
-		public final static byte NEW_DATA = 1 << 1;
+		public final static byte NEW_DATA = (1 << 1);
 
 		/**
 		 * STATE_READY: tile data is uploaded to GL.
 		 * While 'locked' it belongs to GL Thread.
 		 */
-		public final static byte READY = 1 << 2;
+		public final static byte READY = (1 << 2);
 
 		/**
 		 * STATE_CANCEL: tile is removed from TileManager,
 		 * but may still be processed by TileLoader.
 		 */
-		public final static byte CANCEL = 1 << 3;
+		public final static byte CANCEL = (1 << 3);
+
+		public final static byte DEADBEEF = (1 << 4);
+
 	}
 
-	public static abstract class TileData extends Inlist<TileData> {
-		Object id;
+	public final static int PROXY_CHILD00 = (1 << 0);
+	public final static int PROXY_CHILD01 = (1 << 1);
+	public final static int PROXY_CHILD10 = (1 << 2);
+	public final static int PROXY_CHILD11 = (1 << 3);
+	public final static int PROXY_PARENT = (1 << 4);
+	public final static int PROXY_GRAMPA = (1 << 5);
+	public final static int PROXY_HOLDER = (1 << 6);
 
-		protected abstract void dispose();
-	}
+	/** Tile state */
+	byte state;
 
-	public MapTile(TileNode node, int tileX, int tileY, int zoomLevel) {
-		super(tileX, tileY, (byte) zoomLevel);
-		this.x = (double) tileX / (1 << zoomLevel);
-		this.y = (double) tileY / (1 << zoomLevel);
-		this.node = node;
-	}
-
-	protected byte state;
-
-	public boolean state(int testState) {
-		return (state & testState) != 0;
-	}
-
-	public byte getState() {
-		return state;
-	}
+	/**
+	 * absolute tile coordinates: tileX,Y / Math.pow(2, zoomLevel)
+	 */
+	public final double x;
+	public final double y;
 
 	/**
 	 * List of TileData for rendering. ElementLayers is always at first
@@ -95,10 +99,9 @@ public class MapTile extends Tile {
 	public TileData data;
 
 	/**
-	 * absolute tile coordinates: tileX,Y / Math.pow(2, zoomLevel)
+	 * Pointer to access relatives in {@link TileIndex}
 	 */
-	public final double x;
-	public final double y;
+	public final TileNode node;
 
 	/**
 	 * current distance from map center
@@ -117,40 +120,50 @@ public class MapTile extends Tile {
 
 	/**
 	 * Used to avoid drawing a tile twice per frame
-	 * TODO remove
 	 */
 	int lastDraw = 0;
 
-	/**
-	 * Pointer to access relatives in {@link TileIndex}
-	 */
-	public final TileNode node;
+	/** Keep track which tiles are locked as proxy for this tile */
+	private int proxy = 0;
 
-	public final static int PROXY_CHILD1 = 1 << 0;
-	public final static int PROXY_CHILD2 = 1 << 1;
-	public final static int PROXY_CHILD3 = 1 << 2;
-	public final static int PROXY_CHILD4 = 1 << 3;
-	public final static int PROXY_PARENT = 1 << 4;
-	public final static int PROXY_GRAMPA = 1 << 5;
-	public final static int PROXY_HOLDER = 1 << 6;
+	/** Tile lock counter, synced in TileManager */
+	private int locked = 0;
 
-	/** keep track which tiles are locked as proxy for this tile */
-	byte proxies;
-
-	/** counting the tiles that use this tile as proxy */
-	private byte refs;
-
-	/** up to 255 Threads may lock a tile */
-	private byte locked;
+	private int refs = 0;
 
 	/**
-	 * only used GLRenderer when this tile sits in for another tile.
+	 * Only used GLRenderer when this tile sits in for another tile.
 	 * e.g. x:-1,y:0,z:1 for x:1,y:0
 	 */
 	MapTile holder;
 
+	public static abstract class TileData extends Inlist<TileData> {
+		Object id;
+
+		protected abstract void dispose();
+
+		public TileData next() {
+			return (TileData) next;
+		}
+	}
+
+	public MapTile(TileNode node, int tileX, int tileY, int zoomLevel) {
+		super(tileX, tileY, (byte) zoomLevel);
+		this.x = (double) tileX / (1 << zoomLevel);
+		this.y = (double) tileY / (1 << zoomLevel);
+		this.node = node;
+	}
+
+	public boolean state(int testState) {
+		return (state & testState) != 0;
+	}
+
+	public int getState() {
+		return state;
+	}
+
 	/**
-	 * @return true when tile might be referenced by render thread.
+	 * @return true when tile could be used by another thread.
 	 */
 	boolean isLocked() {
 		return locked > 0 || refs > 0;
@@ -166,24 +179,34 @@ public class MapTile extends Tile {
 		if (locked++ > 0)
 			return;
 
+		MapTile p;
 		/* lock all tiles that could serve as proxy */
-		MapTile p = node.parent.item;
-		if (p != null && (p.state != State.NONE)) {
-			proxies |= PROXY_PARENT;
-			p.refs++;
-		}
-
-		p = node.parent.parent.item;
-		if (p != null && (p.state != State.NONE)) {
-			proxies |= PROXY_GRAMPA;
-			p.refs++;
-		}
-
-		for (int j = 0; j < 4; j++) {
-			if ((p = node.child(j)) == null || p.state == 0)
+		for (int i = 0; i < 4; i++) {
+			p = node.child(i);
+			if (p == null)
 				continue;
 
-			proxies |= (1 << j);
+			if (p.state(READY | NEW_DATA)) {
+				proxy |= (1 << i);
+				p.refs++;
+			}
+		}
+
+		if (node.isRoot())
+			return;
+
+		p = node.parent();
+		if (p != null && p.state(READY | NEW_DATA)) {
+			proxy |= PROXY_PARENT;
+			p.refs++;
+		}
+
+		if (node.parent.isRoot())
+			return;
+
+		p = node.parent.parent();
+		if (p != null && p.state(READY | NEW_DATA)) {
+			proxy |= PROXY_GRAMPA;
 			p.refs++;
 		}
 	}
@@ -192,25 +215,28 @@ public class MapTile extends Tile {
 	 * Unlocks this tile when it cannot be used by render-thread.
 	 */
 	void unlock() {
-		if (--locked > 0 || proxies == 0)
+		if (--locked > 0)
 			return;
 
-		if ((proxies & PROXY_PARENT) != 0)
-			node.parent.item.refs--;
-
-		if ((proxies & PROXY_GRAMPA) != 0)
-			node.parent.parent.item.refs--;
+		TileNode parent = node.parent;
+		if ((proxy & PROXY_PARENT) != 0)
+			parent.item.refs--;
 
+		if ((proxy & PROXY_GRAMPA) != 0) {
+			parent = parent.parent;
+			parent.item.refs--;
+		}
 		for (int i = 0; i < 4; i++) {
-			if ((proxies & (1 << i)) != 0)
+			if ((proxy & (1 << i)) != 0)
 				node.child(i).refs--;
 		}
-		proxies = 0;
+
+		/* removed all proxy references for this tile */
+		proxy = 0;
 	}
 
 	/**
-	 * @return true if tile is loading, has new data or is ready
-	 *         for rendering
+	 * @return true if tile is state is not NONE.
 	 */
 	public boolean isActive() {
 		return state > State.NONE;
@@ -221,7 +247,7 @@ public class MapTile extends Tile {
 	 * through this.node.*
 	 */
 	public boolean hasProxy(int proxy) {
-		return (proxies & proxy) != 0;
+		return (this.proxy & proxy) != 0;
 	}
 
 	/**
@@ -233,9 +259,7 @@ public class MapTile extends Tile {
 			data.dispose();
 			data = data.next;
 		}
-
-		// still needed?
-		state = State.NONE;
+		state = DEADBEEF;
 	}
 
 	/**
@@ -257,7 +281,7 @@ public class MapTile extends Tile {
 	}
 
 	public void addData(Object id, TileData td) {
-		// keeping ElementLayers at position 0!
+		/* keeping ElementLayers at position 0! */
 		td.id = id;
 		if (data != null) {
 			td.next = data.next;
@@ -267,7 +291,80 @@ public class MapTile extends Tile {
 		}
 	}
 
+	public TileData removeData(Object id) {
+		if (data == null)
+			return null;
+
+		TileData prev = data;
+		if (data.id == id) {
+			data = data.next;
+			return prev;
+		}
+		for (TileData d = data.next; d != null; d = d.next) {
+			if (d.id == id) {
+				prev.next = d.next;
+				return d;
+			}
+			prev = d;
+		}
+		return null;
+	}
+
 	public static int depthOffset(MapTile t) {
 		return ((t.tileX % 4) + (t.tileY % 4 * 4) + 1);
 	}
+
+	public MapTile getProxyChild(int id, byte state) {
+		if ((proxy & (1 << id)) == 0)
+			return null;
+
+		MapTile child = node.child(id);
+		if (child == null || (child.state & state) == 0)
+			return null;
+
+		return child;
+	}
+
+	public MapTile getParent() {
+		if ((proxy & PROXY_PARENT) == 0)
+			return null;
+
+		return node.parent.item;
+	}
+
+	public MapTile getProxy(int proxy, byte state) {
+
+		if ((this.proxy & proxy) == 0)
+			return null;
+
+		MapTile p = null;
+		switch (proxy) {
+			case PROXY_CHILD00:
+				p = node.child(0);
+				break;
+			case PROXY_CHILD01:
+				p = node.child(1);
+				break;
+			case PROXY_CHILD10:
+				p = node.child(2);
+				break;
+			case PROXY_CHILD11:
+				p = node.child(3);
+				break;
+			case PROXY_PARENT:
+				p = node.parent();
+				break;
+			case PROXY_GRAMPA:
+				p = node.parent.parent();
+				break;
+			case PROXY_HOLDER:
+				p = holder;
+				break;
+		}
+
+		if (p == null || (p.state & state) == 0)
+			return null;
+
+		return p;
+	}
 }
diff --git a/vtm/src/org/oscim/layers/tile/TileRenderer.java b/vtm/src/org/oscim/layers/tile/TileRenderer.java
index bb631aa2..8e01f60b 100644
--- a/vtm/src/org/oscim/layers/tile/TileRenderer.java
+++ b/vtm/src/org/oscim/layers/tile/TileRenderer.java
@@ -16,11 +16,13 @@
  */
 package org.oscim.layers.tile;
 
+import static org.oscim.layers.tile.MapTile.PROXY_PARENT;
 import static org.oscim.layers.tile.MapTile.State.NEW_DATA;
 import static org.oscim.layers.tile.MapTile.State.READY;
 
 import org.oscim.backend.GL20;
 import org.oscim.core.MapPosition;
+import org.oscim.layers.tile.MapTile.TileNode;
 import org.oscim.renderer.BufferObject;
 import org.oscim.renderer.ElementRenderer;
 import org.oscim.renderer.GLViewport;
@@ -36,7 +38,7 @@ public abstract class TileRenderer extends LayerRenderer {
 
 	/** fade-in time */
 	protected static final float FADE_TIME = 500;
-	protected static final int MAX_TILE_LOAD = 1;
+	protected static final int MAX_TILE_LOAD = 8;
 
 	private TileManager mTileManager;
 
@@ -46,8 +48,8 @@ public abstract class TileRenderer extends LayerRenderer {
 	private int mOverdraw = 0;
 	private float mAlpha = 1;
 
-	protected int mRenderOverdraw;
-	protected float mRenderAlpha;
+	protected int mOverdrawColor;
+	protected float mLayerAlpha;
 
 	private int mUploadSerial;
 
@@ -60,12 +62,6 @@ public abstract class TileRenderer extends LayerRenderer {
 		mTileManager = tileManager;
 	}
 
-	/**
-	 * Current number of frames drawn, used to not draw a
-	 * tile twice per frame.
-	 */
-	protected int mDrawSerial;
-
 	/**
 	 * Threadsafe
 	 */
@@ -101,8 +97,8 @@ public abstract class TileRenderer extends LayerRenderer {
 			return;
 
 		/* keep constant while rendering frame */
-		mRenderAlpha = mAlpha;
-		mRenderOverdraw = mOverdraw;
+		mLayerAlpha = mAlpha;
+		mOverdrawColor = mOverdraw;
 
 		int tileCnt = mDrawTiles.cnt;
 		MapTile[] tiles = mDrawTiles.tiles;
@@ -118,8 +114,6 @@ public abstract class TileRenderer extends LayerRenderer {
 			mUploadSerial++;
 			BufferObject.checkBufferUsage(false);
 		}
-
-		mDrawSerial++;
 	}
 
 	@Override
@@ -153,36 +147,30 @@ public abstract class TileRenderer extends LayerRenderer {
 				continue;
 			}
 
-			if (tile.holder != null) {
-				/* load tile that is referenced by this holder */
-				if (tile.holder.state == NEW_DATA)
-					uploadCnt += uploadTileData(tile.holder);
-
-				tile.state = tile.holder.state;
+			/* load tile that is referenced by this holder */
+			MapTile proxy = tile.holder;
+			if (proxy != null && proxy.state == NEW_DATA) {
+				uploadCnt += uploadTileData(proxy);
+				tile.state = proxy.state;
 				continue;
 			}
 
 			/* check near relatives than can serve as proxy */
-			if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
-				MapTile t = tile.node.parent.item;
-				if (t.state == NEW_DATA)
-					uploadCnt += uploadTileData(t);
-
+			proxy = tile.getProxy(PROXY_PARENT, NEW_DATA);
+			if (proxy != null) {
+				uploadCnt += uploadTileData(proxy);
 				/* dont load child proxies */
 				continue;
 			}
 
 			for (int c = 0; c < 4; c++) {
-				if ((tile.proxies & 1 << c) == 0)
-					continue;
+				proxy = tile.getProxyChild(c, NEW_DATA);
+				if (proxy != null)
+					uploadCnt += uploadTileData(proxy);
+			}
 
-				MapTile t = tile.node.child(i);
-				if (t != null && t.state == NEW_DATA)
-					uploadCnt += uploadTileData(t);
-			}
-			if (uploadCnt >= MAX_TILE_LOAD) {
+			if (uploadCnt >= MAX_TILE_LOAD)
 				break;
-			}
 		}
 		return uploadCnt;
 	}
@@ -295,9 +283,9 @@ public abstract class TileRenderer extends LayerRenderer {
 		protected void setVisible(int y, int x1, int x2) {
 
 			MapTile[] tiles = mDrawTiles.tiles;
-			int cnt = mDrawTiles.cnt;
+			int proxyOffset = mDrawTiles.cnt;
 
-			for (int i = 0; i < cnt; i++) {
+			for (int i = 0; i < proxyOffset; i++) {
 				MapTile t = tiles[i];
 				if (t.tileY == y && t.tileX >= x1 && t.tileX < x2)
 					t.isVisible = true;
@@ -322,12 +310,12 @@ public abstract class TileRenderer extends LayerRenderer {
 				if (xx < 0 || xx >= xmax)
 					continue;
 
-				for (int i = cnt; i < cnt + mProxyTileCnt; i++)
+				for (int i = proxyOffset; i < proxyOffset + mProxyTileCnt; i++)
 					if (tiles[i].tileX == x && tiles[i].tileY == y)
 						continue O;
 
 				MapTile tile = null;
-				for (int i = 0; i < cnt; i++)
+				for (int i = 0; i < proxyOffset; i++)
 					if (tiles[i].tileX == xx && tiles[i].tileY == y) {
 						tile = tiles[i];
 						break;
@@ -336,24 +324,31 @@ public abstract class TileRenderer extends LayerRenderer {
 				if (tile == null)
 					continue;
 
-				if (cnt + mProxyTileCnt >= tiles.length) {
+				if (proxyOffset + mProxyTileCnt >= tiles.length) {
 					//log.error(" + mNumTileHolder");
 					break;
 				}
+
 				MapTile holder = new MapTile(null, x, y, (byte) mZoom);
 				holder.isVisible = true;
 				holder.holder = tile;
+				holder.state = tile.state;
 				tile.isVisible = true;
-				tiles[cnt + mProxyTileCnt++] = holder;
+				tiles[proxyOffset + mProxyTileCnt++] = holder;
 			}
 		}
 	};
 
-	protected long getMinFade(MapTile t, int proxyLevel) {
+	/**
+	 * @param proxyLevel zoom-level of tile relative to current TileSet
+	 */
+	public static long getMinFade(MapTile tile, int proxyLevel) {
 		long minFade = MapRenderer.frametime - 50;
+
+		/* check children for grandparent, parent or current */
 		if (proxyLevel <= 0) {
 			for (int c = 0; c < 4; c++) {
-				MapTile ci = t.node.child(c);
+				MapTile ci = tile.node.child(c);
 				if (ci == null)
 					continue;
 
@@ -363,27 +358,27 @@ public abstract class TileRenderer extends LayerRenderer {
 				/* when drawing the parent of the current level
 				 * we also check if the children of current level
 				 * are visible */
-				if (proxyLevel > -2) {
+				if (proxyLevel >= -1) {
 					long m = getMinFade(ci, proxyLevel - 1);
 					if (m < minFade)
 						minFade = m;
 				}
 			}
 		}
-		if (proxyLevel >= -1) {
-			MapTile p = t.node.parent();
-			if (p != null) {
-				if (p.fadeTime > 0 && p.fadeTime < minFade)
-					minFade = p.fadeTime;
 
-				if (proxyLevel >= 0) {
-					if ((p = p.node.parent()) != null) {
-						if (p.fadeTime > 0 && p.fadeTime < minFade)
-							minFade = p.fadeTime;
-					}
-				}
-			}
+		/* check parents for child, current or parent */
+		TileNode p = tile.node.parent;
+
+		for (int i = proxyLevel; i >= -1; i--) {
+			if (p == null)
+				break;
+
+			if (p.item != null && p.item.fadeTime > 0 && p.item.fadeTime < minFade)
+				minFade = p.item.fadeTime;
+
+			p = p.parent;
 		}
+
 		return minFade;
 	}
 }
diff --git a/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java b/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java
index c9ee7c2a..aacaffb1 100644
--- a/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java
+++ b/vtm/src/org/oscim/layers/tile/VectorTileRenderer.java
@@ -1,5 +1,7 @@
 package org.oscim.layers.tile;
 
+import static org.oscim.layers.tile.MapTile.PROXY_GRAMPA;
+import static org.oscim.layers.tile.MapTile.PROXY_PARENT;
 import static org.oscim.layers.tile.MapTile.State.READY;
 import static org.oscim.renderer.elements.RenderElement.BITMAP;
 import static org.oscim.renderer.elements.RenderElement.LINE;
@@ -11,7 +13,6 @@ import org.oscim.backend.GL20;
 import org.oscim.backend.canvas.Color;
 import org.oscim.core.MapPosition;
 import org.oscim.core.Tile;
-import org.oscim.layers.tile.MapTile.TileNode;
 import org.oscim.renderer.GLMatrix;
 import org.oscim.renderer.GLViewport;
 import org.oscim.renderer.MapRenderer;
@@ -32,6 +33,12 @@ public class VectorTileRenderer extends TileRenderer {
 
 	protected GLMatrix mViewProj = new GLMatrix();
 
+	/**
+	 * Current number of frames drawn, used to not draw a
+	 * tile twice per frame.
+	 */
+	protected int mDrawSerial;
+
 	@Override
 	protected synchronized void update(GLViewport v) {
 		super.update(v);
@@ -45,12 +52,14 @@ public class VectorTileRenderer extends TileRenderer {
 
 		mClipMode = PolygonLayer.CLIP_STENCIL;
 
-		/* */
 		int tileCnt = mDrawTiles.cnt + mProxyTileCnt;
+
 		MapTile[] tiles = mDrawTiles.tiles;
 
 		boolean drawProxies = false;
 
+		mDrawSerial++;
+
 		for (int i = 0; i < tileCnt; i++) {
 			MapTile t = tiles[i];
 			if (t.isVisible && t.state != READY) {
@@ -71,47 +80,60 @@ public class VectorTileRenderer extends TileRenderer {
 			MapTile t = tiles[i];
 			if (t.isVisible && t.state == READY)
 				drawTile(t, v, 0);
-
 		}
 
 		/* draw parent or children as proxy for visibile tiles that dont
 		 * have data yet. Proxies are clipped to the region where nothing
 		 * was drawn to depth buffer.
 		 * TODO draw proxies for placeholder */
-		if (drawProxies) {
-			/* only draw where no other tile is drawn */
-			GL.glDepthFunc(GL20.GL_LESS);
+		if (!drawProxies)
+			return;
 
-			/* draw child or parent proxies */
-			boolean preferParent = (v.pos.getZoomScale() < 1.5)
-			        || (v.pos.zoomLevel < tiles[0].zoomLevel);
+		/* only draw where no other tile is drawn */
+		GL.glDepthFunc(GL20.GL_LESS);
 
+		/* draw child or parent proxies */
+		boolean preferParent = (v.pos.getZoomScale() < 1.5)
+		        || (v.pos.zoomLevel < tiles[0].zoomLevel);
+
+		if (preferParent) {
 			for (int i = 0; i < tileCnt; i++) {
 				MapTile t = tiles[i];
-				if (t.isVisible
-				        && (t.state != READY)
-				        && (t.holder == null)) {
-					drawProxyTile(t, v, true, preferParent);
-				}
+				if ((!t.isVisible) || (t.lastDraw == mDrawSerial))
+					continue;
+				if (!drawParent(t, v))
+					drawChildren(t, v);
 			}
-
-			/* draw grandparents */
+		} else {
 			for (int i = 0; i < tileCnt; i++) {
 				MapTile t = tiles[i];
-				if (t.isVisible
-				        && (t.state != READY)
-				        && (t.holder == null))
-					drawProxyTile(t, v, false, false);
+				if ((!t.isVisible) || (t.lastDraw == mDrawSerial))
+					continue;
+				drawChildren(t, v);
+			}
+			for (int i = 0; i < tileCnt; i++) {
+				MapTile t = tiles[i];
+				if ((!t.isVisible) || (t.lastDraw == mDrawSerial))
+					continue;
+				drawParent(t, v);
 			}
-			GL.glDepthMask(false);
 		}
 
-		/* make sure stencil buffer write is disabled */
-		GL.glStencilMask(0x00);
+		/* draw grandparents */
+		for (int i = 0; i < tileCnt; i++) {
+			MapTile t = tiles[i];
+			if ((!t.isVisible) || (t.lastDraw == mDrawSerial))
+				continue;
+			drawGrandParent(t, v);
+		}
+		GL.glDepthMask(false);
 
+		/* make sure stencil buffer write is disabled */
+		//GL.glStencilMask(0x00);
 	}
 
 	private void drawTile(MapTile tile, GLViewport v, int proxyLevel) {
+
 		/* ensure to draw parents only once */
 		if (tile.lastDraw == mDrawSerial)
 			return;
@@ -119,12 +141,11 @@ public class VectorTileRenderer extends TileRenderer {
 		tile.lastDraw = mDrawSerial;
 
 		/* use holder proxy when it is set */
-		MapTile t = tile.holder == null ? tile : tile.holder;
-
-		ElementLayers layers = t.getLayers();
+		ElementLayers layers = (tile.holder == null)
+		        ? tile.getLayers()
+		        : tile.holder.getLayers();
 
 		if (layers == null || layers.vbo == null)
-			//throw new IllegalStateException(t + "no data " + (t.layers == null));
 			return;
 
 		layers.vbo.bind();
@@ -181,19 +202,16 @@ public class VectorTileRenderer extends TileRenderer {
 				clipped = true;
 			}
 			if (l.type == BITMAP) {
-				l = BitmapLayer.Renderer.draw(l, v, 1, mRenderAlpha);
+				l = BitmapLayer.Renderer.draw(l, v, 1, mLayerAlpha);
 				continue;
 			}
 			l = l.next;
 		}
 
-		if (t.fadeTime == 0)
-			t.fadeTime = getMinFade(t, proxyLevel);
-
 		if (debugOverdraw) {
-			if (t.zoomLevel > pos.zoomLevel)
+			if (tile.zoomLevel > pos.zoomLevel)
 				PolygonLayer.Renderer.drawOver(v, Color.BLUE, 0.5f);
-			else if (t.zoomLevel < pos.zoomLevel)
+			else if (tile.zoomLevel < pos.zoomLevel)
 				PolygonLayer.Renderer.drawOver(v, Color.RED, 0.5f);
 			else
 				PolygonLayer.Renderer.drawOver(v, Color.GREEN, 0.5f);
@@ -201,92 +219,57 @@ public class VectorTileRenderer extends TileRenderer {
 			return;
 		}
 
-		if (mRenderOverdraw != 0 && MapRenderer.frametime - t.fadeTime < FADE_TIME) {
-			float fade = 1 - (MapRenderer.frametime - t.fadeTime) / FADE_TIME;
-			PolygonLayer.Renderer.drawOver(v, mRenderOverdraw, fade * fade);
-			MapRenderer.animate();
-		} else {
-			PolygonLayer.Renderer.drawOver(v, 0, 1);
+		if (tile.fadeTime == 0) {
+			/* need to use original tile to get the fade */
+			MapTile t = (tile.holder == null) ? tile : tile.holder;
+			tile.fadeTime = getMinFade(t, proxyLevel);
 		}
+
+		long dTime = MapRenderer.frametime - tile.fadeTime;
+
+		if (mOverdrawColor == 0 || dTime > FADE_TIME) {
+			PolygonLayer.Renderer.drawOver(v, 0, 1);
+			return;
+		}
+
+		float fade = 1 - dTime / FADE_TIME;
+		PolygonLayer.Renderer.drawOver(v, mOverdrawColor, fade * fade);
+
+		MapRenderer.animate();
 	}
 
-	private int drawProxyChild(MapTile tile, GLViewport v) {
+	protected boolean drawChildren(MapTile t, GLViewport v) {
 		int drawn = 0;
 		for (int i = 0; i < 4; i++) {
-			if ((tile.proxies & 1 << i) == 0)
+			MapTile c = t.getProxyChild(i, READY);
+			if (c == null)
 				continue;
 
-			MapTile c = tile.node.child(i);
-
-			if (c.state == READY) {
-				drawTile(c, v, 1);
-				drawn++;
-			}
+			drawTile(c, v, 1);
+			drawn++;
 		}
-		return drawn;
+		if (drawn == 4) {
+			t.lastDraw = mDrawSerial;
+			return true;
+		}
+		return false;
 	}
 
-	protected void drawProxyTile(MapTile tile, GLViewport v,
-	        boolean parent, boolean preferParent) {
+	protected boolean drawParent(MapTile t, GLViewport v) {
+		MapTile proxy = t.getProxy(PROXY_PARENT, READY);
+		if (proxy != null) {
+			drawTile(proxy, v, -1);
+			t.lastDraw = mDrawSerial;
+			return true;
+		}
+		return false;
+	}
 
-		TileNode r = tile.node;
-		MapTile proxy;
-
-		if (!preferParent) {
-			/* prefer drawing children */
-			if (drawProxyChild(tile, v) == 4)
-				return;
-
-			if (parent) {
-				/* draw parent proxy */
-				if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
-					proxy = r.parent.item;
-					if (proxy.state == READY) {
-						//log.debug("1. draw parent " + proxy);
-						drawTile(proxy, v, -1);
-					}
-				}
-			} else if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
-				/* check if parent was already drawn */
-				if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
-					proxy = r.parent.item;
-					if (proxy.state == READY)
-						return;
-				}
-
-				proxy = r.parent.parent.item;
-				if (proxy.state == READY)
-					drawTile(proxy, v, -2);
-			}
-		} else {
-			/* prefer drawing parent */
-			if (parent) {
-				if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
-					proxy = r.parent.item;
-					if (proxy != null && proxy.state == READY) {
-						//log.debug("2. draw parent " + proxy);
-						drawTile(proxy, v, -1);
-						return;
-
-					}
-				}
-				drawProxyChild(tile, v);
-
-			} else if ((tile.proxies & MapTile.PROXY_GRAMPA) != 0) {
-				/* check if parent was already drawn */
-				if ((tile.proxies & MapTile.PROXY_PARENT) != 0) {
-					proxy = r.parent.item;
-					if (proxy.state == READY)
-						return;
-				}
-				/* this will do nothing, just to check */
-				if (drawProxyChild(tile, v) > 0)
-					return;
-
-				proxy = r.parent.parent.item;
-				if (proxy.state == READY)
-					drawTile(proxy, v, -2);
-			}
+	protected void drawGrandParent(MapTile t, GLViewport v) {
+		MapTile proxy = t.getProxy(PROXY_GRAMPA, READY);
+		if (proxy != null) {
+			drawTile(proxy, v, -2);
+			t.lastDraw = mDrawSerial;
 		}
 	}
 }
diff --git a/vtm/src/org/oscim/utils/quadtree/TreeNode.java b/vtm/src/org/oscim/utils/quadtree/TreeNode.java
index 85f0276c..0e86e125 100644
--- a/vtm/src/org/oscim/utils/quadtree/TreeNode.java
+++ b/vtm/src/org/oscim/utils/quadtree/TreeNode.java
@@ -58,4 +58,9 @@ public class TreeNode<T extends TreeNode<T, E>, E> {
 		}
 		return null;
 	}
+
+	public boolean isRoot() {
+		return this == parent;
+	}
+
 }