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

Refactoring and javadoc.

parent 5fdbaf77
No related branches found
No related tags found
No related merge requests found
...@@ -116,7 +116,8 @@ public class MultiResolutionRenderer ...@@ -116,7 +116,8 @@ public class MultiResolutionRenderer
private final long[] iobudget = new long[] { 100l * 1000000l, 10l * 1000000l }; private final long[] iobudget = new long[] { 100l * 1000000l, 10l * 1000000l };
/** /**
* TODO javadoc * Maintains current sizes and transforms at every screen scale level.
* Records interval rendering requests.
*/ */
private final ScreenScales screenScales; private final ScreenScales screenScales;
...@@ -133,22 +134,11 @@ public class MultiResolutionRenderer ...@@ -133,22 +134,11 @@ public class MultiResolutionRenderer
/** /**
* Currently active projector, used to re-paint the display. It maps the * Currently active projector, used to re-paint the display. It maps the
* source data to {@code ©screenImages}. * source data to {@code ©screenImages}. {@code projector.cancel()} can be
* used to cancel the ongoing rendering operation.
*/ */
private VolatileProjector projector; private VolatileProjector projector;
/**
* Screen scale of the last successful (not cancelled) rendering pass in
* full-frame mode.
*/
private int currentScreenScaleIndex;
/**
* The index of the screen scale which should be rendered next in full-frame
* mode.
*/
private int requestedScreenScaleIndex;
/** /**
* Whether the current rendering operation may be cancelled (to start a new * Whether the current rendering operation may be cancelled (to start a new
* one). Rendering may be cancelled unless we are rendering at the * one). Rendering may be cancelled unless we are rendering at the
...@@ -158,6 +148,7 @@ public class MultiResolutionRenderer ...@@ -158,6 +148,7 @@ public class MultiResolutionRenderer
/** /**
* Snapshot of the ViewerState that is currently being rendered. * Snapshot of the ViewerState that is currently being rendered.
* A new snapshot is taken in the first {@code paint()} pass after a (full frame) {@link #requestRepaint()}
*/ */
private ViewerState currentViewerState; private ViewerState currentViewerState;
...@@ -167,10 +158,10 @@ public class MultiResolutionRenderer ...@@ -167,10 +158,10 @@ public class MultiResolutionRenderer
private int currentNumVisibleSources; private int currentNumVisibleSources;
/** /**
* Whether a full repaint was {@link #requestRepaint() requested}. This will * The last successfully rendered (not cancelled) full frame result.
* cause {@link CacheControl#prepareNextFrame()}. * This result is by full frame refinement passes and/or interval rendering passes.
*/ */
private boolean newFrameRequest; private RenderResult currentRenderResult;
/** /**
* If {@code true}, then we are painting intervals currently. * If {@code true}, then we are painting intervals currently.
...@@ -178,26 +169,70 @@ public class MultiResolutionRenderer ...@@ -178,26 +169,70 @@ public class MultiResolutionRenderer
*/ */
private boolean intervalMode; private boolean intervalMode;
/*
*
* === FULL FRAME RENDERING ===
*
*/
/**
* Screen scale of the last successful (not cancelled) rendering pass in
* full-frame mode.
*/
private int currentScreenScaleIndex;
/**
* The index of the screen scale which should be rendered next in full-frame
* mode.
*/
private int requestedScreenScaleIndex;
/**
* Whether a full frame repaint was {@link #requestRepaint() requested}.
* Supersedes {@link #newIntervalRequest}.
*/
private boolean newFrameRequest;
/*
*
* === INTERVAL RENDERING ===
*
*/
/** /**
* Screen scale of the last successful (not cancelled) rendering pass in * Screen scale of the last successful (not cancelled) rendering pass in
* interval mode. * interval mode.
*/ */
private int currentIntervalScaleIndex; private int currentIntervalScaleIndex;
/**
* The index of the screen scale which should be rendered next in interval
* mode.
*/
private int requestedIntervalScaleIndex; private int requestedIntervalScaleIndex;
/** /**
* Whether repainting of an interval was {@link #requestRepaint(Interval) * Whether repainting of an interval was {@link #requestRepaint(Interval)
* requested}. This will cause {@link CacheControl#prepareNextFrame()}. * requested}. The union of all pending intervals are recorded in
* Pending interval requests are obsoleted by full repaint requests. * {@link #screenScales}. Pending interval requests are obsoleted by full
* frame repaints requests ({@link #newFrameRequest}).
*/ */
private boolean newIntervalRequest; private boolean newIntervalRequest;
// =========== intervals ========================================================================================== /**
private RenderResult currentRenderResult; * Re-used for all interval rendering.
*/
private final RenderResult intervalResult; private final RenderResult intervalResult;
/**
* Currently rendering interval. This is pulled from {@link #screenScales}
* at the start of {@code paint()}, which clears requested intervals at
* {@link #currentIntervalScaleIndex} or coarser. (This ensures that new
* interval requests arriving during rendering are not missed. If the
* requested intervals would be cleared after rendering, this might happen.
* Instead we re-request the pulled intervals, if rendering fails.)
*/
private IntervalRenderData intervalRenderData; private IntervalRenderData intervalRenderData;
// =========== intervals ==========================================================================================
/** /**
* @param display * @param display
...@@ -315,6 +350,7 @@ public class MultiResolutionRenderer ...@@ -315,6 +350,7 @@ public class MultiResolutionRenderer
public void kill() public void kill()
{ {
projector = null; projector = null;
currentRenderResult = null;
renderStorage.clear(); renderStorage.clear();
} }
...@@ -331,7 +367,6 @@ public class MultiResolutionRenderer ...@@ -331,7 +367,6 @@ public class MultiResolutionRenderer
final boolean newFrame; final boolean newFrame;
final boolean newInterval; final boolean newInterval;
final boolean paintInterval;
final boolean prepareNextFrame; final boolean prepareNextFrame;
final boolean createProjector; final boolean createProjector;
synchronized ( this ) synchronized ( this )
...@@ -354,19 +389,16 @@ public class MultiResolutionRenderer ...@@ -354,19 +389,16 @@ public class MultiResolutionRenderer
} }
prepareNextFrame = newFrame || newInterval; prepareNextFrame = newFrame || newInterval;
paintInterval = intervalMode; renderingMayBeCancelled = !prepareNextFrame;
if ( paintInterval ) if ( intervalMode )
{ {
createProjector = newInterval || ( requestedIntervalScaleIndex != currentIntervalScaleIndex ); createProjector = newInterval || ( requestedIntervalScaleIndex != currentIntervalScaleIndex );
if ( createProjector ) if ( createProjector )
intervalRenderData = screenScales.pullIntervalRenderData( requestedIntervalScaleIndex, currentScreenScaleIndex ); intervalRenderData = screenScales.pullIntervalRenderData( requestedIntervalScaleIndex, currentScreenScaleIndex );
} }
else else
{
createProjector = newFrame || ( requestedScreenScaleIndex != currentScreenScaleIndex ); createProjector = newFrame || ( requestedScreenScaleIndex != currentScreenScaleIndex );
}
newFrameRequest = false; newFrameRequest = false;
newIntervalRequest = false; newIntervalRequest = false;
...@@ -383,6 +415,13 @@ public class MultiResolutionRenderer ...@@ -383,6 +415,13 @@ public class MultiResolutionRenderer
requestedScreenScaleIndex = screenScales.suggestScreenScale( renderNanosPerPixel ); requestedScreenScaleIndex = screenScales.suggestScreenScale( renderNanosPerPixel );
} }
return intervalMode
? paintInterval( createProjector )
: paintFullFrame( createProjector );
}
private boolean paintFullFrame( final boolean createProjector )
{
// the projector that paints to the screenImage. // the projector that paints to the screenImage.
final VolatileProjector p; final VolatileProjector p;
...@@ -395,15 +434,6 @@ public class MultiResolutionRenderer ...@@ -395,15 +434,6 @@ public class MultiResolutionRenderer
synchronized ( this ) synchronized ( this )
{ {
if ( createProjector ) if ( createProjector )
{
if ( paintInterval )
{
intervalResult.init( intervalRenderData.width(), intervalRenderData.height() );
intervalResult.setScaleFactor( intervalRenderData.scale() );
projector = createProjector( currentViewerState, requestedIntervalScaleIndex, intervalResult.getScreenImage(), intervalRenderData.offsetX(), intervalRenderData.offsetY() );
renderingMayBeCancelled = !newInterval;
}
else
{ {
final ScreenScale screenScale = screenScales.get( requestedScreenScaleIndex ); final ScreenScale screenScale = screenScales.get( requestedScreenScaleIndex );
...@@ -415,28 +445,74 @@ public class MultiResolutionRenderer ...@@ -415,28 +445,74 @@ public class MultiResolutionRenderer
renderStorage.checkRenewData( screenScales.get( 0 ).width(), screenScales.get( 0 ).height(), currentNumVisibleSources ); renderStorage.checkRenewData( screenScales.get( 0 ).width(), screenScales.get( 0 ).height(), currentNumVisibleSources );
projector = createProjector( currentViewerState, requestedScreenScaleIndex, renderResult.getScreenImage(), 0, 0 ); projector = createProjector( currentViewerState, requestedScreenScaleIndex, renderResult.getScreenImage(), 0, 0 );
requestNewFrameIfIncomplete = projectorFactory.requestNewFrameIfIncomplete(); requestNewFrameIfIncomplete = projectorFactory.requestNewFrameIfIncomplete();
renderingMayBeCancelled = !newFrame;
}
} }
p = projector; p = projector;
} }
// try rendering // try rendering
final boolean success = p.map( createProjector ); final boolean success = p.map( createProjector );
final long rendertime = p.getLastFrameRenderNanoTime(); final long rendertime = p.getLastFrameRenderNanoTime();
synchronized ( this ) synchronized ( this )
{ {
// if rendering was not cancelled... // if rendering was not cancelled...
if ( success ) if ( success )
{ {
if ( paintInterval ) currentScreenScaleIndex = requestedScreenScaleIndex;
if ( createProjector )
{
renderResult.setUpdated();
( ( RenderTarget ) display ).setRenderResult( renderResult );
currentRenderResult = renderResult;
recordRenderTime( renderResult, rendertime );
}
else
currentRenderResult.setUpdated();
if ( !p.isValid() && requestNewFrameIfIncomplete )
requestRepaint();
else if ( p.isValid() && currentScreenScaleIndex == 0 )
// indicate that rendering is complete
requestedScreenScaleIndex = -1;
else
iterateRepaint( Math.max( 0, currentScreenScaleIndex - 1 ) );
}
}
return success;
}
private boolean paintInterval( final boolean createProjector )
{
// the projector that paints to the screenImage.
final VolatileProjector p;
synchronized ( this )
{
if ( createProjector )
{
intervalResult.init( intervalRenderData.width(), intervalRenderData.height() );
intervalResult.setScaleFactor( intervalRenderData.scale() );
projector = createProjector( currentViewerState, requestedIntervalScaleIndex, intervalResult.getScreenImage(), intervalRenderData.offsetX(), intervalRenderData.offsetY() );
}
p = projector;
}
// try rendering
final boolean success = p.map( createProjector );
final long rendertime = p.getLastFrameRenderNanoTime();
synchronized ( this )
{
// if rendering was not cancelled...
if ( success )
{ {
currentIntervalScaleIndex = requestedIntervalScaleIndex; currentIntervalScaleIndex = requestedIntervalScaleIndex;
currentRenderResult.patch( intervalResult, intervalRenderData.targetInterval(), intervalRenderData.tx(), intervalRenderData.ty() ); currentRenderResult.patch( intervalResult, intervalRenderData.targetInterval(), intervalRenderData.tx(), intervalRenderData.ty() );
if ( createProjector )
recordRenderTime( intervalResult, rendertime );
if ( currentIntervalScaleIndex > currentScreenScaleIndex ) if ( currentIntervalScaleIndex > currentScreenScaleIndex )
iterateRepaintInterval( currentIntervalScaleIndex - 1 ); iterateRepaintInterval( currentIntervalScaleIndex - 1 );
else if ( p.isValid() ) else if ( p.isValid() )
...@@ -454,51 +530,26 @@ public class MultiResolutionRenderer ...@@ -454,51 +530,26 @@ public class MultiResolutionRenderer
else else
iterateRepaintInterval( currentIntervalScaleIndex ); iterateRepaintInterval( currentIntervalScaleIndex );
} }
else
{
currentScreenScaleIndex = requestedScreenScaleIndex;
if ( createProjector )
{
renderResult.setUpdated();
( ( RenderTarget ) display ).setRenderResult( renderResult );
currentRenderResult = renderResult;
if ( currentNumVisibleSources > 0 )
{
final int numRenderPixels = ( int ) Intervals.numElements( renderResult.getScreenImage() ) * currentNumVisibleSources;
renderNanosPerPixelAndSource.add( rendertime / ( double ) numRenderPixels );
}
}
else
currentRenderResult.setUpdated();
if ( !p.isValid() && requestNewFrameIfIncomplete )
requestRepaint();
else if ( p.isValid() && currentScreenScaleIndex == 0 )
// indicate that rendering is complete
requestedScreenScaleIndex = -1;
else
iterateRepaint( Math.max( 0, currentScreenScaleIndex - 1 ) );
}
}
// if rendering was cancelled... // if rendering was cancelled...
else else
{
if ( paintInterval )
intervalRenderData.reRequest(); intervalRenderData.reRequest();
} }
}
return success; return success;
} }
private void recordRenderTime( final RenderResult result, final long renderNanos )
{
final int numRenderPixels = ( int ) Intervals.numElements( result.getScreenImage() ) * currentNumVisibleSources;
if ( numRenderPixels >= 4096 )
renderNanosPerPixelAndSource.add( renderNanos / ( double ) numRenderPixels );
}
/** /**
* Request a repaint of the display from the painter thread, setting * Request iterated repaint at the specified {@code screenScaleIndex}. This
* {@code requestedScreenScaleIndex} to the specified * is used to repaint the {@code currentViewerState} in a loop, until
* {@code screenScaleIndex}. This is used to repaint the * everything is painted at highest resolution from valid data (or until
* {@code currentViewerState} in a loop, until everything is painted at * painting is interrupted by a new request}.
* highest resolution from valid data (or painting is interrupted by a new
* "real" {@link #requestRepaint()}.
*/ */
private void iterateRepaint( final int screenScaleIndex ) private void iterateRepaint( final int screenScaleIndex )
{ {
...@@ -508,6 +559,12 @@ public class MultiResolutionRenderer ...@@ -508,6 +559,12 @@ public class MultiResolutionRenderer
painterThread.requestRepaint(); painterThread.requestRepaint();
} }
/**
* Request iterated repaint at the specified {@code intervalScaleIndex}.
* This is used to repaint the current interval in a loop, until everything
* is painted at highest resolution from valid data (or until painting is
* interrupted by a new request}.
*/
private void iterateRepaintInterval( final int intervalScaleIndex ) private void iterateRepaintInterval( final int intervalScaleIndex )
{ {
if ( intervalScaleIndex == currentIntervalScaleIndex ) if ( intervalScaleIndex == currentIntervalScaleIndex )
...@@ -542,12 +599,6 @@ public class MultiResolutionRenderer ...@@ -542,12 +599,6 @@ public class MultiResolutionRenderer
final int offsetX, final int offsetX,
final int offsetY ) final int offsetY )
{ {
/*
* This shouldn't be necessary, with
* CacheHints.LoadingStrategy==VOLATILE
*/
// CacheIoTiming.getIoTimeBudget().clear(); // clear time budget such that prefetching doesn't wait for loading blocks.
final AffineTransform3D screenScaleTransform = screenScales.get( screenScaleIndex ).scaleTransform(); final AffineTransform3D screenScaleTransform = screenScales.get( screenScaleIndex ).scaleTransform();
final AffineTransform3D screenTransform = viewerState.getViewerTransform(); final AffineTransform3D screenTransform = viewerState.getViewerTransform();
screenTransform.preConcatenate( screenScaleTransform ); screenTransform.preConcatenate( screenScaleTransform );
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment