Skip to content
Snippets Groups Projects
Commit 1db8f1db authored by Tobias Pietzsch's avatar Tobias Pietzsch
Browse files

WIP

parent d5d2e9e0
No related branches found
No related tags found
No related merge requests found
...@@ -28,12 +28,8 @@ ...@@ -28,12 +28,8 @@
*/ */
package bdv.viewer.render; package bdv.viewer.render;
import bdv.cache.CacheControl;
import bdv.util.MovingAverage;
import bdv.viewer.ViewerState;
import bdv.viewer.render.ScreenScales.IntervalRenderData;
import bdv.viewer.render.ScreenScales.ScreenScale;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import net.imglib2.Interval; import net.imglib2.Interval;
import net.imglib2.RandomAccessibleInterval; import net.imglib2.RandomAccessibleInterval;
import net.imglib2.Volatile; import net.imglib2.Volatile;
...@@ -44,6 +40,12 @@ import net.imglib2.ui.PainterThread; ...@@ -44,6 +40,12 @@ import net.imglib2.ui.PainterThread;
import net.imglib2.ui.RenderTarget; import net.imglib2.ui.RenderTarget;
import net.imglib2.util.Intervals; import net.imglib2.util.Intervals;
import bdv.cache.CacheControl;
import bdv.util.MovingAverage;
import bdv.viewer.ViewerState;
import bdv.viewer.render.ScreenScales.IntervalRenderData;
import bdv.viewer.render.ScreenScales.ScreenScale;
/** /**
* A renderer that uses a coarse-to-fine rendering scheme. First, a small target * A renderer that uses a coarse-to-fine rendering scheme. First, a small target
* image at a fraction of the canvas resolution is rendered. Then, increasingly * image at a fraction of the canvas resolution is rendered. Then, increasingly
...@@ -191,6 +193,12 @@ public class MultiResolutionRenderer ...@@ -191,6 +193,12 @@ public class MultiResolutionRenderer
*/ */
private boolean newIntervalRequest; private boolean newIntervalRequest;
// =========== intervals ==========================================================================================
private RenderResult currentRenderResult;
private final RenderResult intervalResult;
private IntervalRenderData intervalRenderData;
// =========== intervals ==========================================================================================
/** /**
* @param display * @param display
* The canvas that will display the images we render. * The canvas that will display the images we render.
...@@ -256,6 +264,59 @@ public class MultiResolutionRenderer ...@@ -256,6 +264,59 @@ public class MultiResolutionRenderer
accumulateProjectorFactory ); accumulateProjectorFactory );
} }
/**
* Request a repaint of the display from the painter thread. The painter
* thread will trigger a {@link #paint} as soon as possible (that is,
* immediately or after the currently running {@link #paint} has completed).
*/
public synchronized void requestRepaint()
{
if ( renderingMayBeCancelled && projector != null )
projector.cancel();
newFrameRequest = true;
painterThread.requestRepaint();
}
/**
* Request a repaint of the given {@code interval} of the display from the
* painter thread. The painter thread will trigger a {@link #paint} as soon
* as possible (that is, immediately or after the currently running
* {@link #paint} has completed).
*/
public synchronized void requestRepaint( final Interval interval )
{
if ( !intervalMode && !renderingMayBeCancelled )
{
/*
* We are currently rendering a full frame at the coarsest
* resolution. There is no point in painting an interval now. Just
* request a new full frame.
*/
newFrameRequest = true;
}
else
{
if ( renderingMayBeCancelled && projector != null )
projector.cancel();
screenScales.requestInterval( interval );
newIntervalRequest = true;
}
painterThread.requestRepaint();
}
/**
* DON'T USE THIS.
* <p>
* This is a work around for JDK bug
* https://bugs.openjdk.java.net/browse/JDK-8029147 which leads to
* ViewerPanel not being garbage-collected when ViewerFrame is closed. So
* instead we need to manually let go of resources...
*/
public void kill()
{
projector = null;
renderStorage.clear();
}
/** /**
* Render image at the {@link #requestedScreenScaleIndex requested screen * Render image at the {@link #requestedScreenScaleIndex requested screen
...@@ -268,15 +329,14 @@ public class MultiResolutionRenderer ...@@ -268,15 +329,14 @@ public class MultiResolutionRenderer
if ( screenW <= 0 || screenH <= 0 ) if ( screenW <= 0 || screenH <= 0 )
return false; return false;
final boolean resized;
final boolean newFrame; final boolean newFrame;
final boolean newInterval; final boolean newInterval;
final boolean paintInterval; final boolean paintInterval;
final boolean prepareNextFrame; final boolean prepareNextFrame;
boolean createProjector = false; final boolean createProjector;
synchronized ( this ) synchronized ( this )
{ {
resized = screenScales.checkResize( screenW, screenH ); final boolean resized = screenScales.checkResize( screenW, screenH );
newFrame = newFrameRequest || resized; newFrame = newFrameRequest || resized;
if ( newFrame ) if ( newFrame )
...@@ -302,6 +362,11 @@ public class MultiResolutionRenderer ...@@ -302,6 +362,11 @@ public class MultiResolutionRenderer
if ( createProjector ) if ( createProjector )
intervalRenderData = screenScales.pullIntervalRenderData( requestedIntervalScaleIndex, currentScreenScaleIndex ); intervalRenderData = screenScales.pullIntervalRenderData( requestedIntervalScaleIndex, currentScreenScaleIndex );
} }
else
{
createProjector = newFrame || ( requestedScreenScaleIndex != currentScreenScaleIndex );
}
newFrameRequest = false; newFrameRequest = false;
newIntervalRequest = false; newIntervalRequest = false;
...@@ -327,26 +392,18 @@ public class MultiResolutionRenderer ...@@ -327,26 +392,18 @@ public class MultiResolutionRenderer
// whether to request a newFrame, in case that a new projector is created in full frame mode // whether to request a newFrame, in case that a new projector is created in full frame mode
boolean requestNewFrameIfIncomplete = false; boolean requestNewFrameIfIncomplete = false;
if ( paintInterval ) synchronized ( this )
{ {
intervalResult.init( intervalRenderData.width(), intervalRenderData.height() ); if ( createProjector )
intervalResult.setScaleFactor( intervalRenderData.scale() );
synchronized ( this )
{ {
if ( createProjector ) if ( paintInterval )
{ {
intervalResult.init( intervalRenderData.width(), intervalRenderData.height() );
intervalResult.setScaleFactor( intervalRenderData.scale() );
projector = createProjector( currentViewerState, requestedIntervalScaleIndex, intervalResult.getScreenImage(), intervalRenderData.offsetX(), intervalRenderData.offsetY() ); projector = createProjector( currentViewerState, requestedIntervalScaleIndex, intervalResult.getScreenImage(), intervalRenderData.offsetX(), intervalRenderData.offsetY() );
renderingMayBeCancelled = !newInterval; renderingMayBeCancelled = !newInterval;
} }
p = projector; else
}
}
else
{
createProjector = newFrame || ( requestedScreenScaleIndex != currentScreenScaleIndex );
synchronized ( this )
{
if ( createProjector )
{ {
final ScreenScale screenScale = screenScales.get( requestedScreenScaleIndex ); final ScreenScale screenScale = screenScales.get( requestedScreenScaleIndex );
...@@ -360,8 +417,8 @@ public class MultiResolutionRenderer ...@@ -360,8 +417,8 @@ public class MultiResolutionRenderer
requestNewFrameIfIncomplete = projectorFactory.requestNewFrameIfIncomplete(); requestNewFrameIfIncomplete = projectorFactory.requestNewFrameIfIncomplete();
renderingMayBeCancelled = !newFrame; renderingMayBeCancelled = !newFrame;
} }
p = projector;
} }
p = projector;
} }
...@@ -377,37 +434,31 @@ public class MultiResolutionRenderer ...@@ -377,37 +434,31 @@ public class MultiResolutionRenderer
{ {
if ( paintInterval ) if ( paintInterval )
{ {
if ( createProjector ) currentIntervalScaleIndex = requestedIntervalScaleIndex;
currentIntervalScaleIndex = requestedIntervalScaleIndex;
currentRenderResult.patch( intervalResult, intervalRenderData.targetInterval(), intervalRenderData.tx(), intervalRenderData.ty() ); currentRenderResult.patch( intervalResult, intervalRenderData.targetInterval(), intervalRenderData.tx(), intervalRenderData.ty() );
if ( currentIntervalScaleIndex > currentScreenScaleIndex ) if ( currentIntervalScaleIndex > currentScreenScaleIndex )
iterateRepaintInterval( currentIntervalScaleIndex - 1 ); iterateRepaintInterval( currentIntervalScaleIndex - 1 );
else if ( p.isValid() ) else if ( p.isValid() )
{ {
// if full frame rendering was not yet complete
if ( requestedScreenScaleIndex >= 0 ) if ( requestedScreenScaleIndex >= 0 )
{ {
// go back to "normal" rendering // go back to full frame rendering
intervalMode = false; intervalMode = false;
renderingMayBeCancelled = false;
if ( requestedScreenScaleIndex == currentScreenScaleIndex ) if ( requestedScreenScaleIndex == currentScreenScaleIndex )
++currentScreenScaleIndex; ++currentScreenScaleIndex;
painterThread.requestRepaint(); painterThread.requestRepaint();
} }
} }
else else
{
usleep();
intervalRenderData.reRequest();
iterateRepaintInterval( currentIntervalScaleIndex ); iterateRepaintInterval( currentIntervalScaleIndex );
}
} }
else else
{ {
currentScreenScaleIndex = requestedScreenScaleIndex;
if ( createProjector ) if ( createProjector )
{ {
currentScreenScaleIndex = requestedScreenScaleIndex;
renderResult.setUpdated(); renderResult.setUpdated();
( ( RenderTarget ) display ).setRenderResult( renderResult ); ( ( RenderTarget ) display ).setRenderResult( renderResult );
currentRenderResult = renderResult; currentRenderResult = renderResult;
...@@ -423,18 +474,11 @@ public class MultiResolutionRenderer ...@@ -423,18 +474,11 @@ public class MultiResolutionRenderer
if ( !p.isValid() && requestNewFrameIfIncomplete ) if ( !p.isValid() && requestNewFrameIfIncomplete )
requestRepaint(); requestRepaint();
else if ( currentScreenScaleIndex > 0 ) else if ( p.isValid() && currentScreenScaleIndex == 0 )
iterateRepaint( currentScreenScaleIndex - 1 );
else if ( p.isValid() )
{
// indicate that rendering is complete // indicate that rendering is complete
requestedScreenScaleIndex = -1; requestedScreenScaleIndex = -1;
}
else else
{ iterateRepaint( Math.max( 0, currentScreenScaleIndex - 1 ) );
usleep();
iterateRepaint( currentScreenScaleIndex );
}
} }
} }
// if rendering was cancelled... // if rendering was cancelled...
...@@ -458,49 +502,37 @@ public class MultiResolutionRenderer ...@@ -458,49 +502,37 @@ public class MultiResolutionRenderer
*/ */
private void iterateRepaint( final int screenScaleIndex ) private void iterateRepaint( final int screenScaleIndex )
{ {
if ( screenScaleIndex == currentScreenScaleIndex )
usleep();
requestedScreenScaleIndex = screenScaleIndex; requestedScreenScaleIndex = screenScaleIndex;
painterThread.requestRepaint(); painterThread.requestRepaint();
} }
/** private void iterateRepaintInterval( final int intervalScaleIndex )
* Request a repaint of the display from the painter thread. The painter
* thread will trigger a {@link #paint} as soon as possible (that is,
* immediately or after the currently running {@link #paint} has completed).
*/
public synchronized void requestRepaint()
{
if ( renderingMayBeCancelled && projector != null )
projector.cancel();
newFrameRequest = true;
painterThread.requestRepaint();
}
public synchronized void requestRepaint( final Interval screenInterval )
{ {
if ( renderingMayBeCancelled || intervalMode ) if ( intervalScaleIndex == currentIntervalScaleIndex )
{ {
if ( projector != null ) intervalRenderData.reRequest();
projector.cancel(); usleep();
screenScales.requestInterval( screenInterval );
newIntervalRequest = true;
} }
else requestedIntervalScaleIndex = intervalScaleIndex;
newFrameRequest = true;
painterThread.requestRepaint(); painterThread.requestRepaint();
} }
/** /**
* DON'T USE THIS. * Wait for 1ms so that fetcher threads get a chance to do work.
* <p>
* This is a work around for JDK bug
* https://bugs.openjdk.java.net/browse/JDK-8029147 which leads to
* ViewerPanel not being garbage-collected when ViewerFrame is closed. So
* instead we need to manually let go of resources...
*/ */
public void kill() private void usleep()
{ {
projector = null; try
renderStorage.clear(); {
Thread.sleep( 1 );
}
catch ( final InterruptedException e )
{
// restore interrupted state
Thread.currentThread().interrupt();
}
} }
private VolatileProjector createProjector( private VolatileProjector createProjector(
...@@ -529,30 +561,4 @@ public class MultiResolutionRenderer ...@@ -529,30 +561,4 @@ public class MultiResolutionRenderer
CacheIoTiming.getIoTimeBudget().reset( iobudget ); CacheIoTiming.getIoTimeBudget().reset( iobudget );
return projector; return projector;
} }
// =========== intervals ==========================================================================================
private RenderResult currentRenderResult;
private final RenderResult intervalResult;
private IntervalRenderData intervalRenderData;
private void iterateRepaintInterval( final int intervalScaleIndex )
{
requestedIntervalScaleIndex = intervalScaleIndex;
painterThread.requestRepaint();
}
private void usleep()
{
try
{
Thread.sleep( 1 );
}
catch ( final InterruptedException e )
{
// restore interrupted state
Thread.currentThread().interrupt();
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment