diff --git a/src/org/oscim/view/renderer/GLRenderer.java b/src/org/oscim/view/renderer/GLRenderer.java
index f0888691..91b6f7e1 100644
--- a/src/org/oscim/view/renderer/GLRenderer.java
+++ b/src/org/oscim/view/renderer/GLRenderer.java
@@ -97,6 +97,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 
 	// lock to synchronize Main- and GL-Thread
 	static ReentrantLock tilelock = new ReentrantLock();
+	static ReentrantLock lock = new ReentrantLock();
 
 	/**
 	 * @param mapView
@@ -113,6 +114,29 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 
 		Matrix.setIdentityM(mMVPMatrix, 0);
 
+		// add half pixel to tile clip/fill coordinates to avoid rounding issues
+		short min = -4;
+		short max = (short) ((Tile.TILE_SIZE << 3) + 4);
+		mFillCoords = new short[8];
+		mFillCoords[0] = min;
+		mFillCoords[1] = max;
+		mFillCoords[2] = max;
+		mFillCoords[3] = max;
+		mFillCoords[4] = min;
+		mFillCoords[5] = min;
+		mFillCoords[6] = max;
+		mFillCoords[7] = min;
+
+		shortBuffer = new ShortBuffer[rotateBuffers];
+
+		for (int i = 0; i < rotateBuffers; i++) {
+			ByteBuffer bbuf = ByteBuffer.allocateDirect(MB >> 2)
+					.order(ByteOrder.nativeOrder());
+
+			shortBuffer[i] = bbuf.asShortBuffer();
+			shortBuffer[i].put(mFillCoords, 0, 8);
+		}
+
 		mUpdateTiles = false;
 	}
 
@@ -126,8 +150,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 	static TilesData updateTiles(TilesData tiles) {
 		GLRenderer.tilelock.lock();
 
-		// mCurPosition = mapPosition;
-
 		// unlock previously active tiles
 		for (int i = 0; i < mNextTiles.cnt; i++) {
 			MapTile t = mNextTiles.tiles[i];
@@ -179,7 +201,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 	}
 
 	/**
-	 * called by TileLoader. when tile is removed from cache, reuse its vbo.
+	 * called by TileLoader. when tile is removed from cache reuse its vbo.
 	 * 
 	 * @param vbo
 	 *            the VBO
@@ -214,105 +236,100 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 	private int uploadCnt = 0;
 
 	private boolean uploadTileData(MapTile tile) {
-		ShortBuffer sbuf = null;
+		// Upload line data to vertex buffer object
+		// Log.d(TAG, "uploadTileData, " + tile);
+
+		int lineSize = LineRenderer.sizeOf(tile.lineLayers);
+		int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
+		int newSize = lineSize + polySize;
+
+		if (newSize == 0) {
+			LineRenderer.clear(tile.lineLayers);
+			PolygonRenderer.clear(tile.polygonLayers);
+			tile.lineLayers = null;
+			tile.polygonLayers = null;
+			tile.newData = false;
+			return false;
+		}
+
+		GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
 
 		// use multiple buffers to avoid overwriting buffer while current
 		// data is uploaded (or rather the blocking which is probably done to
-		// avoid this)
+		// avoid overwriting)
 		if (uploadCnt >= rotateBuffers) {
 			uploadCnt = 0;
-			GLES20.glFlush();
+			// GLES20.glFlush();
 		}
 
-		// Upload line data to vertex buffer object
-		synchronized (tile) {
-			if (!tile.newData)
-				return false;
+		ShortBuffer sbuf = shortBuffer[uploadCnt];
 
-			int lineSize = LineRenderer.sizeOf(tile.lineLayers);
-			int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
-			int newSize = lineSize + polySize;
+		// add fill coordinates
+		newSize += 8;
 
-			if (newSize == 0) {
-				LineRenderer.clear(tile.lineLayers);
-				PolygonRenderer.clear(tile.polygonLayers);
-				tile.lineLayers = null;
-				tile.polygonLayers = null;
-				tile.newData = false;
-				return false;
-			}
+		// FIXME probably not a good idea to do this in gl thread...
+		if (sbuf.capacity() < newSize) {
+			ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
+					.order(ByteOrder.nativeOrder());
+			sbuf = bbuf.asShortBuffer();
+			shortBuffer[uploadCnt] = sbuf;
+			sbuf.put(mFillCoords, 0, 8);
+		}
 
-			// Log.d(TAG, "uploadTileData, " + tile);
-			GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
+		sbuf.clear();
+		sbuf.position(8);
 
-			sbuf = shortBuffer[uploadCnt];
+		PolygonRenderer.compileLayerData(tile.polygonLayers, sbuf);
 
-			// add fill coordinates
-			newSize += 8;
+		tile.lineOffset = (8 + polySize);
+		if (tile.lineOffset != sbuf.position())
+			Log.d(TAG, "tiles lineoffset is wrong: " + tile + " "
+					+ tile.lineOffset + " "
+					+ sbuf.position() + " "
+					+ sbuf.limit() + " "
+					+ sbuf.remaining() + " "
+					+ PolygonRenderer.sizeOf(tile.polygonLayers) + " "
+					+ tile.rel);
 
-			// FIXME probably not a good idea to do this in gl thread...
-			if (sbuf == null || sbuf.capacity() < newSize) {
-				ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
-						.order(ByteOrder.nativeOrder());
-				sbuf = bbuf.asShortBuffer();
-				shortBuffer[uploadCnt] = sbuf;
-				sbuf.put(mFillCoords, 0, 8);
-			}
+		tile.lineOffset *= SHORT_BYTES;
 
-			sbuf.clear();
-			sbuf.position(8);
+		LineRenderer.compileLayerData(tile.lineLayers, sbuf);
 
-			PolygonRenderer.compileLayerData(tile.polygonLayers, sbuf);
+		sbuf.flip();
 
-			tile.lineOffset = (8 + polySize);
-			if (tile.lineOffset != sbuf.position())
-				Log.d(TAG, "tiles lineoffset is wrong: " + tile + " "
-						+ tile.lineOffset + " "
-						+ sbuf.position() + " "
-						+ sbuf.limit() + " "
-						+ sbuf.remaining() + " "
-						+ PolygonRenderer.sizeOf(tile.polygonLayers) + " "
-						+ tile.rel);
+		if (newSize != sbuf.remaining()) {
+			Log.d(TAG, "tiles wrong: " + tile + " "
+					+ newSize + " "
+					+ sbuf.position() + " "
+					+ sbuf.limit() + " "
+					+ sbuf.remaining() + " "
+					+ LineRenderer.sizeOf(tile.lineLayers)
+					+ tile.isLoading + " "
+					+ tile.rel);
 
-			tile.lineOffset *= SHORT_BYTES;
-
-			LineRenderer.compileLayerData(tile.lineLayers, sbuf);
-
-			sbuf.flip();
-
-			if (newSize != sbuf.remaining()) {
-				Log.d(TAG, "tiles wrong: " + tile + " "
-						+ newSize + " "
-						+ sbuf.position() + " "
-						+ sbuf.limit() + " "
-						+ sbuf.remaining() + " "
-						+ LineRenderer.sizeOf(tile.lineLayers)
-						+ tile.isLoading + " "
-						+ tile.rel);
-
-				tile.newData = false;
-				return false;
-			}
-			newSize *= SHORT_BYTES;
-
-			// reuse memory allocated for vbo when possible and allocated
-			// memory is less then four times the new data
-			if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
-					&& mBufferMemoryUsage < LIMIT_BUFFERS) {
-				GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
-				// Log.d(TAG, "reuse buffer " + tile.vbo.size + " " + newSize);
-			} else {
-				mBufferMemoryUsage -= tile.vbo.size;
-				tile.vbo.size = newSize;
-				GLES20.glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW);
-				mBufferMemoryUsage += tile.vbo.size;
-			}
-
-			uploadCnt++;
-
-			tile.isReady = true;
 			tile.newData = false;
+			return false;
 		}
+		newSize *= SHORT_BYTES;
+
+		// reuse memory allocated for vbo when possible and allocated
+		// memory is less then four times the new data
+		if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4
+				&& mBufferMemoryUsage < LIMIT_BUFFERS) {
+			GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf);
+			// Log.d(TAG, "reuse buffer " + tile.vbo.size + " " + newSize);
+		} else {
+			mBufferMemoryUsage -= tile.vbo.size;
+			tile.vbo.size = newSize;
+			GLES20.glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW);
+			mBufferMemoryUsage += tile.vbo.size;
+		}
+
+		uploadCnt++;
+
+		tile.isReady = true;
+		tile.newData = false;
+
 		return true;
 	}
 
@@ -451,6 +468,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 	@Override
 	public void onDrawFrame(GL10 glUnused) {
 		long start = 0;
+		// prevent main thread recreating all tiles (updateMap)
+		// while rendering is going. not have seen this happen
+		// yet though
+		GLRenderer.lock.lock();
 
 		if (MapView.debugFrameTime)
 			start = SystemClock.uptimeMillis();
@@ -464,9 +485,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 				| GLES20.GL_DEPTH_BUFFER_BIT
 				| GLES20.GL_STENCIL_BUFFER_BIT);
 
-		// get position and current tiles to draw
-		// mapPosition = mCurPosition;
-
+		// get current tiles to draw
 		if (mUpdateTiles) {
 			GLRenderer.tilelock.lock();
 			TilesData tmp = mDrawTiles;
@@ -476,12 +495,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 			GLRenderer.tilelock.unlock();
 		}
 
-		if (mDrawTiles == null || mDrawTiles.cnt == 0)
+		if (mDrawTiles == null || mDrawTiles.cnt == 0) {
+			GLRenderer.lock.unlock();
 			return;
+		}
 
-		// MapPosition mapPosition =
-		// mMapView.getMapViewPosition().getMapPosition();
-
+		// get current MapPosition, set mTileCoords (mapping of screen to model
+		// coordinates)
 		MapPosition mapPosition = mMapPosition;
 		boolean changed = mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
 
@@ -489,10 +509,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		MapTile[] tiles = mDrawTiles.tiles;
 
 		if (changed) {
+			// get visible tiles
 			for (int i = 0; i < tileCnt; i++)
 				tiles[i].isVisible = false;
 
-			// get relative zoom-level, tiles could not have been updated after
+			// relative zoom-level, 'tiles' could not have been updated after
 			// zoom-level changed.
 			float div = scaleDiv(tiles[0]);
 
@@ -517,8 +538,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		}
 
 		if (mUpdateColor && mClearColor != null) {
-			GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2],
-					mClearColor[3]);
+			GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
 			mUpdateColor = false;
 		}
 
@@ -633,6 +653,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 			GLES20.glFinish();
 			Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
 		}
+		GLRenderer.lock.unlock();
 	}
 
 	// used to not draw a tile twice per frame...
@@ -644,12 +665,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 			return;
 
 		float div = scaleDiv(tile);
-		// float div = 1;
-		// int diff = mapPosition.zoomLevel - tile.zoomLevel;
-		// if (diff < 0)
-		// div = (1 << -diff);
-		// else if (diff > 0)
-		// div = (1.0f / (1 << diff));
 
 		tile.lastDraw = mDrawSerial;
 
@@ -681,21 +696,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 
 			if (pl != null && pnext < lnext) {
 				GLES20.glDisable(GL_BLEND);
-
 				pl = PolygonRenderer.drawPolygons(pl, lnext, mvp, z, s, !clipped);
-
 				clipped = true;
-
 			} else {
-				// XXX nasty
+				// FIXME
 				if (!clipped) {
 					PolygonRenderer.drawPolygons(null, 0, mvp, z, s, true);
 					clipped = true;
 				}
-
 				GLES20.glEnable(GL_BLEND);
-				ll = LineRenderer.drawLines(tile, ll, pnext, mvp, div, z, s,
-						simpleShader);
+				ll = LineRenderer.drawLines(tile, ll, pnext, mvp, div, z, s, simpleShader);
 			}
 		}
 	}
@@ -724,7 +734,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		return drawn == 4;
 	}
 
-	// TODO could use tile.proxies here
 	private static void drawProxyTile(MapTile tile) {
 		int diff = mMapPosition.zoomLevel - tile.zoomLevel;
 
@@ -779,21 +788,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		mWidth = width;
 		mHeight = height;
 
-		// Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
-		// 0.5f, -1, 1);
 		float s = 0.5f;
+		// use this to scale only the view to see which tiles are rendered
+		// s = 1.0f;
 		Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
 				-s * height, s * height, 1, 2);
 		Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
 
-		// Matrix.invertM(mProjMatrixI, 0, mProjMatrix, 0);
-
-		// use this to scale only the view to see which tiles are rendered
-		// s = 1.0f;
-		// Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
-		// -s * height, s * height, 1, 2);
-		// Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
-
 		// set to zero: we modify the z value with polygon-offset for clipping
 		mProjMatrix[10] = 0;
 		mProjMatrix[14] = 0;
@@ -852,21 +853,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
 		String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
 		Log.d(TAG, "Extensions: " + ext);
 
-		shortBuffer = new ShortBuffer[rotateBuffers];
-
-		// add half pixel to tile clip/fill coordinates to avoid rounding issues
-		short min = -4;
-		short max = (short) ((Tile.TILE_SIZE << 3) + 4);
-		mFillCoords = new short[8];
-		mFillCoords[0] = min;
-		mFillCoords[1] = max;
-		mFillCoords[2] = max;
-		mFillCoords[3] = max;
-		mFillCoords[4] = min;
-		mFillCoords[5] = min;
-		mFillCoords[6] = max;
-		mFillCoords[7] = min;
-
 		LineRenderer.init();
 		PolygonRenderer.init();
 		TextRenderer.init();
diff --git a/src/org/oscim/view/renderer/MapRenderer.java b/src/org/oscim/view/renderer/MapRenderer.java
index 6392bb43..9af9416f 100644
--- a/src/org/oscim/view/renderer/MapRenderer.java
+++ b/src/org/oscim/view/renderer/MapRenderer.java
@@ -110,7 +110,7 @@ public class MapRenderer extends GLSurfaceView {
 	 * @param clear
 	 *            whether to clear and reload all tiles
 	 */
-	public synchronized void updateMap(boolean clear) {
+	public void updateMap(boolean clear) {
 		boolean changedPos = false;
 
 		if (mMapView == null)
@@ -124,20 +124,19 @@ public class MapRenderer extends GLSurfaceView {
 		}
 
 		if (clear) {
+			// make sure onDrawFrame is not running
+			GLRenderer.lock.lock();
 			// remove all tiles references
 			Log.d(TAG, "CLEAR");
-
-			GLRenderer.tilelock.lock();
-
 			for (MapTile t : mTiles)
 				clearTile(t);
 
 			mTiles.clear();
 			mTilesLoaded.clear();
 			QuadTree.init();
-			GLRenderer.tilelock.unlock();
-
 			mInitial = true;
+
+			GLRenderer.lock.unlock();
 		}
 
 		if (mInitial) {