Skip to content

Commit

Permalink
Several additions to the new display sync mechanism
Browse files Browse the repository at this point in the history
- Adds IDisplaySynchronizer, which regroups the three types of sync
expected (updating, realisation, rendering);
- Simplifies further the update thread in LayeredDisplayView
- Should fix issue #3166
  • Loading branch information
AlexisDrogoul committed Aug 15, 2021
1 parent 9b3df8f commit 5f2a301
Show file tree
Hide file tree
Showing 10 changed files with 194 additions and 230 deletions.
29 changes: 2 additions & 27 deletions msi.gama.core/src/msi/gama/common/interfaces/IDisplaySurface.java
Expand Up @@ -14,7 +14,6 @@
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.concurrent.Semaphore;

import org.locationtech.jts.geom.Envelope;

Expand Down Expand Up @@ -164,7 +163,7 @@ GamaPoint getModelCoordinatesFrom(final int xOnScreen, final int yOnScreen, fina
/**
* @return true if the surface is considered as "realized" (i.e. displayed on the UI)
*/
boolean isRealized();
// boolean isRealized();

/**
* @return true if the surface has been "rendered" (i.e. all the layers have been displayed)
Expand Down Expand Up @@ -199,30 +198,6 @@ default boolean canTriggerContextualMenu() {
return !getManager().hasMouseMenuEventLayer();
}

default void resynchronizeRenderLock() {
getRenderLock().drainPermits();
}

/**
* Makes any thread calling this method wait until either the scene is rendered or the surface is disposed
*/
default void acquireRenderLock() {

try {
getRenderLock().acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

/**
* Allows any object calling this method to release the thread waiting for the scene to be rendered (called by the
* rendering processes or when this surface is disposed)
*/
default void releaseRenderLock() {
getRenderLock().release();
}

Semaphore getRenderLock();
default void setDisplaySynchronizer(final IDisplaySynchronizer layeredDisplaySynchronizer) {}

}
@@ -0,0 +1,36 @@
package msi.gama.common.interfaces;

/**
* A simple object that can synchronize the 3 threads in charge of the drawing of the displays: simulation thread
* (simulation-view update mechanism), update thread, and rendering thread
*
* @author drogoul
*
*/
public interface IDisplaySynchronizer {
/**
* Allows any object calling this method to release the thread waiting for the scene to be rendered (called by the
* rendering processes or when this surface is disposed)
*/
void signalRenderingIsFinished();

/**
* Makes any thread calling this method wait until either the scene is rendered or the surface is disposed
*/
void waitForRenderingToBeFinished();

/**
* Allows any object calling this method to release the thread waiting for the view to be updated
*/
void authorizeViewUpdate();

/**
* Makes any thread calling this method wait until can be updated
*/
void waitForViewUpdateAuthorisation();

void waitForSurfaceToBeRealized();

void signalSurfaceIsRealized();

}
25 changes: 5 additions & 20 deletions msi.gama.core/src/msi/gama/outputs/ImageDisplaySurface.java
Expand Up @@ -19,7 +19,6 @@
import java.io.FileOutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Semaphore;

import javax.imageio.ImageIO;

Expand Down Expand Up @@ -465,11 +464,11 @@ public Envelope getVisibleRegionForLayer(final ILayer currentLayer) {
public int getFPS() {
return 0;
}

@Override
public boolean isRealized() {
return true;
}
//
// @Override
// public boolean isRealized() {
// return true;
// }

/**
* Method isRendered()
Expand Down Expand Up @@ -530,18 +529,4 @@ public void setMenuManager(final Object displaySurfaceMenu) {

}

@Override
public Semaphore getRenderLock() {
return null;
}

@Override
public void acquireRenderLock() {}

@Override
public void releaseRenderLock() {}

@Override
public void resynchronizeRenderLock() {}

}
25 changes: 5 additions & 20 deletions msi.gama.core/src/msi/gama/outputs/display/NullDisplaySurface.java
Expand Up @@ -14,7 +14,6 @@
import java.awt.image.BufferedImage;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Semaphore;

import org.locationtech.jts.geom.Envelope;

Expand Down Expand Up @@ -349,11 +348,11 @@ public Envelope getVisibleRegionForLayer(final ILayer currentLayer) {
public int getFPS() {
return 0;
}

@Override
public boolean isRealized() {
return true;
}
//
// @Override
// public boolean isRealized() {
// return true;
// }

/**
* Method isRendered()
Expand Down Expand Up @@ -419,18 +418,4 @@ public void setMenuManager(final Object displaySurfaceMenu) {

}

@Override
public Semaphore getRenderLock() {
return null;
}

@Override
public void acquireRenderLock() {}

@Override
public void releaseRenderLock() {}

@Override
public void resynchronizeRenderLock() {}

}
Expand Up @@ -51,6 +51,7 @@
import org.locationtech.jts.geom.Envelope;

import msi.gama.common.interfaces.IDisplaySurface;
import msi.gama.common.interfaces.IDisplaySynchronizer;
import msi.gama.common.interfaces.IGraphics;
import msi.gama.common.interfaces.IKeyword;
import msi.gama.common.interfaces.ILayer;
Expand Down Expand Up @@ -114,7 +115,7 @@ public class Java2DDisplaySurface extends JPanel implements IDisplaySurface {

private IScope scope;
int frames;
private volatile boolean realized = false;
private IDisplaySynchronizer synchronizer;
private volatile boolean rendered = false;
Set<IEventLayerListener> listeners = new HashSet<>();
Point mousePosition;
Expand Down Expand Up @@ -192,11 +193,6 @@ public void draggedTo(final int x, final int y) {
setMousePosition(x, y);
updateDisplay(true);
}
//
// public void setMousePosition(final Point point) {
// mousePosition = point;
//
// }

@Override
public Point getMousePosition() {
Expand Down Expand Up @@ -237,9 +233,7 @@ public void outputReloaded() {
setDisplayScope(output.getScope().copy("in java2D display "));
// We disable error reporting
if (!GamaPreferences.Runtime.ERRORS_IN_DISPLAYS.getValue()) { getScope().disableErrorReporting(); }

layerManager.outputChanged();

resizeImage(getWidth(), getHeight(), true);
if (zoomFit) { zoomFit(); }
updateDisplay(true);
Expand All @@ -260,9 +254,7 @@ Point getOrigin() {
}

@Override
public void setFont(final Font f) {
// super.setFont(null);
}
public void setFont(final Font f) {}

@Override
public BufferedImage getImage(final int w, final int h) {
Expand Down Expand Up @@ -419,8 +411,6 @@ public boolean resizeImage(final int x, final int y, final boolean force) {

@Override
public void paintComponent(final Graphics g) {

realized = true;
final AWTDisplayGraphics gg = getIGraphics();
if (gg == null) return;
DEBUG.OUT("-- Surface effectively painting on Java2D context");
Expand All @@ -435,13 +425,15 @@ public void paintComponent(final Graphics g) {
temp_focus = null;
focusOn(geometry);
rendered = true;
synchronizer.signalRenderingIsFinished();
return;
}

// TODO Verify that the following expressions should not be also included in the "focus" block
g2d.dispose();
frames++;
rendered = true;
if (synchronizer != null) { synchronizer.signalRenderingIsFinished(); }
}

AWTDisplayGraphics getIGraphics() {
Expand Down Expand Up @@ -599,7 +591,7 @@ public void runAndUpdate(final Runnable r) {
public void dispose() {
getData().removeListener(this);
if (disposed) return;
setRealized(false);
// setRealized(false);
disposed = true;
if (layerManager != null) { layerManager.dispose(); }

Expand Down Expand Up @@ -636,13 +628,6 @@ public void setBounds(final int arg0, final int arg1, final int arg2, final int
if (arg2 == 0 && arg3 == 0) return;
super.setBounds(arg0, arg1, arg2, arg3);
}
//
// @Override
// public void setBounds(final Rectangle r) {
// DEBUG.OUT("-- Java2D surface set bounds to " + r);
// if (r.width < 1 && r.height < 1) { return; }
// super.setBounds(r);
// }

double applyZoom(final double factor) {
double real_factor = Math.min(factor, 10 / getZoomLevel());
Expand Down Expand Up @@ -723,15 +708,6 @@ public void changed(final Changes property, final Object value) {

}

@Override
public boolean isRealized() {
return realized;
}

public void setRealized(final boolean b) {
realized = b;
}

@Override
public boolean isRendered() {
return rendered;
Expand All @@ -752,8 +728,9 @@ public Font computeFont(final Font f) {
}

@Override
public Semaphore getRenderLock() {
return renderLock;
public void setDisplaySynchronizer(final IDisplaySynchronizer s) {
synchronizer = s;
synchronizer.signalSurfaceIsRealized();
}

}
Expand Up @@ -95,7 +95,7 @@ public void draw(final OpenGL gl) {
});
gl.setZIncrement(0);
rendered = true;
gl.getRenderer().getSurface().releaseRenderLock();
gl.getRenderer().getSurface().synchronizer.signalRenderingIsFinished();
gl.pop(GLMatrixFunc.GL_MODELVIEW);
}

Expand Down
Expand Up @@ -16,8 +16,6 @@

import org.eclipse.swt.widgets.Composite;

import com.jogamp.opengl.util.GLDrawableUtil;

import msi.gama.runtime.GAMA;
import ummisco.gama.dev.utils.DEBUG;
import ummisco.gama.opengl.renderer.helpers.CameraHelper;
Expand Down Expand Up @@ -63,11 +61,4 @@ public List<String> getCameraNames() {
return new ArrayList<>(CameraHelper.PRESETS.keySet());
}

@Override
public void fullScreenSet() {
// DEBUG.OUT("Invoking explicit reshape + display");
getDisplaySurface().renderer.getCanvas().invoke(false,
new GLDrawableUtil.ReshapeGLEventListener(getDisplaySurface().renderer, true));
}

}

0 comments on commit 5f2a301

Please sign in to comment.