- fix adding vbo id twice to pool. null tile.vbo in clear. phew

- improve depth buffer clipping, no more overlapping of polygons
  and use it to clip proxy tiles too
- simplify limitCache function
- linelayers, dont use systemarraycopy for small arrays
This commit is contained in:
Hannes Janetzek 2012-08-29 10:45:19 +02:00
parent ba90664ee2
commit 91ba202082
7 changed files with 644 additions and 463 deletions

View File

@ -94,7 +94,7 @@ public class MapView extends GLSurfaceView {
private IMapRenderer mMapRenderer; private IMapRenderer mMapRenderer;
private JobQueue mJobQueue; private JobQueue mJobQueue;
private MapWorker mMapWorkers[]; private MapWorker mMapWorkers[];
private int mNumMapWorkers = 6; private int mNumMapWorkers = 4;
private JobParameters mJobParameters; private JobParameters mJobParameters;
public DebugSettings debugSettings; public DebugSettings debugSettings;
private String mMapFile; private String mMapFile;

View File

@ -35,9 +35,11 @@ class LineLayer {
ShortItem pool; ShortItem pool;
protected ShortItem curItem; protected ShortItem curItem;
// number of vertices this layer holds
int verticesCnt; int verticesCnt;
// vertices offset of this layer in VBO
int offset; int offset;
short[] mVertex;
LineLayer(int layer, Line line, float width, boolean outline) { LineLayer(int layer, Line line, float width, boolean outline) {
this.layer = layer; this.layer = layer;
@ -55,57 +57,14 @@ class LineLayer {
outlines = link; outlines = link;
} }
private static ShortItem addTwoVertex(short[] vertex, ShortItem item) {
ShortItem it = item;
if (it.used + 6 >= ShortItem.SIZE) {
if (it.used == ShortItem.SIZE) {
it.next = ShortPool.get();
it = it.next;
} else {
System.arraycopy(vertex, 0, it.vertices, it.used, 6);
it.used += 6;
it.next = ShortPool.get();
it = it.next;
System.arraycopy(vertex, 6, it.vertices, it.used, 6);
it.used += 6;
return it;
}
}
System.arraycopy(vertex, 0, it.vertices, it.used, 12);
it.used += 12;
return it;
}
private static ShortItem addVertex(short[] vertex, ShortItem item) {
ShortItem it = item;
if (it.used == ShortItem.SIZE) {
it.next = ShortPool.get();
it = it.next;
}
System.arraycopy(vertex, 0, it.vertices, it.used, 6);
it.used += 6;
return it;
}
/* /*
* line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj -- need some way to know * line extrusion is based on code from GLMap (https://github.com/olofsj/GLMap/) by olofsj -- need some way to know
* how the road connects to set the ending angles * how the road connects to set the ending angles
*/ */
void addLine(float[] pointArray, int pos, int length) { void addLine(float[] points, int pos, int length) {
float x, y, nextX, nextY, prevX, prevY, ux, uy, vx, vy, wx, wy; float x, y, nextX, nextY, prevX, prevY, ux, uy, vx, vy, wx, wy;
float a; float a;
int pointPos = pos; int ipos = pos;
boolean rounded = false; boolean rounded = false;
boolean squared = false; boolean squared = false;
@ -114,23 +73,14 @@ class LineLayer {
else if (line.cap == Cap.SQUARE) else if (line.cap == Cap.SQUARE)
squared = true; squared = true;
if (pool == null) {
curItem = ShortPool.get();
pool = curItem;
mVertex = new short[12];
}
// amount of vertices used // amount of vertices used
verticesCnt += length + (rounded ? 6 : 2); verticesCnt += length + (rounded ? 6 : 2);
ShortItem si = curItem; x = points[ipos++];
y = points[ipos++];
x = pointArray[pointPos++]; nextX = points[ipos++];
y = pointArray[pointPos++]; nextY = points[ipos++];
nextX = pointArray[pointPos++];
nextY = pointArray[pointPos++];
// Calculate triangle corners for the given width // Calculate triangle corners for the given width
vx = nextX - x; vx = nextX - x;
@ -144,47 +94,116 @@ class LineLayer {
ux = -vy; ux = -vy;
uy = vx; uy = vx;
float uxw = ux;
float uyw = uy;
float vxw = vx;
float vyw = vy;
int tsize = Tile.TILE_SIZE; int tsize = Tile.TILE_SIZE;
short v[] = mVertex; if (pool == null) {
pool = curItem = ShortPool.get();
}
v[0] = (short) (x * S); ShortItem si = curItem;
v[1] = (short) (y * S); short v[] = si.vertices;
int opos = si.used;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
boolean outside = (x <= 0 || x >= tsize || y <= 0 || y >= tsize) boolean outside = (x <= 0 || x >= tsize || y <= 0 || y >= tsize)
&& (x - vxw <= 0 || x - vxw >= tsize || y - vyw <= 0 || y - vyw >= tsize); && (x - vx <= 0 || x - vx >= tsize || y - vy <= 0 || y - vy >= tsize);
short ox, oy, dx, dy;
ox = (short) (x * S);
oy = (short) (y * S);
if (rounded && !outside) { if (rounded && !outside) {
v[2] = (short) ((uxw - vxw) * S1000);
v[3] = (short) ((uyw - vyw) * S1000);
v[4] = -1;
v[5] = 1;
si = addVertex(v, si);
si = addVertex(v, si);
v[2] = (short) (-(uxw + vxw) * S1000); // For rounded line edges
v[3] = (short) (-(uyw + vyw) * S1000); dx = (short) ((ux - vx) * S1000);
v[4] = 1; dy = (short) ((uy - vy) * S1000);
v[5] = 1;
si = addVertex(v, si); v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = -1;
v[opos + 5] = 1;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = -1;
v[opos + 5] = 1;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
dx = (short) (-(ux + vx) * S1000);
dy = (short) (-(uy + vy) * S1000);
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = 1;
v[opos + 5] = 1;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
// Start of line // Start of line
v[2] = (short) ((uxw) * S1000); dx = (short) (ux * S1000);
v[3] = (short) ((uyw) * S1000); dy = (short) (uy * S1000);
v[4] = -1;
v[5] = 0;
si = addVertex(v, si);
v[2] = (short) ((-uxw) * S1000); v[opos + 0] = ox;
v[3] = (short) ((-uyw) * S1000); v[opos + 1] = oy;
v[4] = 1; v[opos + 2] = dx;
v[5] = 0; v[opos + 3] = dy;
si = addVertex(v, si); v[opos + 4] = -1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = (short) (-dx);
v[opos + 3] = (short) (-dy);
v[opos + 4] = 1;
v[opos + 5] = 0;
opos += 6;
} else { } else {
// outside means line is probably clipped // outside means line is probably clipped
@ -192,29 +211,61 @@ class LineLayer {
// for now, just extend the line a little // for now, just extend the line a little
if (squared) { if (squared) {
vxw = 0; vx = 0;
vyw = 0; vy = 0;
} else if (!outside) { } else if (!outside) {
vxw *= 0.5; vx *= 0.5;
vyw *= 0.5; vy *= 0.5;
} }
if (rounded) if (rounded)
verticesCnt -= 2; verticesCnt -= 2;
// Add the first point twice to be able to draw with GL_TRIANGLE_STRIP dx = (short) ((ux - vx) * S1000);
v[2] = (short) ((uxw - vxw) * S1000); dy = (short) ((uy - vy) * S1000);
v[3] = (short) ((uyw - vyw) * S1000);
v[4] = -1;
v[5] = 0;
si = addVertex(v, si);
si = addVertex(v, si);
v[2] = (short) (-(uxw + vxw) * S1000); v[opos + 0] = ox;
v[3] = (short) (-(uyw + vyw) * S1000); v[opos + 1] = oy;
v[4] = 1; v[opos + 2] = dx;
v[5] = 0; v[opos + 3] = dy;
si = addVertex(v, si); v[opos + 4] = -1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = -1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
dx = (short) (-(ux + vx) * S1000);
dy = (short) (-(uy + vy) * S1000);
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = 1;
v[opos + 5] = 0;
opos += 6;
} }
prevX = x; prevX = x;
@ -222,9 +273,9 @@ class LineLayer {
x = nextX; x = nextX;
y = nextY; y = nextY;
for (; pointPos < pos + length;) { for (; ipos < pos + length;) {
nextX = pointArray[pointPos++]; nextX = points[ipos++];
nextY = pointArray[pointPos++]; nextY = points[ipos++];
// Unit vector pointing back to previous node // Unit vector pointing back to previous node
vx = prevX - x; vx = prevX - x;
@ -261,22 +312,43 @@ class LineLayer {
} }
} }
uxw = ux * S1000; if (opos == ShortItem.SIZE) {
uyw = uy * S1000; si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[6] = v[0] = (short) (x * S); ox = (short) (x * S);
v[7] = v[1] = (short) (y * S); oy = (short) (y * S);
v[2] = (short) uxw; dx = (short) (ux * S1000);
v[3] = (short) uyw; dy = (short) (uy * S1000);
v[4] = -1;
v[5] = 0;
v[8] = (short) -uxw; v[opos + 0] = ox;
v[9] = (short) -uyw; v[opos + 1] = oy;
v[10] = 1; v[opos + 2] = dx;
v[11] = 0; v[opos + 3] = dy;
si = addTwoVertex(v, si); v[opos + 4] = -1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = (short) -dx;
v[opos + 3] = (short) -dy;
v[opos + 4] = 1;
v[opos + 5] = 0;
opos += 6;
prevX = x; prevX = x;
prevY = y; prevY = y;
@ -295,71 +367,164 @@ class LineLayer {
ux = vy; ux = vy;
uy = -vx; uy = -vx;
uxw = ux;
uyw = uy;
vxw = vx;
vyw = vy;
outside = (x <= 0 || x >= tsize || y <= 0 || y >= tsize) outside = (x <= 0 || x >= tsize || y <= 0 || y >= tsize)
&& (x - vxw <= 0 || x - vxw >= tsize || y - vyw <= 0 || y - vyw >= tsize); && (x - vx <= 0 || x - vx >= tsize || y - vy <= 0 || y - vy >= tsize);
v[0] = (short) (x * S); if (opos == ShortItem.SIZE) {
v[1] = (short) (y * S); si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
ox = (short) (x * S);
oy = (short) (y * S);
if (rounded && !outside) { if (rounded && !outside) {
v[2] = (short) ((uxw) * S1000);
v[3] = (short) ((uyw) * S1000);
v[4] = -1;
v[5] = 0;
si = addVertex(v, si);
v[2] = (short) ((-uxw) * S1000); dx = (short) (ux * S1000);
v[3] = (short) ((-uyw) * S1000); dy = (short) (uy * S1000);
v[4] = 1;
v[5] = 0; v[opos + 0] = ox;
si = addVertex(v, si); v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = -1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = (short) -dx;
v[opos + 3] = (short) -dy;
v[opos + 4] = 1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
// For rounded line edges // For rounded line edges
v[2] = (short) ((uxw - vxw) * S1000); dx = (short) ((ux - vx) * S1000);
v[3] = (short) ((uyw - vyw) * S1000); dy = (short) ((uy - vy) * S1000);
v[4] = -1;
v[5] = -1;
si = addVertex(v, si);
v[2] = (short) (-(uxw + vxw) * S1000); v[opos + 0] = ox;
v[3] = (short) (-(uyw + vyw) * S1000); v[opos + 1] = oy;
v[4] = 1; v[opos + 2] = dx;
v[5] = -1; v[opos + 3] = dy;
si = addVertex(v, si); v[opos + 4] = -1;
si = addVertex(v, si); v[opos + 5] = -1;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
dx = (short) (-(ux + vx) * S1000);
dy = (short) (-(uy + vy) * S1000);
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = 1;
v[opos + 5] = -1;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = 1;
v[opos + 5] = -1;
opos += 6;
} else { } else {
if (squared) { if (squared) {
vxw = 0; vx = 0;
vyw = 0; vy = 0;
} else if (!outside) { } else if (!outside) {
vxw *= 0.5; vx *= 0.5;
vyw *= 0.5; vy *= 0.5;
} }
if (rounded) if (rounded)
verticesCnt -= 2; verticesCnt -= 2;
v[2] = (short) ((uxw) * S1000); dx = (short) ((ux - vx) * S1000);
v[3] = (short) ((uyw) * S1000); dy = (short) ((uy - vy) * S1000);
v[4] = -1;
v[5] = 0;
si = addVertex(v, si);
v[2] = (short) (-(uxw + vxw) * S1000); v[opos + 0] = ox;
v[3] = (short) (-(uyw + vyw) * S1000); v[opos + 1] = oy;
v[4] = 1; v[opos + 2] = dx;
v[5] = 0; v[opos + 3] = dy;
si = addVertex(v, si); v[opos + 4] = -1;
si = addVertex(v, si); v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
} }
dx = (short) (-(ux + vx) * S1000);
dy = (short) (-(uy + vy) * S1000);
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = 1;
v[opos + 5] = 0;
opos += 6;
if (opos == ShortItem.SIZE) {
si.used = ShortItem.SIZE;
si.next = ShortPool.get();
si = si.next;
opos = 0;
v = si.vertices;
}
v[opos + 0] = ox;
v[opos + 1] = oy;
v[opos + 2] = dx;
v[opos + 3] = dy;
v[opos + 4] = 1;
v[opos + 5] = 0;
opos += 6;
}
si.used = opos;
curItem = si; curItem = si;
} }
} }

View File

@ -511,6 +511,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas
PolygonLayers.clear(mPolyLayers); PolygonLayers.clear(mPolyLayers);
mLineLayers = null; mLineLayers = null;
mPolyLayers = null; mPolyLayers = null;
mLabels = null;
tile.isLoading = false; tile.isLoading = false;
return false; return false;
} }

View File

@ -85,6 +85,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
private final MapView mMapView; private final MapView mMapView;
private static ArrayList<MapGeneratorJob> mJobList; private static ArrayList<MapGeneratorJob> mJobList;
private static ArrayList<VertexBufferObject> mVBOs; private static ArrayList<VertexBufferObject> mVBOs;
private static TileCacheKey mTileCacheKey; private static TileCacheKey mTileCacheKey;
private static HashMap<TileCacheKey, GLMapTile> mTiles; private static HashMap<TileCacheKey, GLMapTile> mTiles;
@ -152,6 +153,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
@Override @Override
public void setRenderTheme(RenderTheme t) { public void setRenderTheme(RenderTheme t) {
int bg = t.getMapBackground(); int bg = t.getMapBackground();
Log.d(TAG, "BG" + bg);
float[] c = new float[4]; float[] c = new float[4];
c[0] = (bg >> 16 & 0xff) / 255.0f; c[0] = (bg >> 16 & 0xff) / 255.0f;
c[1] = (bg >> 8 & 0xff) / 255.0f; c[1] = (bg >> 8 & 0xff) / 255.0f;
@ -246,78 +248,56 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return false; return false;
} }
private static void limitCache(int remove) { private static boolean tileInUse(GLMapTile t) {
byte z = mLastZoom; byte z = mLastZoom;
// Log.d(TAG, "--------------------------------");
if (t.zoomLevel == z + 1) {
if (t.parent != null
&& t.parent.isActive
&& !(t.parent.isReady || t.parent.newData))
return true;
} else if (t.zoomLevel == z - 1) {
if (childIsActive(t))
return true;
} else if (t.zoomLevel == z - 2) {
for (int i = 0; i < 4; i++) {
if (t.child[i] != null && childIsActive(t.child[i]))
return true;
}
}
return false;
}
private static void limitCache(int remove) {
for (int j = mTileList.size() - 1, cnt = 0; cnt < remove && j > 0; j--) { for (int j = mTileList.size() - 1, cnt = 0; cnt < remove && j > 0; j--) {
GLMapTile t = mTileList.remove(j); GLMapTile t = mTileList.remove(j);
synchronized (t) {
// dont remove tile used by renderthread or mapgenerator // dont remove tile used by renderthread or mapgenerator
// FIXME set tile loading state in main thread // FIXME set tile loading state in main thread
if (t.isLoading) { // if (t.isLoading) {
// Log.d(TAG, "cancel loading " + t + " " + (t.zoomLevel - mCurZ)
Log.d(TAG, "cancel loading " + t + " " + (t.zoomLevel - mCurZ) // + " " + (t.zoomLevel - mDrawZ) + " " + t.distance);
+ " " + (t.zoomLevel - mDrawZ) + " " + t.distance); // t.isCanceled = true;
t.isCanceled = true; // }
} // else
else if (t.isActive) { if (t.isActive || t.isLoading) {
Log.d(TAG, "EEEK removing active " + t + " " + (t.zoomLevel - mCurZ) Log.d(TAG, "EEEK removing active " + t + " " + (t.zoomLevel - mCurZ)
+ " " + (t.zoomLevel - mDrawZ) + " " + t.distance); + " " + (t.zoomLevel - mDrawZ) + " " + t.distance);
mTileList.add(t); mTileList.add(t);
continue; continue;
} } else if (t.isReady || t.newData) {
// check if this tile is used as proxy for not yet drawn active tile // check if this tile is used as proxy for not yet drawn active tile
// TODO to be simplified...
else if (t.isReady || t.newData) {
if (t.zoomLevel == z + 1) {
if (t.parent != null && t.parent.isActive
&& !(t.parent.isReady || t.parent.newData)) {
mTileList.add(t);
Log.d(TAG, "EEEK removing active proxy child");
continue;
}
} else if (t.zoomLevel == z - 1) {
GLMapTile c = null;
for (int i = 0; i < 4; i++) {
c = t.child[i];
if (c != null && c.isActive && !(c.isReady || c.newData))
break;
c = null;
}
if (c != null) { if (tileInUse(t)) {
Log.d(TAG, "EEEK removing active proxy parent"); Log.d(TAG, "X removing proxy: " + t);
mTileList.add(t);
continue;
}
} else if (t.zoomLevel == z - 2) {
GLMapTile c = null, c2 = null;
for (int i = 0; i < 4; i++) {
c = t.child[i];
if (c != null) {
for (int k = 0; k < 4; k++) {
c2 = c.child[k];
if (c2 != null && c2.isActive
&& !(c2.isReady || c2.newData))
break;
c2 = null;
}
if (c2 != null)
break;
}
c = null;
}
if (c != null) {
// Log.d(TAG, "EEEK removing active second level proxy parent");
mTileList.add(t); mTileList.add(t);
continue; continue;
} }
} }
}
// Log.d(TAG, ">>> remove " + t + " " + (t.zoomLevel - mCurZ)
// + " " + t.distance);
cnt++; cnt++;
mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel); mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel);
@ -337,12 +317,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
} }
} }
synchronized (mVBOs) {
clearTile(t); clearTile(t);
} }
} }
// Log.d(TAG, "--------------------------------<<");
} }
private boolean updateVisibleList(double x, double y, int zdir) { private boolean updateVisibleList(double x, double y, int zdir) {
@ -370,27 +347,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return false; return false;
int max = newTiles.tiles.length - 1; int max = newTiles.tiles.length - 1;
long limit = (long) Math.pow(2, zoomLevel) - 1; long limit = (long) Math.pow(2, zoomLevel);
if (tileTop < 0) if (tileTop < 0)
tileTop = 0; tileTop = 0;
if (tileLeft < 0) if (tileLeft < 0)
tileLeft = 0; tileLeft = 0;
if (tileBottom >= limit) if (tileBottom >= limit)
tileBottom = limit; tileBottom = limit - 1;
if (tileRight >= limit) if (tileRight >= limit)
tileRight = limit; tileRight = limit - 1;
for (long tileY = tileTop; tileY <= tileBottom; tileY++) { for (long yy = tileTop; yy <= tileBottom; yy++) {
for (long tileX = tileLeft; tileX <= tileRight; tileX++) { for (long xx = tileLeft; xx <= tileRight; xx++) {
// FIXME // FIXME
if (tiles == max) if (tiles == max)
break; break;
GLMapTile tile = mTiles.get(mTileCacheKey.set(tileX, tileY, zoomLevel)); long tx = xx;// % limit;
GLMapTile tile = mTiles.get(mTileCacheKey.set(tx, yy, zoomLevel));
if (tile == null) { if (tile == null) {
tile = new GLMapTile(tileX, tileY, zoomLevel); tile = new GLMapTile(tx, yy, zoomLevel);
TileCacheKey key = new TileCacheKey(mTileCacheKey); TileCacheKey key = new TileCacheKey(mTileCacheKey);
// FIXME use sparse matrix or sth. // FIXME use sparse matrix or sth.
@ -399,15 +378,15 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
Log.d(TAG, "eeek collision"); Log.d(TAG, "eeek collision");
mTileList.add(tile); mTileList.add(tile);
mTileCacheKey.set((tileX >> 1), (tileY >> 1), (byte) (zoomLevel - 1)); mTileCacheKey.set((tx >> 1), (yy >> 1), (byte) (zoomLevel - 1));
tile.parent = mTiles.get(mTileCacheKey); tile.parent = mTiles.get(mTileCacheKey);
int idx = (int) ((tileX & 0x01) + 2 * (tileY & 0x01)); int idx = (int) ((tx & 0x01) + 2 * (yy & 0x01));
// set this tile to be child of its parent // set this tile to be child of its parent
if (tile.parent != null) { if (tile.parent != null) {
tile.parent.child[idx] = tile; tile.parent.child[idx] = tile;
} else if (zdir > 0 && zoomLevel > 0) { } else if (zdir > 0 && zoomLevel > 0) {
tile.parent = new GLMapTile(tileX >> 1, tileY >> 1, tile.parent = new GLMapTile(tx >> 1, yy >> 1,
(byte) (zoomLevel - 1)); (byte) (zoomLevel - 1));
key = new TileCacheKey(mTileCacheKey); key = new TileCacheKey(mTileCacheKey);
if (mTiles.put(key, tile.parent) != null) if (mTiles.put(key, tile.parent) != null)
@ -436,6 +415,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
MapGeneratorJob job = new MapGeneratorJob(tile.parent, MapGeneratorJob job = new MapGeneratorJob(tile.parent,
mJobParameter, mJobParameter,
mDebugSettings); mDebugSettings);
if (!mJobList.contains(job)) if (!mJobList.contains(job))
mJobList.add(job); mJobList.add(job);
} }
@ -443,19 +423,10 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
} }
// scramble tile draw order: might help to make gl
// pipelines more independent... just a guess :)
// for (int i = 1; i < tiles / 2; i += 2) {
// GLMapTile tmp = newTiles.tiles[i];
// newTiles.tiles[i] = newTiles.tiles[tiles - i];
// newTiles.tiles[tiles - i] = tmp;
// }
newTiles.cnt = tiles; newTiles.cnt = tiles;
// pass new tile list to glThread // pass new tile list to glThread
synchronized (this) { synchronized (this) {
for (int i = 0; i < curTiles.cnt; i++) { for (int i = 0; i < curTiles.cnt; i++) {
boolean found = false; boolean found = false;
@ -467,18 +438,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (curTiles.tiles[i] == newTiles.tiles[j]) if (curTiles.tiles[i] == newTiles.tiles[j])
found = true; found = true;
if (!found) { if (!found)
curTiles.tiles[i].isActive = false; curTiles.tiles[i].isActive = false;
// activeList.remove(newTiles.tiles[i]);
}
} }
for (int i = 0; i < tiles; i++) { for (int i = 0; i < tiles; i++)
if (!newTiles.tiles[i].isActive) {
newTiles.tiles[i].isActive = true; newTiles.tiles[i].isActive = true;
// activeList.add(newTiles.tiles[i]);
}
}
TilesData tmp = curTiles; TilesData tmp = curTiles;
curTiles = newTiles; curTiles = newTiles;
@ -493,19 +458,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mUpdateTiles = true; mUpdateTiles = true;
} }
// see FIXME in passTile
// synchronized (mTiles) {
updateTileDistances(); updateTileDistances();
// }
if (mJobList.size() > 0) if (mJobList.size() > 0)
mMapView.addJobs(mJobList); mMapView.addJobs(mJobList);
int removes = mTiles.size() - CACHE_TILES; int removes = mTiles.size() - CACHE_TILES;
if (removes > 20) { if (removes > 10) {
// Log.d(TAG, "---- remove " + removes + " on " + zoomLevel + " active:"
// + active + "------");
Collections.sort(mTileList, mTileDistanceSort); Collections.sort(mTileList, mTileDistanceSort);
limitCache(removes); limitCache(removes);
} }
@ -534,18 +494,23 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
private static void clearTile(GLMapTile t) { private static void clearTile(GLMapTile t) {
t.newData = false;
t.isLoading = false;
t.isReady = false;
LineLayers.clear(t.lineLayers); LineLayers.clear(t.lineLayers);
PolygonLayers.clear(t.polygonLayers); PolygonLayers.clear(t.polygonLayers);
if (t.vbo != null)
mVBOs.add(t.vbo);
t.labels = null; t.labels = null;
t.lineLayers = null; t.lineLayers = null;
t.polygonLayers = null; t.polygonLayers = null;
t.newData = false;
t.isLoading = false; if (t.vbo != null) {
t.isReady = false; synchronized (mVBOs) {
mVBOs.add(t.vbo);
}
}
t.vbo = null;
} }
/** /**
@ -624,6 +589,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
mCurY = y; mCurY = y;
mCurZ = zoomLevel; mCurZ = zoomLevel;
mCurScale = scale; mCurScale = scale;
// Log.d(TAG, "draw at:" + tileX + " " + tileY + " " + mCurX + " " + mCurY
// + " " + mCurZ);
} }
} }
@ -632,25 +599,13 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (changedPos) if (changedPos)
updateVisibleList(x, y, zdir); updateVisibleList(x, y, zdir);
}
private static final int MAX_TILES_IN_QUEUE = 40;
/**
* called by MapWorkers when tile is loaded
*/
@Override
public synchronized boolean passTile(MapGeneratorJob mapGeneratorJob) {
GLMapTile tile = (GLMapTile) mapGeneratorJob.tile;
if (tile.isCanceled) {
Log.d(TAG, "passTile: canceld " + tile);
clearTile(tile);
return true;
}
int size = mTilesLoaded.size(); int size = mTilesLoaded.size();
if (size > MAX_TILES_IN_QUEUE) { if (size < MAX_TILES_IN_QUEUE)
return;
synchronized (mTilesLoaded) {
// remove uploaded tiles // remove uploaded tiles
for (int i = 0; i < size;) { for (int i = 0; i < size;) {
GLMapTile t = mTilesLoaded.get(i); GLMapTile t = mTilesLoaded.get(i);
@ -663,40 +618,53 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
i++; i++;
} }
if (size > MAX_TILES_IN_QUEUE) {
// FIXME pass tile via queue back to mainloop instead...
// synchronized (mTiles) {
// Collections.sort(mTilesLoaded, mTileDistanceSort);
// }
// clear loaded but not used tiles // clear loaded but not used tiles
while (size-- > MAX_TILES_IN_QUEUE) { if (size > MAX_TILES_IN_QUEUE) {
while (size-- > MAX_TILES_IN_QUEUE - 20) {
GLMapTile t = mTilesLoaded.get(size); GLMapTile t = mTilesLoaded.get(size);
// FIXME race condition: tile could be uploaded as proxy
// therefore sync with upload tile data synchronized (t) {
// synchronized (t) { if (tileInUse(t)) {
// dont remove tile if currently used or is direct parent Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive);
// or child of currently active tile
if (t.isActive || childIsActive(t) ||
(tile.parent != null && tile.parent.isActive)) {
// Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive);
continue; continue;
} }
mTilesLoaded.remove(size); mTilesLoaded.remove(size);
// Log.d(TAG, "remove unused tile data: " + t); Log.d(TAG, "remove unused tile data: " + t);
clearTile(t); clearTile(t);
// TODO could also remove from mTileHash/List ? }
}
}
}
}
private static final int MAX_TILES_IN_QUEUE = 40;
/**
* called by MapWorkers when tile is loaded
*/
@Override
public synchronized boolean passTile(MapGeneratorJob mapGeneratorJob) {
GLMapTile tile = (GLMapTile) mapGeneratorJob.tile;
// if (tile.isCanceled) {
// // no one should be able to use this tile now, mapgenerator passed it,
// // glthread does nothing until newdata is set.
// Log.d(TAG, "passTile: canceled " + tile);
// clearTile(tile);
// return true;
// } // }
}
}
}
tile.newData = true; tile.newData = true;
tile.isLoading = false; tile.isLoading = false;
mTilesLoaded.add(0, tile);
if (!timing) if (!timing)
mMapView.requestRender(); mMapView.requestRender();
synchronized (mTilesLoaded) {
mTilesLoaded.add(0, tile);
}
return true; return true;
} }
@ -754,10 +722,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
// Upload line data to vertex buffer object // Upload line data to vertex buffer object
synchronized (tile) {
if (!tile.newData)
return false;
// FIXME do this in main thread:
if (tile.vbo == null) {
synchronized (mVBOs) { synchronized (mVBOs) {
if (tile.vbo == null) {
if (mVBOs.size() < 1) { if (mVBOs.size() < 1) {
Log.d(TAG, "uploadTileData, no VBOs left"); Log.d(TAG, "uploadTileData, no VBOs left");
return false; return false;
@ -766,14 +736,6 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
} }
// synchronized (tile) {
if (!tile.newData)
return false;
tile.isReady = true;
tile.newData = false;
// }
int lineSize = LineLayers.sizeOf(tile.lineLayers); int lineSize = LineLayers.sizeOf(tile.lineLayers);
int polySize = PolygonLayers.sizeOf(tile.polygonLayers); int polySize = PolygonLayers.sizeOf(tile.polygonLayers);
int newSize = lineSize + polySize; int newSize = lineSize + polySize;
@ -786,7 +748,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
return false; return false;
} }
// Log.d(TAG, "uploadTileData, " + tile); Log.d(TAG, "uploadTileData, " + tile);
glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id); glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id);
@ -827,23 +789,23 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
uploadCnt++; uploadCnt++;
tile.isReady = true;
tile.newData = false;
}
return true; return true;
} }
private float[] mClearColor; private float[] mClearColor = null;
private static long mRedrawCnt = 0; private static long mRedrawCnt = 0;
@Override @Override
public void onDrawFrame(GL10 glUnused) { public void onDrawFrame(GL10 glUnused) {
long start = 0, poly_time = 0, clear_time = 0; long start = 0, poly_time = 0, clear_time = 0;
if (mClearColor != null) { glClear(GLES20.GL_COLOR_BUFFER_BIT
glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], | GLES20.GL_DEPTH_BUFFER_BIT
mClearColor[3]); // | GLES20.GL_STENCIL_BUFFER_BIT
mClearColor = null; );
}
glClear(GLES20.GL_COLOR_BUFFER_BIT);// | GLES20.GL_DEPTH_BUFFER_BIT);
if (mInitial) if (mInitial)
return; return;
@ -903,8 +865,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (!setTileScissor(tile, 1)) if (!setTileScissor(tile, 1))
continue; continue;
if (updateTextures < 4 && tile.texture == null if (tile.texture == null && TextRenderer.drawToTexture(tile))
&& TextRenderer.drawToTexture(tile))
updateTextures++; updateTextures++;
if (tile.newData) { if (tile.newData) {
@ -930,8 +891,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (updateTextures > 0) { if (updateTextures > 0) {
TextRenderer.compileTextures(); TextRenderer.compileTextures();
if (updateTextures == 4) // if (updateTextures == 4)
mMapView.requestRender(); // mMapView.requestRender();
} }
// if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage) // if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage)
// && LIMIT_BUFFERS > MB) // && LIMIT_BUFFERS > MB)
@ -941,18 +902,25 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
clear_time = (SystemClock.uptimeMillis() - start); clear_time = (SystemClock.uptimeMillis() - start);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
for (int i = 0; i < tileCnt; i++) { glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
if (tiles[i].isVisible && !tiles[i].isReady) {
drawProxyTile(tiles[i]);
}
}
for (int i = 0; i < tileCnt; i++) { for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && tiles[i].isReady) { if (tiles[i].isVisible && tiles[i].isReady) {
drawTile(tiles[i], 1); drawTile(tiles[i], 1);
} }
} }
// proxies are clipped to the region where nothing was drawn to depth buffer
for (int i = 0; i < tileCnt; i++) {
if (tiles[i].isVisible && !tiles[i].isReady) {
drawProxyTile(tiles[i]);
}
}
glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
glDisable(GLES20.GL_DEPTH_TEST);
mDrawCount = 0; mDrawCount = 0;
glEnable(GL_BLEND); glEnable(GL_BLEND);
@ -1006,6 +974,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
boolean clipped = false; boolean clipped = false;
// GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
for (; pl != null || ll != null;) { for (; pl != null || ll != null;) {
int lnext = Integer.MAX_VALUE; int lnext = Integer.MAX_VALUE;
int pnext = Integer.MAX_VALUE; int pnext = Integer.MAX_VALUE;
@ -1024,28 +995,31 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
if (!clipped) { if (!clipped) {
clipped = true; clipped = true;
glDisable(GLES20.GL_DEPTH_TEST); // glDisable(GLES20.GL_DEPTH_TEST);
} }
} else { } else {
// nastay // nastay
if (!clipped) if (!clipped)
PolygonLayers.drawPolygons(null, 0, mMVPMatrix, mDrawZ, PolygonLayers.drawPolygons(null, 0, mMVPMatrix, mDrawZ,
mDrawScale, mDrawCount, true); mDrawScale, mDrawCount, true);
else { // else {
GLES20.glEnable(GLES20.GL_DEPTH_TEST); // GLES20.glEnable(GLES20.GL_DEPTH_TEST);
glEnable(GLES20.GL_POLYGON_OFFSET_FILL); // glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glPolygonOffset(0, mDrawCount); // GLES20.glPolygonOffset(0, mDrawCount);
} // }
glEnable(GL_BLEND); glEnable(GL_BLEND);
ll = LineLayers.drawLines(tile, ll, pnext, mMVPMatrix, div, ll = LineLayers.drawLines(tile, ll, pnext, mMVPMatrix, div,
mDrawZ, mDrawScale); mDrawZ, mDrawScale);
glDisable(GLES20.GL_DEPTH_TEST); // glDisable(GLES20.GL_DEPTH_TEST);
glDisable(GLES20.GL_POLYGON_OFFSET_FILL); // glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
} }
} }
// glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
// glDisable(GLES20.GL_DEPTH_TEST);
mDrawCount++; mDrawCount++;
} }
@ -1059,7 +1033,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
continue; continue;
} }
if (c.isReady && c.isVisible) { if (c.isReady) {
drawTile(c, 2); drawTile(c, 2);
drawn++; drawn++;
} }
@ -1069,19 +1043,19 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
} }
private static void drawProxyTile(GLMapTile tile) { private static void drawProxyTile(GLMapTile tile) {
if (mDrawScale < 1.5f) { // if (mDrawScale < 1.5f) {
if (!drawProxyChild(tile)) { // if (!drawProxyChild(tile)) {
if (tile.parent != null) { // if (tile.parent != null) {
if (tile.parent.isReady) { // if (tile.parent.isReady) {
drawTile(tile.parent, 0.5f); // drawTile(tile.parent, 0.5f);
} else { // } else {
GLMapTile p = tile.parent.parent; // GLMapTile p = tile.parent.parent;
if (p != null && p.isReady) // if (p != null && p.isReady)
drawTile(p, 0.25f); // drawTile(p, 0.25f);
} // }
} // }
} // }
} else { // } else {
if (tile.parent != null && tile.parent.isReady) { if (tile.parent != null && tile.parent.isReady) {
drawTile(tile.parent, 0.5f); drawTile(tile.parent, 0.5f);
} else if (!drawProxyChild(tile)) { } else if (!drawProxyChild(tile)) {
@ -1091,7 +1065,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
drawTile(p, 0.25f); drawTile(p, 0.25f);
} }
} }
} // }
} }
@Override @Override
@ -1147,7 +1121,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
glDisable(GLES20.GL_DEPTH_TEST); glDisable(GLES20.GL_DEPTH_TEST);
glDepthMask(false); glDepthMask(false);
glDisable(GL_DITHER); glDisable(GL_DITHER);
if (mClearColor != null) {
glClearColor(mClearColor[0], mClearColor[1], mClearColor[2],
mClearColor[3]);
} else {
glClearColor(0.98f, 0.98f, 0.97f, 1.0f); glClearColor(0.98f, 0.98f, 0.97f, 1.0f);
}
glClearStencil(0); glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT); glClear(GL_STENCIL_BUFFER_BIT);

