From 8626aa2f53621b2f74f1bc421653e3aa8cd69a26 Mon Sep 17 00:00:00 2001 From: Hannes Janetzek Date: Fri, 24 Oct 2014 22:20:11 +0200 Subject: [PATCH] api: no more sync'ed Viewport methods - remove synchronized viewport methods: viewport MUST only be changed on main-thread - when calling Map.setPosition() from another thread the position will be applied on the next main-loop iteration --- .../src/org/oscim/android/AndroidMap.java | 60 ++++--- vtm-gdx/src/org/oscim/gdx/GdxMap.java | 79 ++++----- .../gdx/emu/org/oscim/utils/ThreadUtils.java | 16 ++ vtm/src/org/oscim/map/Animator.java | 154 ++++++++++-------- vtm/src/org/oscim/map/Map.java | 47 +++++- vtm/src/org/oscim/map/ViewController.java | 58 ++++++- vtm/src/org/oscim/map/Viewport.java | 31 ++-- vtm/src/org/oscim/renderer/GLViewport.java | 5 +- vtm/src/org/oscim/renderer/MapRenderer.java | 23 ++- vtm/src/org/oscim/utils/ThreadUtils.java | 20 +++ 10 files changed, 328 insertions(+), 165 deletions(-) create mode 100644 vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/ThreadUtils.java create mode 100644 vtm/src/org/oscim/utils/ThreadUtils.java diff --git a/vtm-android/src/org/oscim/android/AndroidMap.java b/vtm-android/src/org/oscim/android/AndroidMap.java index 4801da94..0a130a6f 100644 --- a/vtm-android/src/org/oscim/android/AndroidMap.java +++ b/vtm-android/src/org/oscim/android/AndroidMap.java @@ -18,16 +18,20 @@ package org.oscim.android; import org.oscim.android.gl.GLView; import org.oscim.map.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import android.widget.RelativeLayout.LayoutParams; public class AndroidMap extends Map { + static final Logger log = LoggerFactory.getLogger(AndroidMap.class); private final MapView mMapView; final GLView mGLView; - private volatile boolean mWaitRedraw; - private volatile boolean mPausing; + private boolean mRenderRequest; + private boolean mRenderWait; + private boolean mPausing; public AndroidMap(MapView mapView) { super(); @@ -52,14 +56,24 @@ public class AndroidMap extends Map { return mMapView.getHeight(); } + private final Runnable mRedrawCb = new Runnable() { + @Override + public void run() { + prepareFrame(); + mGLView.requestRender(); + } + }; + @Override public void updateMap(boolean redraw) { - //if (redraw && !mClearMap && !mPausing) - // mGLView.requestRender(); + if (mPausing) + return; - if (!mWaitRedraw) { - mWaitRedraw = true; - mMapView.post(mRedrawRequest); + if (!mRenderRequest) { + mRenderRequest = true; + mMapView.post(mRedrawCb); + } else { + mRenderWait = true; } } @@ -68,25 +82,24 @@ public class AndroidMap extends Map { if (mPausing) return; - if (mClearMap) - updateMap(false); - else - mGLView.requestRender(); + updateMap(true); } - private final Runnable mRedrawRequest = new Runnable() { - @Override - public void run() { - redrawMapInternal(); + @Override + public void beginFrame() { + } + + @Override + public void doneFrame() { + mRenderRequest = false; + + if (mRenderWait) { + //log.debug("redraw"); + mRenderWait = false; + updateMap(true); + //prepareFrame(); + //mGLView.requestRender(); } - }; - - void redrawMapInternal() { - mWaitRedraw = false; - - updateLayers(); - - mGLView.requestRender(); } @Override @@ -100,6 +113,7 @@ public class AndroidMap extends Map { } public void pause(boolean pause) { + log.debug("pause... {}", pause); mPausing = pause; } } diff --git a/vtm-gdx/src/org/oscim/gdx/GdxMap.java b/vtm-gdx/src/org/oscim/gdx/GdxMap.java index dda61619..20fa383a 100644 --- a/vtm-gdx/src/org/oscim/gdx/GdxMap.java +++ b/vtm-gdx/src/org/oscim/gdx/GdxMap.java @@ -38,15 +38,12 @@ import com.badlogic.gdx.utils.Timer.Task; public abstract class GdxMap implements ApplicationListener { final static Logger log = LoggerFactory.getLogger(GdxMap.class); - protected final Map mMap; - private final MapAdapter mMapAdapter; + protected Map mMap; VectorTileLayer mMapLayer; - private final MapRenderer mMapRenderer; + private MapRenderer mMapRenderer; public GdxMap() { - mMap = mMapAdapter = new MapAdapter(); - mMapRenderer = new MapRenderer(mMap); } protected void initDefaultLayers(TileSource tileSource, boolean tileGrid, boolean labels, @@ -70,6 +67,8 @@ public abstract class GdxMap implements ApplicationListener { @Override public void create() { + mMap = new MapAdapter(); + mMapRenderer = new MapRenderer(mMap); Gdx.graphics.setContinuousRendering(false); Gdx.app.setLogLevel(Application.LOG_DEBUG); @@ -101,9 +100,13 @@ public abstract class GdxMap implements ApplicationListener { } + /* private */boolean mRenderWait; + /* private */boolean mRenderRequest; + /* private */boolean mUpdateRequest; + @Override public void render() { - if (!mMapAdapter.needsRedraw()) + if (!mRenderRequest) return; mMapRenderer.onDrawFrame(); @@ -132,8 +135,7 @@ public abstract class GdxMap implements ApplicationListener { return mMap; } - static class MapAdapter extends Map { - boolean mRenderRequest; + class MapAdapter extends Map { @Override public int getWidth() { @@ -145,21 +147,35 @@ public abstract class GdxMap implements ApplicationListener { return Gdx.graphics.getHeight(); } + private final Runnable mRedrawCb = new Runnable() { + @Override + public void run() { + prepareFrame(); + Gdx.graphics.requestRendering(); + } + }; + @Override public void updateMap(boolean forceRender) { - if (!mWaitRedraw) { - mWaitRedraw = true; - Gdx.app.postRunnable(mRedrawRequest); + + if (!mRenderRequest) { + mRenderRequest = true; + Gdx.app.postRunnable(mRedrawCb); + } else { + mRenderWait = true; } } @Override public void render() { + //updateMap(true); + mRenderRequest = true; if (mClearMap) updateMap(false); - else + else { Gdx.graphics.requestRendering(); + } } @Override @@ -179,35 +195,22 @@ public abstract class GdxMap implements ApplicationListener { return true; } - /** - * Update all Layers on Main thread. - * - * @param forceRedraw - * also render frame FIXME (does nothing atm) - */ - private void redrawMapInternal(boolean forceRedraw) { - updateLayers(); - - mRenderRequest = true; - Gdx.graphics.requestRendering(); + @Override + public void beginFrame() { } - /* private */boolean mWaitRedraw; - private final Runnable mRedrawRequest = new Runnable() { - @Override - public void run() { - mWaitRedraw = false; - redrawMapInternal(false); - } - }; - - public boolean needsRedraw() { - if (!mRenderRequest) - return false; - + @Override + public void doneFrame() { mRenderRequest = false; - return true; - } + if (mRenderWait) { + mRenderWait = false; + + mRenderRequest = true; + + prepareFrame(); + Gdx.graphics.requestRendering(); + } + } } } diff --git a/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/ThreadUtils.java b/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/ThreadUtils.java new file mode 100644 index 00000000..56ee2076 --- /dev/null +++ b/vtm-web/src/org/oscim/gdx/emu/org/oscim/utils/ThreadUtils.java @@ -0,0 +1,16 @@ +package org.oscim.utils; + +public class ThreadUtils { + + public static void assertMainThread() { + } + + public static boolean isMainThread() { + return true; + } + + public static void init() { + + } + +} diff --git a/vtm/src/org/oscim/map/Animator.java b/vtm/src/org/oscim/map/Animator.java index 0bf182b2..40b5ec04 100644 --- a/vtm/src/org/oscim/map/Animator.java +++ b/vtm/src/org/oscim/map/Animator.java @@ -27,14 +27,14 @@ import org.oscim.core.MapPosition; import org.oscim.core.Point; import org.oscim.core.Tile; import org.oscim.renderer.MapRenderer; +import org.oscim.utils.ThreadUtils; +import org.oscim.utils.async.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Animator { static final Logger log = LoggerFactory.getLogger(Animator.class); - //static final Logger log = LoggerFactory.getLogger(MapAnimator.class); - private final static int ANIM_NONE = 0; private final static int ANIM_MOVE = 1 << 0; private final static int ANIM_SCALE = 1 << 1; @@ -62,6 +62,8 @@ public class Animator { } public synchronized void animateTo(long duration, BoundingBox bbox) { + ThreadUtils.assertMainThread(); + mMap.getMapPosition(mStartPos); /* TODO for large distance first scale out, then in * calculate the maximum scale at which the BoundingBox @@ -89,12 +91,22 @@ public class Animator { animStart(duration, ANIM_MOVE | ANIM_SCALE | ANIM_ROTATE | ANIM_TILT); } - public synchronized void animateTo(BoundingBox bbox) { + public void animateTo(BoundingBox bbox) { animateTo(1000, bbox); } - public synchronized void animateTo(long duration, GeoPoint geoPoint, + /** + * Animate to GeoPoint + * + * @param duration in ms + * @param geoPoint + * @param scale + * @param relative alter scale relative to current scale + */ + public void animateTo(long duration, GeoPoint geoPoint, double scale, boolean relative) { + ThreadUtils.assertMainThread(); + mMap.getMapPosition(mStartPos); if (relative) @@ -110,11 +122,13 @@ public class Animator { animStart(duration, ANIM_MOVE | ANIM_SCALE); } - public synchronized void animateTo(GeoPoint p) { + public void animateTo(GeoPoint p) { animateTo(500, p, 1, true); } - public synchronized void animateTo(long duration, MapPosition pos) { + public void animateTo(long duration, MapPosition pos) { + ThreadUtils.assertMainThread(); + mMap.getMapPosition(mStartPos); pos.scale = clamp(pos.scale, @@ -130,8 +144,10 @@ public class Animator { animStart(duration, ANIM_MOVE | ANIM_SCALE | ANIM_ROTATE | ANIM_TILT); } - public synchronized void animateZoom(long duration, double scaleBy, + public void animateZoom(long duration, double scaleBy, float pivotX, float pivotY) { + ThreadUtils.assertMainThread(); + mMap.getMapPosition(mCurPos); if (mState == ANIM_SCALE) @@ -150,9 +166,11 @@ public class Animator { animStart(duration, ANIM_SCALE); } - public synchronized void animateFling(float velocityX, float velocityY, + public void animateFling(float velocityX, float velocityY, int xmin, int xmax, int ymin, int ymax) { + ThreadUtils.assertMainThread(); + if (velocityX * velocityX + velocityY * velocityY < 2048) return; @@ -177,87 +195,90 @@ public class Animator { } private void animStart(float duration, int state) { - mState = state; mCurPos.copy(mStartPos); + mState = state; mDuration = duration; mAnimEnd = System.currentTimeMillis() + (long) duration; mMap.render(); } - private void animCancel() { - mState = ANIM_NONE; - mPivot.x = 0; - mPivot.y = 0; - } - /** * called by MapRenderer at begin of each frame. */ - public synchronized void updateAnimation() { + void updateAnimation() { if (mState == ANIM_NONE) return; long millisLeft = mAnimEnd - MapRenderer.frametime; - boolean changed = false; + //boolean changed = false; ViewController v = mMap.viewport(); - synchronized (v) { - /* cancel animation when position was changed since last - * update, i.e. when it was modified outside the animator. */ - if (v.getMapPosition(mCurPos)) { - animCancel(); - return; - } - - float adv = clamp(1.0f - millisLeft / mDuration, 0, 1); - - double scaleAdv = 1; - if ((mState & ANIM_SCALE) != 0) { - scaleAdv = doScale(v, adv); - } - - if ((mState & ANIM_MOVE) != 0) { - v.moveTo(mStartPos.x + mDeltaPos.x * (adv / scaleAdv), - mStartPos.y + mDeltaPos.y * (adv / scaleAdv)); - } - - if ((mState & ANIM_FLING) != 0) { - adv = (float) Math.sqrt(adv); - double dx = mVelocity.x * adv; - double dy = mVelocity.y * adv; - if ((dx - mScroll.x) != 0 || (dy - mScroll.y) != 0) { - v.moveMap((float) (dx - mScroll.x), - (float) (dy - mScroll.y)); - mScroll.x = dx; - mScroll.y = dy; - } - } - if ((mState & ANIM_ROTATE) != 0) { - v.setRotation(mStartPos.bearing + mDeltaPos.bearing * adv); - } - - if ((mState & ANIM_TILT) != 0) { - v.setTilt(mStartPos.tilt + mDeltaPos.tilt * adv); - } - - if (millisLeft <= 0) - animCancel(); - - /* remember current map position */ - changed = v.getMapPosition(mCurPos); + //synchronized (v) { + /* cancel animation when position was changed since last + * update, i.e. when it was modified outside the animator. */ + if (v.getMapPosition(mCurPos)) { + log.debug("cancel anim - changed"); + cancel(); + return; } + float adv = clamp(1.0f - millisLeft / mDuration, 0, 1); + + double scaleAdv = 1; + if ((mState & ANIM_SCALE) != 0) { + scaleAdv = doScale(v, adv); + } + + if ((mState & ANIM_MOVE) != 0) { + v.moveTo(mStartPos.x + mDeltaPos.x * (adv / scaleAdv), + mStartPos.y + mDeltaPos.y * (adv / scaleAdv)); + } + + if ((mState & ANIM_FLING) != 0) { + adv = (float) Math.sqrt(adv); + double dx = mVelocity.x * adv; + double dy = mVelocity.y * adv; + if ((dx - mScroll.x) != 0 || (dy - mScroll.y) != 0) { + v.moveMap((float) (dx - mScroll.x), + (float) (dy - mScroll.y)); + mScroll.x = dx; + mScroll.y = dy; + } + } + if ((mState & ANIM_ROTATE) != 0) { + v.setRotation(mStartPos.bearing + mDeltaPos.bearing * adv); + } + + if ((mState & ANIM_TILT) != 0) { + v.setTilt(mStartPos.tilt + mDeltaPos.tilt * adv); + } + + if (millisLeft <= 0) { + //log.debug("animate END"); + cancel(); + } + + /* remember current map position */ + final boolean changed = v.getMapPosition(mCurPos); + if (changed) { - /* render and inform layers that position has changed */ mMap.updateMap(true); } else { - /* just render next frame */ - mMap.render(); + mMap.postDelayed(updateTask, 10); } } + private Task updateTask = new Task() { + @Override + public int go(boolean canceled) { + if (!canceled) + updateAnimation(); + return Task.DONE; + } + }; + private double doScale(ViewController v, float adv) { double newScale = mStartPos.scale + mDeltaPos.scale * Math.sqrt(adv); @@ -267,7 +288,10 @@ public class Animator { return newScale / (mStartPos.scale + mDeltaPos.scale); } - public synchronized void cancel() { + public void cancel() { + //ThreadUtils.assertMainThread(); mState = ANIM_NONE; + mPivot.x = 0; + mPivot.y = 0; } } diff --git a/vtm/src/org/oscim/map/Map.java b/vtm/src/org/oscim/map/Map.java index 8d027099..8d2a15b0 100644 --- a/vtm/src/org/oscim/map/Map.java +++ b/vtm/src/org/oscim/map/Map.java @@ -32,6 +32,7 @@ import org.oscim.theme.IRenderTheme; import org.oscim.theme.ThemeFile; import org.oscim.theme.ThemeLoader; import org.oscim.tiling.TileSource; +import org.oscim.utils.ThreadUtils; import org.oscim.utils.async.AsyncExecutor; import org.oscim.utils.async.TaskQueue; import org.slf4j.Logger; @@ -85,7 +86,7 @@ public abstract class Map implements TaskQueue { private final Layers mLayers; private final ViewController mViewport; - private final Animator mAnimator; + protected final Animator mAnimator; private final MapPosition mMapPosition; private final AsyncExecutor mAsyncExecutor; @@ -97,6 +98,8 @@ public abstract class Map implements TaskQueue { protected boolean mClearMap = true; public Map() { + ThreadUtils.init(); + mViewport = new ViewController(); mAnimator = new Animator(this); mLayers = new Layers(this); @@ -237,9 +240,19 @@ public abstract class Map implements TaskQueue { /** * Set {@link MapPosition} of {@link Viewport} and trigger a redraw. */ - public void setMapPosition(MapPosition mapPosition) { - mViewport.setMapPosition(mapPosition); - updateMap(true); + public void setMapPosition(final MapPosition mapPosition) { + if (!ThreadUtils.isMainThread()) + post(new Runnable() { + @Override + public void run() { + mViewport.setMapPosition(mapPosition); + updateMap(true); + } + }); + else { + mViewport.setMapPosition(mapPosition); + updateMap(true); + } } public void setMapPosition(double latitude, double longitude, double scale) { @@ -253,6 +266,10 @@ public abstract class Map implements TaskQueue { * @return true when MapPosition was updated (has changed) */ public boolean getMapPosition(MapPosition mapPosition) { + if (!ThreadUtils.isMainThread()) { + return mViewport.getSyncMapPosition(mapPosition); + } + return mViewport.getMapPosition(mapPosition); } @@ -289,14 +306,18 @@ public abstract class Map implements TaskQueue { } /** - * This function is run on main-loop before rendering a frame. - * Caution: Do not call directly! + * This function is run on main-thread before rendering a frame. + * + * For internal use only. Do not call! */ - protected void updateLayers() { - boolean changed = false; + protected void prepareFrame() { + ThreadUtils.assertMainThread(); + MapPosition pos = mMapPosition; - changed |= mViewport.getMapPosition(pos); + mAnimator.updateAnimation(); + + boolean changed = mViewport.getMapPosition(pos); if (mClearMap) events.fire(CLEAR_EVENT, pos); @@ -306,9 +327,17 @@ public abstract class Map implements TaskQueue { events.fire(UPDATE_EVENT, pos); mClearMap = false; + + mAnimator.updateAnimation(); + + mViewport.syncViewport(); } public boolean handleGesture(Gesture g, MotionEvent e) { return mLayers.handleGesture(g, e); } + + public abstract void beginFrame(); + + public abstract void doneFrame(); } diff --git a/vtm/src/org/oscim/map/ViewController.java b/vtm/src/org/oscim/map/ViewController.java index c7b9fabc..df144b44 100644 --- a/vtm/src/org/oscim/map/ViewController.java +++ b/vtm/src/org/oscim/map/ViewController.java @@ -5,10 +5,13 @@ import org.oscim.core.Point; import org.oscim.core.Tile; import org.oscim.renderer.GLMatrix; import org.oscim.utils.FastMath; +import org.oscim.utils.ThreadUtils; public class ViewController extends Viewport { - public synchronized void setScreenSize(int width, int height) { + public void setScreenSize(int width, int height) { + ThreadUtils.assertMainThread(); + mHeight = height; mWidth = width; @@ -50,7 +53,9 @@ public class ViewController extends Viewport { * @param mx the amount of pixels to move the map horizontally. * @param my the amount of pixels to move the map vertically. */ - public synchronized void moveMap(float mx, float my) { + public void moveMap(float mx, float my) { + ThreadUtils.assertMainThread(); + Point p = applyRotation(mx, my); double tileScale = mPos.scale * Tile.SIZE; moveTo(mPos.x - p.x / tileScale, mPos.y - p.y / tileScale); @@ -94,7 +99,9 @@ public class ViewController extends Viewport { * @param pivotY * @return true if scale was changed */ - public synchronized boolean scaleMap(float scale, float pivotX, float pivotY) { + public boolean scaleMap(float scale, float pivotX, float pivotY) { + ThreadUtils.assertMainThread(); + // just sanitize input //scale = FastMath.clamp(scale, 0.5f, 2); if (scale < 0.000001) @@ -126,7 +133,8 @@ public class ViewController extends Viewport { * @param pivotX * @param pivotY */ - public synchronized void rotateMap(double radians, float pivotX, float pivotY) { + public void rotateMap(double radians, float pivotX, float pivotY) { + ThreadUtils.assertMainThread(); double rsin = Math.sin(radians); double rcos = Math.cos(radians); @@ -139,7 +147,9 @@ public class ViewController extends Viewport { setRotation(mPos.bearing + Math.toDegrees(radians)); } - public synchronized void setRotation(double degree) { + public void setRotation(double degree) { + ThreadUtils.assertMainThread(); + while (degree > 180) degree -= 360; while (degree < -180) @@ -149,11 +159,15 @@ public class ViewController extends Viewport { updateMatrices(); } - public synchronized boolean tiltMap(float move) { + public boolean tiltMap(float move) { + ThreadUtils.assertMainThread(); + return setTilt(mPos.tilt + move); } - public synchronized boolean setTilt(float tilt) { + public boolean setTilt(float tilt) { + ThreadUtils.assertMainThread(); + tilt = FastMath.clamp(tilt, 0, MAX_TILT); if (tilt == mPos.tilt) return false; @@ -162,7 +176,9 @@ public class ViewController extends Viewport { return true; } - public synchronized void setMapPosition(MapPosition mapPosition) { + public void setMapPosition(MapPosition mapPosition) { + ThreadUtils.assertMainThread(); + mPos.scale = FastMath.clamp(mapPosition.scale, MIN_SCALE, MAX_SCALE); mPos.x = mapPosition.x; mPos.y = mapPosition.y; @@ -199,4 +215,30 @@ public class ViewController extends Viewport { /* (AB)^-1 = B^-1*A^-1, invert projection */ mUnprojMatrix.multiplyMM(mTmpMatrix, mProjMatrixInverse); } + + public final Viewport mNextFrame = new Viewport(); + + /** synchronize on this object when doing multiple calls on it */ + public final Viewport getSyncViewport() { + return mNextFrame; + } + + void syncViewport() { + synchronized (mNextFrame) { + mNextFrame.copy(this); + } + } + + public boolean getSyncViewport(Viewport v) { + synchronized (mNextFrame) { + return v.copy(mNextFrame); + } + } + + public boolean getSyncMapPosition(MapPosition mapPosition) { + synchronized (mNextFrame) { + return mNextFrame.getMapPosition(mapPosition); + } + } + } diff --git a/vtm/src/org/oscim/map/Viewport.java b/vtm/src/org/oscim/map/Viewport.java index fd07da6d..ac7b2cec 100644 --- a/vtm/src/org/oscim/map/Viewport.java +++ b/vtm/src/org/oscim/map/Viewport.java @@ -87,7 +87,7 @@ public class Viewport { * @return true iff current position is different from * passed position. */ - public synchronized boolean getMapPosition(MapPosition pos) { + public boolean getMapPosition(MapPosition pos) { boolean changed = (pos.scale != mPos.scale || pos.x != mPos.x @@ -114,7 +114,7 @@ public class Viewport { * @param box float[8] will be set. * @param add increase extents of box */ - public synchronized void getMapExtents(float[] box, float add) { + public void getMapExtents(float[] box, float add) { float t = getDepth(1); float t2 = getDepth(-1); @@ -143,6 +143,8 @@ public class Viewport { * Get Z-value of the map-plane for a point on screen - * calculate the intersection of a ray from camera origin * and the map plane + * TODO use + * www.comp.nus.edu.sg/~lowkl/publications/lowk_persp_interp_techrep.pdf */ protected float getDepth(float y) { // origin is moved by VIEW_DISTANCE @@ -244,7 +246,7 @@ public class Viewport { * @param y screen coordinate * @return the corresponding GeoPoint */ - public synchronized GeoPoint fromScreenPoint(float x, float y) { + public GeoPoint fromScreenPoint(float x, float y) { fromScreenPoint(x, y, mMovePoint); return new GeoPoint( MercatorProjection.toLatitude(mMovePoint.y), @@ -257,7 +259,7 @@ public class Viewport { * @param x screen coordinate * @param y screen coordinate */ - public synchronized void fromScreenPoint(double x, double y, Point out) { + public void fromScreenPoint(double x, double y, Point out) { // scale to -1..1 float mx = (float) (1 - (x / mWidth * 2)); float my = (float) (1 - (y / mHeight * 2)); @@ -294,7 +296,7 @@ public class Viewport { * @param geoPoint the GeoPoint * @param out Point projected to screen pixel relative to center */ - public synchronized void toScreenPoint(GeoPoint geoPoint, Point out) { + public void toScreenPoint(GeoPoint geoPoint, Point out) { MercatorProjection.project(geoPoint, out); toScreenPoint(out.x, out.y, out); } @@ -304,7 +306,7 @@ public class Viewport { * * @param out Point projected to screen coordinate */ - public synchronized void toScreenPoint(double x, double y, Point out) { + public void toScreenPoint(double x, double y, Point out) { double cs = mPos.scale * Tile.SIZE; double cx = mPos.x * cs; @@ -322,20 +324,17 @@ public class Viewport { out.y = -(mv[1] * (mHeight / 2)); } - public synchronized boolean copy(Viewport viewport) { + protected boolean copy(Viewport viewport) { + mHeight = viewport.mHeight; + mWidth = viewport.mWidth; + mProjMatrix.copy(viewport.mProjMatrix); + mProjMatrixUnscaled.copy(viewport.mProjMatrixUnscaled); + mProjMatrixInverse.copy(viewport.mProjMatrixInverse); + mUnprojMatrix.copy(viewport.mUnprojMatrix); mRotationMatrix.copy(viewport.mRotationMatrix); mViewMatrix.copy(viewport.mViewMatrix); mViewProjMatrix.copy(viewport.mViewProjMatrix); return viewport.getMapPosition(mPos); } - - public synchronized void initFrom(Viewport viewport) { - mProjMatrix.copy(viewport.mProjMatrix); - mProjMatrixUnscaled.copy(viewport.mProjMatrixUnscaled); - mProjMatrixInverse.copy(viewport.mProjMatrixInverse); - - mHeight = viewport.mHeight; - mWidth = viewport.mWidth; - } } diff --git a/vtm/src/org/oscim/renderer/GLViewport.java b/vtm/src/org/oscim/renderer/GLViewport.java index e735f7c2..c6f25a2d 100644 --- a/vtm/src/org/oscim/renderer/GLViewport.java +++ b/vtm/src/org/oscim/renderer/GLViewport.java @@ -1,6 +1,7 @@ package org.oscim.renderer; import org.oscim.core.MapPosition; +import org.oscim.map.Map; import org.oscim.map.Viewport; public class GLViewport extends Viewport { @@ -40,8 +41,8 @@ public class GLViewport extends Viewport { return changed; } - void setFrom(Viewport viewport) { - changed = super.copy(viewport); + void setFrom(Map map) { + changed = map.viewport().getSyncViewport(this); getMapExtents(plane, 0); } diff --git a/vtm/src/org/oscim/renderer/MapRenderer.java b/vtm/src/org/oscim/renderer/MapRenderer.java index 81d40e93..63fe7152 100644 --- a/vtm/src/org/oscim/renderer/MapRenderer.java +++ b/vtm/src/org/oscim/renderer/MapRenderer.java @@ -70,10 +70,28 @@ public class MapRenderer { mClearColor = GLUtils.colorToFloat(color); } + private final Runnable renderBegin = new Runnable() { + @Override + public void run() { + mMap.beginFrame(); + } + }; + private final Runnable renderDone = new Runnable() { + @Override + public void run() { + mMap.doneFrame(); + } + }; + public void onDrawFrame() { frametime = System.currentTimeMillis(); + + mMap.post(renderBegin); + draw(); + mMap.post(renderDone); + mBufferPool.releaseBuffers(); TextureItem.disposeTextures(); } @@ -98,8 +116,7 @@ public class MapRenderer { GLState.bindElementBuffer(-1); GLState.bindVertexBuffer(-1); - mMap.animator().updateAnimation(); - mViewport.setFrom(mMap.viewport()); + mViewport.setFrom(mMap); if (GLAdapter.debugView) { /* modify this to scale only the view, to see @@ -145,8 +162,6 @@ public class MapRenderer { if (width <= 0 || height <= 0) return; - //mMap.viewport().getMatrix(null, mMatrices.proj, null); - mViewport.initFrom(mMap.viewport()); gl.viewport(0, 0, width, height); //GL.scissor(0, 0, width, height); diff --git a/vtm/src/org/oscim/utils/ThreadUtils.java b/vtm/src/org/oscim/utils/ThreadUtils.java new file mode 100644 index 00000000..2f7d5344 --- /dev/null +++ b/vtm/src/org/oscim/utils/ThreadUtils.java @@ -0,0 +1,20 @@ +package org.oscim.utils; + +public class ThreadUtils { + + private static Thread MAIN_THREAD; + + public static void assertMainThread() { + if (MAIN_THREAD != Thread.currentThread()) + throw new RuntimeException("Access from non-main thread!"); + } + + public static boolean isMainThread() { + return MAIN_THREAD == Thread.currentThread(); + } + + public static void init() { + MAIN_THREAD = Thread.currentThread(); + } + +}