implement managing of tasks instances in ContinuousTask
This commit is contained in:
parent
c8d79ee6fc
commit
401b0bf2dc
@ -68,6 +68,8 @@ public class LabelLayer extends Layer implements Map.InputListener, Map.UpdateLi
|
||||
public void onMapUpdate(MapPosition mapPosition, boolean changed, boolean clear) {
|
||||
if (clear)
|
||||
mTextRenderer.clearLabels();
|
||||
|
||||
mTextRenderer.update();
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
||||
@ -53,9 +53,11 @@ import org.oscim.utils.FastMath;
|
||||
import org.oscim.utils.OBB2D;
|
||||
import org.oscim.utils.async.ContinuousTask;
|
||||
import org.oscim.utils.pool.Pool;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
class TextRenderer extends ElementRenderer {
|
||||
//static final Logger log = LoggerFactory.getLogger(TextRenderLayer.class);
|
||||
static final Logger log = LoggerFactory.getLogger(TextRenderer.class);
|
||||
|
||||
private final static float MIN_CAPTION_DIST = 5;
|
||||
private final static float MIN_WAY_DIST = 3;
|
||||
@ -65,10 +67,10 @@ class TextRenderer extends ElementRenderer {
|
||||
private final Viewport mViewport;
|
||||
private final TileSet mTileSet;
|
||||
|
||||
class TextureLayers {
|
||||
boolean ready;
|
||||
//private ElementLayers mDebugLayer;
|
||||
|
||||
final TextureLayer l;
|
||||
class TextureLayers {
|
||||
final TextureLayer layers;
|
||||
final TextLayer textLayer;
|
||||
final SymbolLayer symbolLayer;
|
||||
|
||||
@ -80,17 +82,12 @@ class TextRenderer extends ElementRenderer {
|
||||
symbolLayer = new SymbolLayer();
|
||||
textLayer = new TextLayer();
|
||||
|
||||
l = symbolLayer;
|
||||
l.next = textLayer;
|
||||
layers = symbolLayer;
|
||||
symbolLayer.next = textLayer;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// used by GL thread
|
||||
private TextureLayers mCurLayer;
|
||||
|
||||
// used by labeling thread
|
||||
private TextureLayers mNextLayer;
|
||||
|
||||
// thread local pool (labeling)
|
||||
class LabelPool extends Pool<TextItem> {
|
||||
Label releaseAndGetNext(Label l) {
|
||||
@ -139,9 +136,6 @@ class TextRenderer extends ElementRenderer {
|
||||
layers.textureLayers = new TextLayer();
|
||||
layers.textureLayers.next = new SymbolLayer();
|
||||
|
||||
mCurLayer = new TextureLayers();
|
||||
mNextLayer = new TextureLayers();
|
||||
|
||||
//mActiveTiles = new HashMap<MapTile, LabelTile>();
|
||||
mRelabelCnt = 0;
|
||||
|
||||
@ -241,6 +235,15 @@ class TextRenderer extends ElementRenderer {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean iconIsVisible(int x, int y) {
|
||||
// rough filter
|
||||
float dist = x * x + y * y;
|
||||
if (dist > mSquareRadius)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean wayIsVisible(TextItem ti) {
|
||||
// rough filter
|
||||
float dist = ti.x * ti.x + ti.y * ti.y;
|
||||
@ -258,8 +261,6 @@ class TextRenderer extends ElementRenderer {
|
||||
return false;
|
||||
}
|
||||
|
||||
private ElementLayers mDebugLayer;
|
||||
|
||||
private Label getLabel() {
|
||||
Label l = (Label) mPool.get();
|
||||
l.active = Integer.MAX_VALUE;
|
||||
@ -379,10 +380,10 @@ class TextRenderer extends ElementRenderer {
|
||||
return l;
|
||||
}
|
||||
|
||||
boolean updateLabels() {
|
||||
boolean updateLabels(TextureLayers work) {
|
||||
// nextLayer is not loaded yet
|
||||
if (mNextLayer.ready)
|
||||
return false;
|
||||
//if (mNextLayer.ready)
|
||||
// return false;
|
||||
|
||||
// get current tiles
|
||||
boolean changedTiles = mTileLayer.getVisibleTiles(mTileSet);
|
||||
@ -393,7 +394,7 @@ class TextRenderer extends ElementRenderer {
|
||||
return false;
|
||||
}
|
||||
|
||||
MapPosition pos = mNextLayer.pos;
|
||||
MapPosition pos = work.pos;
|
||||
|
||||
synchronized (mViewport) {
|
||||
changedPos = mViewport.getMapPosition(pos);
|
||||
@ -428,7 +429,7 @@ class TextRenderer extends ElementRenderer {
|
||||
//if (dbg != null)
|
||||
// Debug.addDebugLayers(dbg);
|
||||
|
||||
SymbolLayer sl = mNextLayer.symbolLayer;
|
||||
SymbolLayer sl = work.symbolLayer;
|
||||
sl.clearItems();
|
||||
|
||||
mRelabelCnt++;
|
||||
@ -570,13 +571,17 @@ class TextRenderer extends ElementRenderer {
|
||||
if (ti.texRegion == null)
|
||||
continue;
|
||||
|
||||
int x = (int) ((dx + ti.x) * scale);
|
||||
int y = (int) ((dy + ti.y) * scale);
|
||||
|
||||
if (!iconIsVisible(x, y))
|
||||
continue;
|
||||
|
||||
SymbolItem s = SymbolItem.pool.get();
|
||||
|
||||
s.texRegion = ti.texRegion;
|
||||
s.x = (float) ((dx + ti.x) * scale);
|
||||
s.y = (float) ((dy + ti.y) * scale);
|
||||
s.x = x;
|
||||
s.y = y;
|
||||
s.billboard = true;
|
||||
|
||||
sl.addSymbol(s);
|
||||
}
|
||||
}
|
||||
@ -585,18 +590,16 @@ class TextRenderer extends ElementRenderer {
|
||||
// temporary used Label
|
||||
l = (Label) mPool.release(l);
|
||||
|
||||
TextLayer tl = mNextLayer.textLayer;
|
||||
|
||||
tl.labels = mLabels;
|
||||
// draw text to bitmaps and create vertices
|
||||
tl.prepare();
|
||||
tl.labels = null;
|
||||
work.textLayer.labels = mLabels;
|
||||
work.textLayer.prepare();
|
||||
work.textLayer.labels = null;
|
||||
|
||||
// remove tile locks
|
||||
mTileLayer.releaseTiles(mTileSet);
|
||||
|
||||
mDebugLayer = dbg;
|
||||
mNextLayer.ready = true;
|
||||
//mDebugLayer = dbg;
|
||||
//mNextLayer.ready = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -607,90 +610,87 @@ class TextRenderer extends ElementRenderer {
|
||||
public synchronized void update(MapPosition pos, boolean changed,
|
||||
Matrices matrices) {
|
||||
|
||||
if (mNextLayer.ready) {
|
||||
// exchange current with next layers
|
||||
TextureLayers tmp = mCurLayer;
|
||||
mCurLayer = mNextLayer;
|
||||
mNextLayer = tmp;
|
||||
mNextLayer.ready = false;
|
||||
TextureLayers t;
|
||||
synchronized (mLabelTask) {
|
||||
|
||||
t = mLabelTask.poll();
|
||||
|
||||
if (t == null)
|
||||
return;
|
||||
|
||||
// clear textures and text items from previous layer
|
||||
layers.clear();
|
||||
|
||||
if (mDebugLayer != null) {
|
||||
layers.baseLayers = mDebugLayer.baseLayers;
|
||||
mDebugLayer = null;
|
||||
}
|
||||
|
||||
// set new TextLayer to be uploaded and rendered
|
||||
layers.textureLayers = mCurLayer.l;
|
||||
mMapPosition = mCurLayer.pos;
|
||||
|
||||
compile();
|
||||
}
|
||||
|
||||
mLabelTask.submit((mLastRun + MAX_RELABEL_DELAY) - System.currentTimeMillis());
|
||||
// set new TextLayer to be uploaded and rendered
|
||||
layers.textureLayers = t.layers;
|
||||
mMapPosition = t.pos;
|
||||
compile();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void render(MapPosition pos, Matrices m) {
|
||||
GLState.test(false, false);
|
||||
|
||||
layers.vbo.bind();
|
||||
|
||||
float scale = (float) (mMapPosition.scale / pos.scale);
|
||||
|
||||
setMatrix(pos, m, true);
|
||||
if (layers.baseLayers != null) {
|
||||
setMatrix(pos, m, true);
|
||||
|
||||
synchronized (layers) {
|
||||
layers.vbo.bind();
|
||||
if (layers.baseLayers != null) {
|
||||
for (RenderElement l = layers.baseLayers; l != null;) {
|
||||
if (l.type == RenderElement.POLYGON) {
|
||||
l = PolygonLayer.Renderer.draw(pos, l, m, true, 1, false);
|
||||
} else {
|
||||
float div = scale * (float) (pos.scale / (1 << pos.zoomLevel));
|
||||
l = LineLayer.Renderer.draw(layers, l, pos, m, div);
|
||||
}
|
||||
for (RenderElement l = layers.baseLayers; l != null;) {
|
||||
if (l.type == RenderElement.POLYGON) {
|
||||
l = PolygonLayer.Renderer.draw(pos, l, m, true, 1, false);
|
||||
} else {
|
||||
float div = (float) (mMapPosition.scale / (1 << pos.zoomLevel));
|
||||
l = LineLayer.Renderer.draw(layers, l, pos, m, div);
|
||||
}
|
||||
}
|
||||
|
||||
setMatrix(pos, m, false);
|
||||
|
||||
for (RenderElement l = layers.textureLayers; l != null;)
|
||||
l = TextureLayer.Renderer.draw(l, scale, m);
|
||||
}
|
||||
|
||||
setMatrix(pos, m, false);
|
||||
|
||||
for (RenderElement l = layers.textureLayers; l != null;)
|
||||
l = TextureLayer.Renderer.draw(l, scale, m);
|
||||
}
|
||||
|
||||
final class LabelTask extends ContinuousTask {
|
||||
final class LabelTask extends ContinuousTask<TextureLayers> {
|
||||
|
||||
public LabelTask(Map map) {
|
||||
super(map, 10);
|
||||
super(map, 10, new TextureLayers(), new TextureLayers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doWork() {
|
||||
public boolean doWork(TextureLayers t) {
|
||||
|
||||
if (updateLabels())
|
||||
if (updateLabels(t)) {
|
||||
mMap.render();
|
||||
return true;
|
||||
}
|
||||
|
||||
mLastRun = System.currentTimeMillis();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
clearLabelsInternal();
|
||||
public void cleanup(TextureLayers t) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
mLabels = (Label) mPool.releaseAll(mLabels);
|
||||
mTileSet.releaseTiles();
|
||||
}
|
||||
}
|
||||
|
||||
private final LabelTask mLabelTask;
|
||||
|
||||
/* private */long mLastRun;
|
||||
|
||||
/* private */void clearLabelsInternal() {
|
||||
mLabels = (Label) mPool.releaseAll(mLabels);
|
||||
mTileSet.releaseTiles();
|
||||
public void clearLabels() {
|
||||
mLabelTask.cancel(true);
|
||||
}
|
||||
|
||||
public void clearLabels() {
|
||||
mLabelTask.cancel();
|
||||
public void update() {
|
||||
mLabelTask.submit(MAX_RELABEL_DELAY);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,12 @@ package org.oscim.utils.async;
|
||||
|
||||
import org.oscim.map.Map;
|
||||
|
||||
public abstract class ContinuousTask implements Runnable {
|
||||
/**
|
||||
* Simple 'Double Buffering' worker for running Tasks on AsyncExecutor
|
||||
* thread.
|
||||
*/
|
||||
public abstract class ContinuousTask<T> implements Runnable {
|
||||
|
||||
private final Map mMap;
|
||||
|
||||
protected boolean mRunning;
|
||||
@ -12,30 +17,40 @@ public abstract class ContinuousTask implements Runnable {
|
||||
|
||||
protected long mMinDelay;
|
||||
|
||||
public ContinuousTask(Map map, long minDelay) {
|
||||
/** Stuff which can be processed on the worker thread. */
|
||||
protected T mTaskTodo;
|
||||
|
||||
/** Stuff that is done an ready for being fetched by poll(). */
|
||||
protected T mTaskDone;
|
||||
|
||||
/** Stuff that is ready - will not be modified in the worker. */
|
||||
protected T mTaskLocked;
|
||||
|
||||
public ContinuousTask(Map map, long minDelay, T t1, T t2) {
|
||||
mMap = map;
|
||||
mMinDelay = minDelay;
|
||||
|
||||
mTaskTodo = t1;
|
||||
mTaskLocked = t2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
synchronized (this) {
|
||||
//System.out.println("run " + mRunning + " "
|
||||
// + mCancel + " " + mDelayed + " " + mWait);
|
||||
|
||||
if (mCancel) {
|
||||
mCancel = false;
|
||||
mRunning = false;
|
||||
mDelayed = false;
|
||||
mWait = false;
|
||||
cleanup();
|
||||
cleanup(mTaskTodo);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (mDelayed) {
|
||||
|
||||
if (mDelayed || mTaskTodo == null) {
|
||||
// entered on main-loop
|
||||
mDelayed = false;
|
||||
mWait = false;
|
||||
// unset running temporarily
|
||||
mRunning = false;
|
||||
submit(0);
|
||||
@ -43,32 +58,43 @@ public abstract class ContinuousTask implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
doWork();
|
||||
boolean done = doWork(mTaskTodo);
|
||||
|
||||
synchronized (this) {
|
||||
mRunning = false;
|
||||
|
||||
if (mCancel)
|
||||
cleanup();
|
||||
else if (mWait)
|
||||
if (mCancel) {
|
||||
cleanup(mTaskTodo);
|
||||
finish();
|
||||
mCancel = false;
|
||||
} else if (done) {
|
||||
mTaskDone = mTaskTodo;
|
||||
mTaskTodo = null;
|
||||
} else if (mWait) {
|
||||
// only submit if not 'done'
|
||||
// as otherwise there is no
|
||||
// mStuffTodo
|
||||
submit(mMinDelay);
|
||||
|
||||
mCancel = false;
|
||||
mWait = false;
|
||||
mWait = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void doWork();
|
||||
public abstract boolean doWork(T task);
|
||||
|
||||
public abstract void cleanup();
|
||||
public abstract void cleanup(T task);
|
||||
|
||||
public void finish() {
|
||||
|
||||
}
|
||||
|
||||
public synchronized void submit(long delay) {
|
||||
//System.out.println("submit " + mRunning + " " + mCancel + " " + delay);
|
||||
|
||||
if (mRunning) {
|
||||
mWait = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mRunning = true;
|
||||
if (delay <= 0) {
|
||||
mMap.addTask(this);
|
||||
@ -80,12 +106,31 @@ public abstract class ContinuousTask implements Runnable {
|
||||
|
||||
}
|
||||
|
||||
public synchronized void cancel() {
|
||||
public synchronized T poll() {
|
||||
if (mTaskDone == null)
|
||||
return null;
|
||||
|
||||
cleanup(mTaskLocked);
|
||||
mTaskTodo = mTaskLocked;
|
||||
|
||||
mTaskLocked = mTaskDone;
|
||||
mTaskDone = null;
|
||||
|
||||
if (mWait) {
|
||||
submit(mMinDelay);
|
||||
mWait = false;
|
||||
}
|
||||
|
||||
return mTaskLocked;
|
||||
}
|
||||
|
||||
public synchronized void cancel(boolean clear) {
|
||||
if (mRunning) {
|
||||
mCancel = true;
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
cleanup(mTaskTodo);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user