- 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:
parent
ba90664ee2
commit
91ba202082
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -85,6 +85,7 @@ public class MapRenderer implements org.mapsforge.android.IMapRenderer {
|
||||
private final MapView mMapView;
|
||||
private static ArrayList<MapGeneratorJob> mJobList;
|
||||
private static ArrayList<VertexBufferObject> mVBOs;
|
||||
|
||||
private static TileCacheKey mTileCacheKey;
|
||||
private static HashMap<TileCacheKey, GLMapTile> 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);
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user