diff --git a/src/org/mapsforge/android/MapView.java b/src/org/mapsforge/android/MapView.java index af376cf4..d443d2e6 100644 --- a/src/org/mapsforge/android/MapView.java +++ b/src/org/mapsforge/android/MapView.java @@ -94,7 +94,7 @@ public class MapView extends GLSurfaceView { private IMapRenderer mMapRenderer; private JobQueue mJobQueue; private MapWorker mMapWorkers[]; - private int mNumMapWorkers = 6; + private int mNumMapWorkers = 4; private JobParameters mJobParameters; public DebugSettings debugSettings; private String mMapFile; diff --git a/src/org/mapsforge/android/glrenderer/LineLayer.java b/src/org/mapsforge/android/glrenderer/LineLayer.java index b0bf8d73..4b64bee7 100644 --- a/src/org/mapsforge/android/glrenderer/LineLayer.java +++ b/src/org/mapsforge/android/glrenderer/LineLayer.java @@ -35,9 +35,11 @@ class LineLayer { ShortItem pool; protected ShortItem curItem; + + // number of vertices this layer holds int verticesCnt; + // vertices offset of this layer in VBO int offset; - short[] mVertex; LineLayer(int layer, Line line, float width, boolean outline) { this.layer = layer; @@ -55,57 +57,14 @@ class LineLayer { 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 * 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 a; - int pointPos = pos; + int ipos = pos; boolean rounded = false; boolean squared = false; @@ -114,23 +73,14 @@ class LineLayer { else if (line.cap == Cap.SQUARE) squared = true; - if (pool == null) { - curItem = ShortPool.get(); - pool = curItem; - - mVertex = new short[12]; - } - // amount of vertices used verticesCnt += length + (rounded ? 6 : 2); - ShortItem si = curItem; + x = points[ipos++]; + y = points[ipos++]; - x = pointArray[pointPos++]; - y = pointArray[pointPos++]; - - nextX = pointArray[pointPos++]; - nextY = pointArray[pointPos++]; + nextX = points[ipos++]; + nextY = points[ipos++]; // Calculate triangle corners for the given width vx = nextX - x; @@ -144,47 +94,116 @@ class LineLayer { ux = -vy; uy = vx; - float uxw = ux; - float uyw = uy; - - float vxw = vx; - float vyw = vy; int tsize = Tile.TILE_SIZE; - short v[] = mVertex; + if (pool == null) { + pool = curItem = ShortPool.get(); + } - v[0] = (short) (x * S); - v[1] = (short) (y * S); + ShortItem si = curItem; + 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) - && (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) { - 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); - v[3] = (short) (-(uyw + vyw) * S1000); - v[4] = 1; - v[5] = 1; - si = addVertex(v, si); + // For rounded line edges + 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; + + 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 - v[2] = (short) ((uxw) * S1000); - v[3] = (short) ((uyw) * S1000); - v[4] = -1; - v[5] = 0; - si = addVertex(v, si); + dx = (short) (ux * S1000); + dy = (short) (uy * S1000); - v[2] = (short) ((-uxw) * S1000); - v[3] = (short) ((-uyw) * S1000); - v[4] = 1; - v[5] = 0; - 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] = 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 { // outside means line is probably clipped @@ -192,29 +211,61 @@ class LineLayer { // for now, just extend the line a little if (squared) { - vxw = 0; - vyw = 0; + vx = 0; + vy = 0; } else if (!outside) { - vxw *= 0.5; - vyw *= 0.5; + vx *= 0.5; + vy *= 0.5; } if (rounded) verticesCnt -= 2; - // Add the first point twice to be able to draw with GL_TRIANGLE_STRIP - v[2] = (short) ((uxw - vxw) * S1000); - v[3] = (short) ((uyw - vyw) * S1000); - v[4] = -1; - v[5] = 0; - si = addVertex(v, si); - si = addVertex(v, si); + dx = (short) ((ux - vx) * S1000); + dy = (short) ((uy - vy) * S1000); - v[2] = (short) (-(uxw + vxw) * S1000); - v[3] = (short) (-(uyw + vyw) * S1000); - v[4] = 1; - v[5] = 0; - 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] = 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; @@ -222,9 +273,9 @@ class LineLayer { x = nextX; y = nextY; - for (; pointPos < pos + length;) { - nextX = pointArray[pointPos++]; - nextY = pointArray[pointPos++]; + for (; ipos < pos + length;) { + nextX = points[ipos++]; + nextY = points[ipos++]; // Unit vector pointing back to previous node vx = prevX - x; @@ -261,22 +312,43 @@ class LineLayer { } } - uxw = ux * S1000; - uyw = uy * S1000; + if (opos == ShortItem.SIZE) { + si.used = ShortItem.SIZE; + si.next = ShortPool.get(); + si = si.next; + opos = 0; + v = si.vertices; + } - v[6] = v[0] = (short) (x * S); - v[7] = v[1] = (short) (y * S); + ox = (short) (x * S); + oy = (short) (y * S); - v[2] = (short) uxw; - v[3] = (short) uyw; - v[4] = -1; - v[5] = 0; + dx = (short) (ux * S1000); + dy = (short) (uy * S1000); - v[8] = (short) -uxw; - v[9] = (short) -uyw; - v[10] = 1; - v[11] = 0; - si = addTwoVertex(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] = 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; prevY = y; @@ -295,71 +367,164 @@ class LineLayer { ux = vy; uy = -vx; - uxw = ux; - uyw = uy; - - vxw = vx; - vyw = vy; - 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); - v[1] = (short) (y * S); + if (opos == ShortItem.SIZE) { + 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) { - 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); - v[3] = (short) ((-uyw) * S1000); - v[4] = 1; - v[5] = 0; - si = addVertex(v, si); + dx = (short) (ux * S1000); + dy = (short) (uy * 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] = (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 - v[2] = (short) ((uxw - vxw) * S1000); - v[3] = (short) ((uyw - vyw) * S1000); - v[4] = -1; - v[5] = -1; - si = addVertex(v, si); + dx = (short) ((ux - vx) * S1000); + dy = (short) ((uy - vy) * S1000); - 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[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; + } + + 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 { if (squared) { - vxw = 0; - vyw = 0; + vx = 0; + vy = 0; } else if (!outside) { - vxw *= 0.5; - vyw *= 0.5; + vx *= 0.5; + vy *= 0.5; } if (rounded) verticesCnt -= 2; - v[2] = (short) ((uxw) * S1000); - v[3] = (short) ((uyw) * S1000); - v[4] = -1; - v[5] = 0; - si = addVertex(v, si); + dx = (short) ((ux - vx) * S1000); + dy = (short) ((uy - vy) * S1000); - v[2] = (short) (-(uxw + vxw) * S1000); - v[3] = (short) (-(uyw + vyw) * S1000); - v[4] = 1; - v[5] = 0; - si = addVertex(v, si); - 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] = 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; } } diff --git a/src/org/mapsforge/android/glrenderer/MapGenerator.java b/src/org/mapsforge/android/glrenderer/MapGenerator.java index b0a1ff80..318dadc8 100644 --- a/src/org/mapsforge/android/glrenderer/MapGenerator.java +++ b/src/org/mapsforge/android/glrenderer/MapGenerator.java @@ -511,6 +511,7 @@ public class MapGenerator implements IMapGenerator, IRenderCallback, IMapDatabas PolygonLayers.clear(mPolyLayers); mLineLayers = null; mPolyLayers = null; + mLabels = null; tile.isLoading = false; return false; } diff --git a/src/org/mapsforge/android/glrenderer/MapRenderer.java b/src/org/mapsforge/android/glrenderer/MapRenderer.java index 4ecc2931..4abe4f53 100644 --- a/src/org/mapsforge/android/glrenderer/MapRenderer.java +++ b/src/org/mapsforge/android/glrenderer/MapRenderer.java @@ -85,6 +85,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { private final MapView mMapView; private static ArrayList mJobList; private static ArrayList mVBOs; + private static TileCacheKey mTileCacheKey; private static HashMap mTiles; @@ -152,6 +153,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { @Override public void setRenderTheme(RenderTheme t) { int bg = t.getMapBackground(); + Log.d(TAG, "BG" + bg); float[] c = new float[4]; c[0] = (bg >> 16 & 0xff) / 255.0f; c[1] = (bg >> 8 & 0xff) / 255.0f; @@ -246,103 +248,78 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { return false; } - private static void limitCache(int remove) { + private static boolean tileInUse(GLMapTile t) { 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--) { GLMapTile t = mTileList.remove(j); - // dont remove tile used by renderthread or mapgenerator - // FIXME set tile loading state in main thread - if (t.isLoading) { - Log.d(TAG, "cancel loading " + t + " " + (t.zoomLevel - mCurZ) - + " " + (t.zoomLevel - mDrawZ) + " " + t.distance); - t.isCanceled = true; - } - else if (t.isActive) { - Log.d(TAG, "EEEK removing active " + t + " " + (t.zoomLevel - mCurZ) - + " " + (t.zoomLevel - mDrawZ) + " " + t.distance); - mTileList.add(t); - continue; - } - // 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; - } + synchronized (t) { + // dont remove tile used by renderthread or mapgenerator + // FIXME set tile loading state in main thread + // if (t.isLoading) { + // Log.d(TAG, "cancel loading " + t + " " + (t.zoomLevel - mCurZ) + // + " " + (t.zoomLevel - mDrawZ) + " " + t.distance); + // t.isCanceled = true; + // } + // else + if (t.isActive || t.isLoading) { + Log.d(TAG, "EEEK removing active " + t + " " + (t.zoomLevel - mCurZ) + + " " + (t.zoomLevel - mDrawZ) + " " + t.distance); + mTileList.add(t); + continue; + } else if (t.isReady || t.newData) { + // check if this tile is used as proxy for not yet drawn active tile - if (c != null) { - Log.d(TAG, "EEEK removing active proxy parent"); - 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"); + if (tileInUse(t)) { + Log.d(TAG, "X removing proxy: " + t); mTileList.add(t); continue; } } - } - // Log.d(TAG, ">>> remove " + t + " " + (t.zoomLevel - mCurZ) - // + " " + t.distance); - cnt++; - mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel); - mTiles.remove(mTileCacheKey); + cnt++; + mTileCacheKey.set(t.tileX, t.tileY, t.zoomLevel); + mTiles.remove(mTileCacheKey); - // clear references to this tile - for (int i = 0; i < 4; i++) { - if (t.child[i] != null) - t.child[i].parent = null; - } - - if (t.parent != null) { + // clear references to this tile for (int i = 0; i < 4; i++) { - if (t.parent.child[i] == t) { - t.parent.child[i] = null; - break; + if (t.child[i] != null) + t.child[i].parent = null; + } + + if (t.parent != null) { + for (int i = 0; i < 4; i++) { + if (t.parent.child[i] == t) { + t.parent.child[i] = null; + break; + } } } - } - - synchronized (mVBOs) { clearTile(t); } } - // Log.d(TAG, "--------------------------------<<"); } private boolean updateVisibleList(double x, double y, int zdir) { @@ -370,27 +347,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { return false; int max = newTiles.tiles.length - 1; - long limit = (long) Math.pow(2, zoomLevel) - 1; + long limit = (long) Math.pow(2, zoomLevel); if (tileTop < 0) tileTop = 0; if (tileLeft < 0) tileLeft = 0; if (tileBottom >= limit) - tileBottom = limit; + tileBottom = limit - 1; if (tileRight >= limit) - tileRight = limit; + tileRight = limit - 1; - for (long tileY = tileTop; tileY <= tileBottom; tileY++) { - for (long tileX = tileLeft; tileX <= tileRight; tileX++) { + for (long yy = tileTop; yy <= tileBottom; yy++) { + for (long xx = tileLeft; xx <= tileRight; xx++) { // FIXME if (tiles == max) 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) { - tile = new GLMapTile(tileX, tileY, zoomLevel); + tile = new GLMapTile(tx, yy, zoomLevel); TileCacheKey key = new TileCacheKey(mTileCacheKey); // FIXME use sparse matrix or sth. @@ -399,15 +378,15 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { Log.d(TAG, "eeek collision"); 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); - 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 if (tile.parent != null) { tile.parent.child[idx] = tile; } 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)); key = new TileCacheKey(mTileCacheKey); 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, mJobParameter, mDebugSettings); + if (!mJobList.contains(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; // pass new tile list to glThread synchronized (this) { - for (int i = 0; i < curTiles.cnt; i++) { boolean found = false; @@ -467,18 +438,12 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { if (curTiles.tiles[i] == newTiles.tiles[j]) found = true; - if (!found) { + if (!found) curTiles.tiles[i].isActive = false; - // activeList.remove(newTiles.tiles[i]); - } } - for (int i = 0; i < tiles; i++) { - if (!newTiles.tiles[i].isActive) { - newTiles.tiles[i].isActive = true; - // activeList.add(newTiles.tiles[i]); - } - } + for (int i = 0; i < tiles; i++) + newTiles.tiles[i].isActive = true; TilesData tmp = curTiles; curTiles = newTiles; @@ -493,19 +458,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { mUpdateTiles = true; } - // see FIXME in passTile - // synchronized (mTiles) { updateTileDistances(); - // } if (mJobList.size() > 0) mMapView.addJobs(mJobList); int removes = mTiles.size() - CACHE_TILES; - if (removes > 20) { - // Log.d(TAG, "---- remove " + removes + " on " + zoomLevel + " active:" - // + active + "------"); + if (removes > 10) { Collections.sort(mTileList, mTileDistanceSort); limitCache(removes); } @@ -534,18 +494,23 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { } private static void clearTile(GLMapTile t) { + t.newData = false; + t.isLoading = false; + t.isReady = false; + LineLayers.clear(t.lineLayers); PolygonLayers.clear(t.polygonLayers); - if (t.vbo != null) - mVBOs.add(t.vbo); - t.labels = null; t.lineLayers = null; t.polygonLayers = null; - t.newData = false; - t.isLoading = false; - t.isReady = false; + + if (t.vbo != null) { + synchronized (mVBOs) { + mVBOs.add(t.vbo); + } + } + t.vbo = null; } /** @@ -624,6 +589,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { mCurY = y; mCurZ = zoomLevel; 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) 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(); - if (size > MAX_TILES_IN_QUEUE) { + if (size < MAX_TILES_IN_QUEUE) + return; + + synchronized (mTilesLoaded) { + // remove uploaded tiles for (int i = 0; i < size;) { GLMapTile t = mTilesLoaded.get(i); @@ -663,40 +618,53 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { i++; } + // clear loaded but not used tiles 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 - while (size-- > MAX_TILES_IN_QUEUE) { + while (size-- > MAX_TILES_IN_QUEUE - 20) { GLMapTile t = mTilesLoaded.get(size); - // FIXME race condition: tile could be uploaded as proxy - // therefore sync with upload tile data - // synchronized (t) { - // dont remove tile if currently used or is direct parent - // 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; + + synchronized (t) { + if (tileInUse(t)) { + Log.d(TAG, "keep unused tile data: " + t + " " + t.isActive); + continue; + } + mTilesLoaded.remove(size); + Log.d(TAG, "remove unused tile data: " + t); + + clearTile(t); } - mTilesLoaded.remove(size); - // Log.d(TAG, "remove unused tile data: " + 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.isLoading = false; - mTilesLoaded.add(0, tile); - if (!timing) mMapView.requestRender(); + synchronized (mTilesLoaded) { + mTilesLoaded.add(0, tile); + } + return true; } @@ -754,96 +722,90 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { } // 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) { - if (mVBOs.size() < 1) { - Log.d(TAG, "uploadTileData, no VBOs left"); - return false; + if (tile.vbo == null) { + if (mVBOs.size() < 1) { + Log.d(TAG, "uploadTileData, no VBOs left"); + return false; + } + tile.vbo = mVBOs.remove(mVBOs.size() - 1); } - tile.vbo = mVBOs.remove(mVBOs.size() - 1); } + + int lineSize = LineLayers.sizeOf(tile.lineLayers); + int polySize = PolygonLayers.sizeOf(tile.polygonLayers); + int newSize = lineSize + polySize; + + if (newSize == 0) { + LineLayers.clear(tile.lineLayers); + PolygonLayers.clear(tile.polygonLayers); + tile.lineLayers = null; + tile.polygonLayers = null; + return false; + } + + Log.d(TAG, "uploadTileData, " + tile); + + glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id); + + sbuf = shortBuffer[uploadCnt]; + + // add fill coordinates + newSize += 8; + + // 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); + } + + sbuf.clear(); + sbuf.position(8); + + PolygonLayers.compileLayerData(tile.polygonLayers, sbuf); + LineLayers.compileLayerData(tile.lineLayers, sbuf); + sbuf.flip(); + + newSize *= SHORT_BYTES; + + if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4) { + GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf); + } else { + mBufferMemoryUsage -= tile.vbo.size; + tile.vbo.size = newSize; + glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW); + mBufferMemoryUsage += tile.vbo.size; + } + tile.lineOffset = (8 + polySize) * SHORT_BYTES; + + // tile.isLoading = false; + + uploadCnt++; + + tile.isReady = true; + tile.newData = false; } - - // synchronized (tile) { - if (!tile.newData) - return false; - - tile.isReady = true; - tile.newData = false; - // } - - int lineSize = LineLayers.sizeOf(tile.lineLayers); - int polySize = PolygonLayers.sizeOf(tile.polygonLayers); - int newSize = lineSize + polySize; - - if (newSize == 0) { - LineLayers.clear(tile.lineLayers); - PolygonLayers.clear(tile.polygonLayers); - tile.lineLayers = null; - tile.polygonLayers = null; - return false; - } - - // Log.d(TAG, "uploadTileData, " + tile); - - glBindBuffer(GL_ARRAY_BUFFER, tile.vbo.id); - - sbuf = shortBuffer[uploadCnt]; - - // add fill coordinates - newSize += 8; - - // 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); - } - - sbuf.clear(); - sbuf.position(8); - - PolygonLayers.compileLayerData(tile.polygonLayers, sbuf); - LineLayers.compileLayerData(tile.lineLayers, sbuf); - sbuf.flip(); - - newSize *= SHORT_BYTES; - - if (tile.vbo.size > newSize && tile.vbo.size < newSize * 4) { - GLES20.glBufferSubData(GL_ARRAY_BUFFER, 0, newSize, sbuf); - } else { - mBufferMemoryUsage -= tile.vbo.size; - tile.vbo.size = newSize; - glBufferData(GL_ARRAY_BUFFER, tile.vbo.size, sbuf, GL_DYNAMIC_DRAW); - mBufferMemoryUsage += tile.vbo.size; - } - tile.lineOffset = (8 + polySize) * SHORT_BYTES; - - // tile.isLoading = false; - - uploadCnt++; - return true; } - private float[] mClearColor; + private float[] mClearColor = null; private static long mRedrawCnt = 0; @Override public void onDrawFrame(GL10 glUnused) { long start = 0, poly_time = 0, clear_time = 0; - if (mClearColor != null) { - glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], - mClearColor[3]); - mClearColor = null; - } - - glClear(GLES20.GL_COLOR_BUFFER_BIT);// | GLES20.GL_DEPTH_BUFFER_BIT); + glClear(GLES20.GL_COLOR_BUFFER_BIT + | GLES20.GL_DEPTH_BUFFER_BIT + // | GLES20.GL_STENCIL_BUFFER_BIT + ); if (mInitial) return; @@ -903,8 +865,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { if (!setTileScissor(tile, 1)) continue; - if (updateTextures < 4 && tile.texture == null - && TextRenderer.drawToTexture(tile)) + if (tile.texture == null && TextRenderer.drawToTexture(tile)) updateTextures++; if (tile.newData) { @@ -930,8 +891,8 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { if (updateTextures > 0) { TextRenderer.compileTextures(); - if (updateTextures == 4) - mMapView.requestRender(); + // if (updateTextures == 4) + // mMapView.requestRender(); } // if (GlUtils.checkGlOutOfMemory("upload: " + mBufferMemoryUsage) // && LIMIT_BUFFERS > MB) @@ -941,18 +902,25 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { clear_time = (SystemClock.uptimeMillis() - start); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - for (int i = 0; i < tileCnt; i++) { - if (tiles[i].isVisible && !tiles[i].isReady) { - drawProxyTile(tiles[i]); - } - } + GLES20.glEnable(GLES20.GL_DEPTH_TEST); + glEnable(GLES20.GL_POLYGON_OFFSET_FILL); for (int i = 0; i < tileCnt; i++) { if (tiles[i].isVisible && tiles[i].isReady) { 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; glEnable(GL_BLEND); @@ -1006,6 +974,9 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { boolean clipped = false; + // GLES20.glEnable(GLES20.GL_DEPTH_TEST); + // glEnable(GLES20.GL_POLYGON_OFFSET_FILL); + for (; pl != null || ll != null;) { int lnext = Integer.MAX_VALUE; int pnext = Integer.MAX_VALUE; @@ -1024,28 +995,31 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { if (!clipped) { clipped = true; - glDisable(GLES20.GL_DEPTH_TEST); + // glDisable(GLES20.GL_DEPTH_TEST); } } else { // nastay if (!clipped) PolygonLayers.drawPolygons(null, 0, mMVPMatrix, mDrawZ, mDrawScale, mDrawCount, true); - else { - GLES20.glEnable(GLES20.GL_DEPTH_TEST); - glEnable(GLES20.GL_POLYGON_OFFSET_FILL); - GLES20.glPolygonOffset(0, mDrawCount); - } + // else { + // GLES20.glEnable(GLES20.GL_DEPTH_TEST); + // glEnable(GLES20.GL_POLYGON_OFFSET_FILL); + // GLES20.glPolygonOffset(0, mDrawCount); + // } glEnable(GL_BLEND); ll = LineLayers.drawLines(tile, ll, pnext, mMVPMatrix, div, mDrawZ, mDrawScale); - glDisable(GLES20.GL_DEPTH_TEST); - glDisable(GLES20.GL_POLYGON_OFFSET_FILL); + // glDisable(GLES20.GL_DEPTH_TEST); + // glDisable(GLES20.GL_POLYGON_OFFSET_FILL); } } + // glDisable(GLES20.GL_POLYGON_OFFSET_FILL); + // glDisable(GLES20.GL_DEPTH_TEST); + mDrawCount++; } @@ -1059,7 +1033,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { continue; } - if (c.isReady && c.isVisible) { + if (c.isReady) { drawTile(c, 2); drawn++; } @@ -1069,29 +1043,29 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { } private static void drawProxyTile(GLMapTile tile) { - if (mDrawScale < 1.5f) { - if (!drawProxyChild(tile)) { - if (tile.parent != null) { - if (tile.parent.isReady) { - drawTile(tile.parent, 0.5f); - } else { - GLMapTile p = tile.parent.parent; - if (p != null && p.isReady) - drawTile(p, 0.25f); - } - } - } - } else { - if (tile.parent != null && tile.parent.isReady) { - drawTile(tile.parent, 0.5f); - } else if (!drawProxyChild(tile)) { - if (tile.parent != null) { - GLMapTile p = tile.parent.parent; - if (p != null && p.isReady) - drawTile(p, 0.25f); - } + // if (mDrawScale < 1.5f) { + // if (!drawProxyChild(tile)) { + // if (tile.parent != null) { + // if (tile.parent.isReady) { + // drawTile(tile.parent, 0.5f); + // } else { + // GLMapTile p = tile.parent.parent; + // if (p != null && p.isReady) + // drawTile(p, 0.25f); + // } + // } + // } + // } else { + if (tile.parent != null && tile.parent.isReady) { + drawTile(tile.parent, 0.5f); + } else if (!drawProxyChild(tile)) { + if (tile.parent != null) { + GLMapTile p = tile.parent.parent; + if (p != null && p.isReady) + drawTile(p, 0.25f); } } + // } } @Override @@ -1147,7 +1121,14 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer { glDisable(GLES20.GL_DEPTH_TEST); glDepthMask(false); glDisable(GL_DITHER); - glClearColor(0.98f, 0.98f, 0.97f, 1.0f); + + if (mClearColor != null) { + + glClearColor(mClearColor[0], mClearColor[1], mClearColor[2], + mClearColor[3]); + } else { + glClearColor(0.98f, 0.98f, 0.97f, 1.0f); + } glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); diff --git a/src/org/mapsforge/android/glrenderer/PolygonLayers.java b/src/org/mapsforge/android/glrenderer/PolygonLayers.java index f20dcd06..44ab69f2 100644 --- a/src/org/mapsforge/android/glrenderer/PolygonLayers.java +++ b/src/org/mapsforge/android/glrenderer/PolygonLayers.java @@ -17,8 +17,6 @@ package org.mapsforge.android.glrenderer; import static android.opengl.GLES20.GL_BLEND; import static android.opengl.GLES20.GL_EQUAL; 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_TRIANGLE_FAN; import static android.opengl.GLES20.GL_TRIANGLE_STRIP; @@ -84,6 +82,10 @@ class PolygonLayers { // do not modify stencil buffer 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++) { PolygonLayer l = mFillPolys[c]; @@ -137,6 +139,9 @@ class PolygonLayers { if (blend) glDisable(GL_BLEND); + + // glDisable(GLES20.GL_DEPTH_TEST); + // glDisable(GLES20.GL_POLYGON_OFFSET_FILL); } static PolygonLayer drawPolygons(PolygonLayer layer, int next, @@ -156,6 +161,8 @@ class PolygonLayers { PolygonLayer l = layer; + boolean first = clip; + for (; l != null && l.layer < next; l = l.next) { // fade out polygon layers (set in RederTheme) if (l.area.fade > 0 && l.area.fade > zoom) @@ -166,18 +173,34 @@ class PolygonLayers { glColorMask(false, false, false, false); // 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 glStencilMask(0xFF); // glClear(GL_STENCIL_BUFFER_BIT); // 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); + if (first) { + first = false; + GLES20.glDepthMask(false); + GLES20.glDepthFunc(GLES20.GL_EQUAL); + // glDisable(GLES20.GL_DEPTH_TEST); + } + // stencil op for stencil method polygon drawing - glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP); + glStencilOp(GL_INVERT, GL_INVERT, GL_INVERT); } mFillPolys[cnt] = l; @@ -199,9 +222,8 @@ class PolygonLayers { glDisable(GL_STENCIL_TEST); - if (clip) { + if (clip && first) drawDepthClip(drawCount); - } // required on GalaxyII, Android 2.3.3 (cant just VAA enable once...) GLES20.glDisableVertexAttribArray(hPolygonVertexPosition); @@ -243,19 +265,13 @@ class PolygonLayers { static void drawDepthClip(short drawCount) { glColorMask(false, false, false, false); - glEnable(GLES20.GL_DEPTH_TEST); - glEnable(GLES20.GL_POLYGON_OFFSET_FILL); - // GLES20.GL_PO + // glEnable(GLES20.GL_DEPTH_TEST); + // glEnable(GLES20.GL_POLYGON_OFFSET_FILL); 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.glDepthFunc(GLES20.GL_ALWAYS); + GLES20.glDepthFunc(GLES20.GL_LESS); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); diff --git a/src/org/mapsforge/android/glrenderer/ShortItem.java b/src/org/mapsforge/android/glrenderer/ShortItem.java index 37a66083..e668f247 100644 --- a/src/org/mapsforge/android/glrenderer/ShortItem.java +++ b/src/org/mapsforge/android/glrenderer/ShortItem.java @@ -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 * 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) - static final int SIZE = 240; + static final int SIZE = 480; } diff --git a/src/org/mapsforge/android/glrenderer/ShortPool.java b/src/org/mapsforge/android/glrenderer/ShortPool.java index 4b0e71c5..d4074a1e 100644 --- a/src/org/mapsforge/android/glrenderer/ShortPool.java +++ b/src/org/mapsforge/android/glrenderer/ShortPool.java @@ -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 * 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; public class ShortPool { - private static final int POOL_LIMIT = 6000; + private static final int POOL_LIMIT = 2500; static private ShortItem pool = null; static private int count = 0; @@ -31,6 +31,9 @@ public class ShortPool { static synchronized ShortItem get() { + if (pool == null && count > 0) { + Log.d("ShortPool", "XXX wrong count: " + count); + } if (pool == null) { countAll++; return new ShortItem(); @@ -44,7 +47,7 @@ public class ShortPool { for (ShortItem tmp = pool; tmp != null; tmp = tmp.next) c++; - Log.d("ShortPool", "eek wrong count: " + count + " left" + c); + Log.d("ShortPool", "XXX wrong count: " + count + " left" + c); return new ShortItem(); } @@ -55,10 +58,16 @@ public class ShortPool { return it; } + // private static float load = 1.0f; + // private static int loadCount = 0; + static synchronized void add(ShortItem items) { if (items == null) return; + // int pall = countAll; + // int pcnt = count; + // limit pool items if (countAll < POOL_LIMIT) { @@ -66,6 +75,8 @@ public class ShortPool { while (true) { count++; + // load += (float) last.used / ShortItem.SIZE; + // loadCount++; if (last.next == null) break; @@ -75,6 +86,8 @@ public class ShortPool { last.next = pool; pool = items; + // Log.d("Pool", "added: " + (count - pcnt) + " " + count + " " + countAll + // + " load: " + (load / loadCount)); } else { // int cleared = 0; @@ -85,9 +98,14 @@ public class ShortPool { countAll--; + // load += (float) prev.used / ShortItem.SIZE; + // loadCount++; + prev.next = null; } + // Log.d("Pool", "dropped: " + (pall - countAll) + " " + count + " " + // + countAll + " load: " + (load / loadCount)); } } }