View File

@ -17,8 +17,6 @@ package org.mapsforge.android.glrenderer;
import static android.opengl.GLES20.GL_BLEND; import static android.opengl.GLES20.GL_BLEND;
import static android.opengl.GLES20.GL_EQUAL; import static android.opengl.GLES20.GL_EQUAL;
import static android.opengl.GLES20.GL_INVERT; import static android.opengl.GLES20.GL_INVERT;
import static android.opengl.GLES20.GL_KEEP;
import static android.opengl.GLES20.GL_NEVER;
import static android.opengl.GLES20.GL_STENCIL_TEST; import static android.opengl.GLES20.GL_STENCIL_TEST;
import static android.opengl.GLES20.GL_TRIANGLE_FAN; import static android.opengl.GLES20.GL_TRIANGLE_FAN;
import static android.opengl.GLES20.GL_TRIANGLE_STRIP; import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
@ -84,6 +82,10 @@ class PolygonLayers {
// do not modify stencil buffer // do not modify stencil buffer
glStencilMask(0); glStencilMask(0);
// clip with depth mask
// GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
for (int c = 0; c < count; c++) { for (int c = 0; c < count; c++) {
PolygonLayer l = mFillPolys[c]; PolygonLayer l = mFillPolys[c];
@ -137,6 +139,9 @@ class PolygonLayers {
if (blend) if (blend)
glDisable(GL_BLEND); glDisable(GL_BLEND);
// glDisable(GLES20.GL_DEPTH_TEST);
// glDisable(GLES20.GL_POLYGON_OFFSET_FILL);
} }
static PolygonLayer drawPolygons(PolygonLayer layer, int next, static PolygonLayer drawPolygons(PolygonLayer layer, int next,
@ -156,6 +161,8 @@ class PolygonLayers {
PolygonLayer l = layer; PolygonLayer l = layer;
boolean first = clip;
for (; l != null && l.layer < next; l = l.next) { for (; l != null && l.layer < next; l = l.next) {
// fade out polygon layers (set in RederTheme) // fade out polygon layers (set in RederTheme)
if (l.area.fade > 0 && l.area.fade > zoom) if (l.area.fade > 0 && l.area.fade > zoom)
@ -166,18 +173,34 @@ class PolygonLayers {
glColorMask(false, false, false, false); glColorMask(false, false, false, false);
// never pass the test, i.e. always apply first stencil op (sfail) // never pass the test, i.e. always apply first stencil op (sfail)
glStencilFunc(GL_NEVER, 0, 0xff); glStencilFunc(GLES20.GL_ALWAYS, 0, 0xff);
// clear stencilbuffer // clear stencilbuffer
glStencilMask(0xFF); glStencilMask(0xFF);
// glClear(GL_STENCIL_BUFFER_BIT); // glClear(GL_STENCIL_BUFFER_BIT);
// clear stencilbuffer (tile region) // clear stencilbuffer (tile region)
glStencilOp(GL_ZERO, GL_KEEP, GL_KEEP); glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
if (first) {
// glEnable(GLES20.GL_DEPTH_TEST);
// glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
GLES20.glPolygonOffset(0, drawCount);
GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_LESS);
}
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
if (first) {
first = false;
GLES20.glDepthMask(false);
GLES20.glDepthFunc(GLES20.GL_EQUAL);
// glDisable(GLES20.GL_DEPTH_TEST);
}
// stencil op for stencil method polygon drawing // stencil op for stencil method polygon drawing
glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP); glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT);
} }
mFillPolys[cnt] = l; mFillPolys[cnt] = l;
@ -199,9 +222,8 @@ class PolygonLayers {
glDisable(GL_STENCIL_TEST); glDisable(GL_STENCIL_TEST);
if (clip) { if (clip && first)
drawDepthClip(drawCount); drawDepthClip(drawCount);
}
// required on GalaxyII, Android 2.3.3 (cant just VAA enable once...) // required on GalaxyII, Android 2.3.3 (cant just VAA enable once...)
GLES20.glDisableVertexAttribArray(hPolygonVertexPosition); GLES20.glDisableVertexAttribArray(hPolygonVertexPosition);
@ -243,19 +265,13 @@ class PolygonLayers {
static void drawDepthClip(short drawCount) { static void drawDepthClip(short drawCount) {
glColorMask(false, false, false, false); glColorMask(false, false, false, false);
glEnable(GLES20.GL_DEPTH_TEST); // glEnable(GLES20.GL_DEPTH_TEST);
glEnable(GLES20.GL_POLYGON_OFFSET_FILL); // glEnable(GLES20.GL_POLYGON_OFFSET_FILL);
// GLES20.GL_PO
GLES20.glPolygonOffset(0, drawCount); GLES20.glPolygonOffset(0, drawCount);
// int i[] = new int[1];
// GLES20.glGetIntegerv(GLES20.GL_POLYGON_OFFSET_UNITS, i, 0);
// Log.d("...", "UNITS " + i[0]);
//
// System.out.println("set offset: " + drawCount);
GLES20.glDepthMask(true); GLES20.glDepthMask(true);
GLES20.glDepthFunc(GLES20.GL_ALWAYS); GLES20.glDepthFunc(GLES20.GL_LESS);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2010, 2011, 2012 mapsforge.org * Copyright 2012 Hannes Janetzek
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software * terms of the GNU Lesser General Public License as published by the Free Software
@ -25,5 +25,5 @@ public class ShortItem {
} }
// must be multiple of 6 and 4 (expected in LineLayer/PolygonLayer) // must be multiple of 6 and 4 (expected in LineLayer/PolygonLayer)
static final int SIZE = 240; static final int SIZE = 480;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2010, 2011, 2012 mapsforge.org * Copyright 2012 Hannes Janetzek
* *
* This program is free software: you can redistribute it and/or modify it under the * This program is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software * terms of the GNU Lesser General Public License as published by the Free Software
@ -17,7 +17,7 @@ package org.mapsforge.android.glrenderer;
import android.util.Log; import android.util.Log;
public class ShortPool { public class ShortPool {
private static final int POOL_LIMIT = 6000; private static final int POOL_LIMIT = 2500;
static private ShortItem pool = null; static private ShortItem pool = null;
static private int count = 0; static private int count = 0;
@ -31,6 +31,9 @@ public class ShortPool {
static synchronized ShortItem get() { static synchronized ShortItem get() {
if (pool == null && count > 0) {
Log.d("ShortPool", "XXX wrong count: " + count);
}
if (pool == null) { if (pool == null) {
countAll++; countAll++;
return new ShortItem(); return new ShortItem();
@ -44,7 +47,7 @@ public class ShortPool {
for (ShortItem tmp = pool; tmp != null; tmp = tmp.next) for (ShortItem tmp = pool; tmp != null; tmp = tmp.next)
c++; c++;
Log.d("ShortPool", "eek wrong count: " + count + " left" + c); Log.d("ShortPool", "XXX wrong count: " + count + " left" + c);
return new ShortItem(); return new ShortItem();
} }
@ -55,10 +58,16 @@ public class ShortPool {
return it; return it;
} }
// private static float load = 1.0f;
// private static int loadCount = 0;
static synchronized void add(ShortItem items) { static synchronized void add(ShortItem items) {
if (items == null) if (items == null)
return; return;
// int pall = countAll;
// int pcnt = count;
// limit pool items // limit pool items
if (countAll < POOL_LIMIT) { if (countAll < POOL_LIMIT) {
@ -66,6 +75,8 @@ public class ShortPool {
while (true) { while (true) {
count++; count++;
// load += (float) last.used / ShortItem.SIZE;
// loadCount++;
if (last.next == null) if (last.next == null)
break; break;
@ -75,6 +86,8 @@ public class ShortPool {
last.next = pool; last.next = pool;
pool = items; pool = items;
// Log.d("Pool", "added: " + (count - pcnt) + " " + count + " " + countAll
// + " load: " + (load / loadCount));
} else { } else {
// int cleared = 0; // int cleared = 0;
@ -85,9 +98,14 @@ public class ShortPool {
countAll--; countAll--;
// load += (float) prev.used / ShortItem.SIZE;
// loadCount++;
prev.next = null; prev.next = null;
} }
// Log.d("Pool", "dropped: " + (pall - countAll) + " " + count + " "
// + countAll + " load: " + (load / loadCount));
} }
} }
} }