- prevent possible concurrency between updateMap 'clear' tiles and onDrawFrame
- no need to sync tile in uploadTileData anymore, now that proxies are locked properly - cleanups
This commit is contained in:
parent
fbc39c65cb
commit
5bf9deef89
@ -97,6 +97,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
// lock to synchronize Main- and GL-Thread
|
// lock to synchronize Main- and GL-Thread
|
||||||
static ReentrantLock tilelock = new ReentrantLock();
|
static ReentrantLock tilelock = new ReentrantLock();
|
||||||
|
static ReentrantLock lock = new ReentrantLock();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mapView
|
* @param mapView
|
||||||
@ -113,6 +114,29 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
Matrix.setIdentityM(mMVPMatrix, 0);
|
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;
|
mUpdateTiles = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,8 +150,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
static TilesData updateTiles(TilesData tiles) {
|
static TilesData updateTiles(TilesData tiles) {
|
||||||
GLRenderer.tilelock.lock();
|
GLRenderer.tilelock.lock();
|
||||||
|
|
||||||
// mCurPosition = mapPosition;
|
|
||||||
|
|
||||||
// unlock previously active tiles
|
// unlock previously active tiles
|
||||||
for (int i = 0; i < mNextTiles.cnt; i++) {
|
for (int i = 0; i < mNextTiles.cnt; i++) {
|
||||||
MapTile t = mNextTiles.tiles[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
|
* @param vbo
|
||||||
* the VBO
|
* the VBO
|
||||||
@ -214,20 +236,8 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
private int uploadCnt = 0;
|
private int uploadCnt = 0;
|
||||||
|
|
||||||
private boolean uploadTileData(MapTile tile) {
|
private boolean uploadTileData(MapTile tile) {
|
||||||
ShortBuffer sbuf = null;
|
|
||||||
|
|
||||||
// use multiple buffers to avoid overwriting buffer while current
|
|
||||||
// data is uploaded (or rather the blocking which is probably done to
|
|
||||||
// avoid this)
|
|
||||||
if (uploadCnt >= rotateBuffers) {
|
|
||||||
uploadCnt = 0;
|
|
||||||
GLES20.glFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upload line data to vertex buffer object
|
// Upload line data to vertex buffer object
|
||||||
synchronized (tile) {
|
// Log.d(TAG, "uploadTileData, " + tile);
|
||||||
if (!tile.newData)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int lineSize = LineRenderer.sizeOf(tile.lineLayers);
|
int lineSize = LineRenderer.sizeOf(tile.lineLayers);
|
||||||
int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
|
int polySize = PolygonRenderer.sizeOf(tile.polygonLayers);
|
||||||
@ -242,16 +252,23 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log.d(TAG, "uploadTileData, " + tile);
|
|
||||||
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
GLES20.glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
|
||||||
|
|
||||||
sbuf = shortBuffer[uploadCnt];
|
// use multiple buffers to avoid overwriting buffer while current
|
||||||
|
// data is uploaded (or rather the blocking which is probably done to
|
||||||
|
// avoid overwriting)
|
||||||
|
if (uploadCnt >= rotateBuffers) {
|
||||||
|
uploadCnt = 0;
|
||||||
|
// GLES20.glFlush();
|
||||||
|
}
|
||||||
|
|
||||||
|
ShortBuffer sbuf = shortBuffer[uploadCnt];
|
||||||
|
|
||||||
// add fill coordinates
|
// add fill coordinates
|
||||||
newSize += 8;
|
newSize += 8;
|
||||||
|
|
||||||
// FIXME probably not a good idea to do this in gl thread...
|
// FIXME probably not a good idea to do this in gl thread...
|
||||||
if (sbuf == null || sbuf.capacity() < newSize) {
|
if (sbuf.capacity() < newSize) {
|
||||||
ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
|
ByteBuffer bbuf = ByteBuffer.allocateDirect(newSize * SHORT_BYTES)
|
||||||
.order(ByteOrder.nativeOrder());
|
.order(ByteOrder.nativeOrder());
|
||||||
sbuf = bbuf.asShortBuffer();
|
sbuf = bbuf.asShortBuffer();
|
||||||
@ -312,7 +329,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
tile.isReady = true;
|
tile.isReady = true;
|
||||||
tile.newData = false;
|
tile.newData = false;
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -451,6 +468,10 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
@Override
|
@Override
|
||||||
public void onDrawFrame(GL10 glUnused) {
|
public void onDrawFrame(GL10 glUnused) {
|
||||||
long start = 0;
|
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)
|
if (MapView.debugFrameTime)
|
||||||
start = SystemClock.uptimeMillis();
|
start = SystemClock.uptimeMillis();
|
||||||
@ -464,9 +485,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
| GLES20.GL_DEPTH_BUFFER_BIT
|
| GLES20.GL_DEPTH_BUFFER_BIT
|
||||||
| GLES20.GL_STENCIL_BUFFER_BIT);
|
| GLES20.GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
// get position and current tiles to draw
|
// get current tiles to draw
|
||||||
// mapPosition = mCurPosition;
|
|
||||||
|
|
||||||
if (mUpdateTiles) {
|
if (mUpdateTiles) {
|
||||||
GLRenderer.tilelock.lock();
|
GLRenderer.tilelock.lock();
|
||||||
TilesData tmp = mDrawTiles;
|
TilesData tmp = mDrawTiles;
|
||||||
@ -476,12 +495,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
GLRenderer.tilelock.unlock();
|
GLRenderer.tilelock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDrawTiles == null || mDrawTiles.cnt == 0)
|
if (mDrawTiles == null || mDrawTiles.cnt == 0) {
|
||||||
|
GLRenderer.lock.unlock();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// MapPosition mapPosition =
|
// get current MapPosition, set mTileCoords (mapping of screen to model
|
||||||
// mMapView.getMapViewPosition().getMapPosition();
|
// coordinates)
|
||||||
|
|
||||||
MapPosition mapPosition = mMapPosition;
|
MapPosition mapPosition = mMapPosition;
|
||||||
boolean changed = mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
boolean changed = mMapViewPosition.getMapPosition(mapPosition, mTileCoords);
|
||||||
|
|
||||||
@ -489,10 +509,11 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
MapTile[] tiles = mDrawTiles.tiles;
|
MapTile[] tiles = mDrawTiles.tiles;
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
// get visible tiles
|
||||||
for (int i = 0; i < tileCnt; i++)
|
for (int i = 0; i < tileCnt; i++)
|
||||||
tiles[i].isVisible = false;
|
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.
|
// zoom-level changed.
|
||||||
float div = scaleDiv(tiles[0]);
|
float div = scaleDiv(tiles[0]);
|
||||||
|
|
||||||
@ -517,8 +538,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mUpdateColor && mClearColor != null) {
|
if (mUpdateColor && mClearColor != null) {
|
||||||
GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2],
|
GLES20.glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], mClearColor[3]);
|
||||||
mClearColor[3]);
|
|
||||||
mUpdateColor = false;
|
mUpdateColor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,6 +653,7 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
GLES20.glFinish();
|
GLES20.glFinish();
|
||||||
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
|
Log.d(TAG, "draw took " + (SystemClock.uptimeMillis() - start));
|
||||||
}
|
}
|
||||||
|
GLRenderer.lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// used to not draw a tile twice per frame...
|
// used to not draw a tile twice per frame...
|
||||||
@ -644,12 +665,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
float div = scaleDiv(tile);
|
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;
|
tile.lastDraw = mDrawSerial;
|
||||||
|
|
||||||
@ -681,21 +696,16 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
|
|
||||||
if (pl != null && pnext < lnext) {
|
if (pl != null && pnext < lnext) {
|
||||||
GLES20.glDisable(GL_BLEND);
|
GLES20.glDisable(GL_BLEND);
|
||||||
|
|
||||||
pl = PolygonRenderer.drawPolygons(pl, lnext, mvp, z, s, !clipped);
|
pl = PolygonRenderer.drawPolygons(pl, lnext, mvp, z, s, !clipped);
|
||||||
|
|
||||||
clipped = true;
|
clipped = true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// XXX nasty
|
// FIXME
|
||||||
if (!clipped) {
|
if (!clipped) {
|
||||||
PolygonRenderer.drawPolygons(null, 0, mvp, z, s, true);
|
PolygonRenderer.drawPolygons(null, 0, mvp, z, s, true);
|
||||||
clipped = true;
|
clipped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLES20.glEnable(GL_BLEND);
|
GLES20.glEnable(GL_BLEND);
|
||||||
ll = LineRenderer.drawLines(tile, ll, pnext, mvp, div, z, s,
|
ll = LineRenderer.drawLines(tile, ll, pnext, mvp, div, z, s, simpleShader);
|
||||||
simpleShader);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -724,7 +734,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
return drawn == 4;
|
return drawn == 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO could use tile.proxies here
|
|
||||||
private static void drawProxyTile(MapTile tile) {
|
private static void drawProxyTile(MapTile tile) {
|
||||||
int diff = mMapPosition.zoomLevel - tile.zoomLevel;
|
int diff = mMapPosition.zoomLevel - tile.zoomLevel;
|
||||||
|
|
||||||
@ -779,21 +788,13 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
mWidth = width;
|
mWidth = width;
|
||||||
mHeight = height;
|
mHeight = height;
|
||||||
|
|
||||||
// Matrix.orthoM(mProjMatrix, 0, -0.5f / mAspect, 0.5f / mAspect, -0.5f,
|
|
||||||
// 0.5f, -1, 1);
|
|
||||||
float s = 0.5f;
|
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,
|
Matrix.frustumM(mProjMatrix, 0, -s * width, s * width,
|
||||||
-s * height, s * height, 1, 2);
|
-s * height, s * height, 1, 2);
|
||||||
Matrix.translateM(mProjMatrix, 0, 0, 0, -1);
|
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
|
// set to zero: we modify the z value with polygon-offset for clipping
|
||||||
mProjMatrix[10] = 0;
|
mProjMatrix[10] = 0;
|
||||||
mProjMatrix[14] = 0;
|
mProjMatrix[14] = 0;
|
||||||
@ -852,21 +853,6 @@ public class GLRenderer implements GLSurfaceView.Renderer {
|
|||||||
String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
String ext = GLES20.glGetString(GLES20.GL_EXTENSIONS);
|
||||||
Log.d(TAG, "Extensions: " + ext);
|
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();
|
LineRenderer.init();
|
||||||
PolygonRenderer.init();
|
PolygonRenderer.init();
|
||||||
TextRenderer.init();
|
TextRenderer.init();
|
||||||
|
@ -110,7 +110,7 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
* @param clear
|
* @param clear
|
||||||
* whether to clear and reload all tiles
|
* whether to clear and reload all tiles
|
||||||
*/
|
*/
|
||||||
public synchronized void updateMap(boolean clear) {
|
public void updateMap(boolean clear) {
|
||||||
boolean changedPos = false;
|
boolean changedPos = false;
|
||||||
|
|
||||||
if (mMapView == null)
|
if (mMapView == null)
|
||||||
@ -124,20 +124,19 @@ public class MapRenderer extends GLSurfaceView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (clear) {
|
if (clear) {
|
||||||
|
// make sure onDrawFrame is not running
|
||||||
|
GLRenderer.lock.lock();
|
||||||
// remove all tiles references
|
// remove all tiles references
|
||||||
Log.d(TAG, "CLEAR");
|
Log.d(TAG, "CLEAR");
|
||||||
|
|
||||||
GLRenderer.tilelock.lock();
|
|
||||||
|
|
||||||
for (MapTile t : mTiles)
|
for (MapTile t : mTiles)
|
||||||
clearTile(t);
|
clearTile(t);
|
||||||
|
|
||||||
mTiles.clear();
|
mTiles.clear();
|
||||||
mTilesLoaded.clear();
|
mTilesLoaded.clear();
|
||||||
QuadTree.init();
|
QuadTree.init();
|
||||||
GLRenderer.tilelock.unlock();
|
|
||||||
|
|
||||||
mInitial = true;
|
mInitial = true;
|
||||||
|
|
||||||
|
GLRenderer.lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mInitial) {
|
if (mInitial) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user