Class MultiResolutionRenderer


  • public class MultiResolutionRenderer
    extends Object
    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 larger images are rendered, until the full canvas resolution is reached.

    When drawing the low-resolution target images to the screen, they will be scaled up by Java2D (or JavaFX, etc) to the full canvas size, which is relatively fast. Rendering the small, low-resolution images is usually very fast, such that the display is very interactive while the user changes the viewing transformation for example. When the transformation remains fixed for a longer period, higher-resolution details are filled in successively.

    The renderer allocates a RenderResult for each of a predefined set of screen scales (a screen scale of 1 means that 1 pixel in the screen image is displayed as 1 pixel on the canvas, a screen scale of 0.5 means 1 pixel in the screen image is displayed as 2 pixel on the canvas, etc.)

    At any time, one of these screen scales is selected as the highest screen scale. Rendering starts with this highest screen scale and then proceeds to lower screen scales (higher resolution images). Unless the highest screen scale is currently rendering, repaint request will cancel rendering, such that display remains interactive.

    The renderer tries to maintain a per-frame rendering time close to targetRenderNanos nanoseconds. The current highest screen scale is chosen to match this time based on per-output-pixel time measured in previous frames.

    The renderer uses multiple threads (if desired).

    The renderer supports rendering of Volatile sources. In each rendering pass, all currently valid data for the best fitting mipmap level and all coarser levels is rendered to a temporary image for each visible source. Then the temporary images are combined to the final image for display. The number of passes required until all data is valid might differ between visible sources.

    Rendering timing is tied to a CacheControl control for IO budgeting, etc.

    Author:
    Tobias Pietzsch
    • Constructor Detail

      • MultiResolutionRenderer

        public MultiResolutionRenderer​(RenderTarget<?> display,
                                       RequestRepaint painterThread,
                                       double[] screenScaleFactors,
                                       long targetRenderNanos,
                                       int numRenderingThreads,
                                       ExecutorService renderingExecutorService,
                                       boolean useVolatileIfAvailable,
                                       CacheControl cacheControl)
        Parameters:
        display - The canvas that will display the images we render.
        painterThread - Thread that triggers repainting of the display. Requests for repainting are send there.
        screenScaleFactors - Scale factors from the viewer canvas to screen images of different resolutions. A scale factor of 1 means 1 pixel in the screen image is displayed as 1 pixel on the canvas, a scale factor of 0.5 means 1 pixel in the screen image is displayed as 2 pixel on the canvas, etc.
        targetRenderNanos - Target rendering time in nanoseconds. The rendering time for the coarsest rendered scale should be below this threshold.
        numRenderingThreads - How many threads to use for rendering. This is only used if no (valid) renderingExecutorService is provided.
        renderingExecutorService - if this is a ForkJoinPool it is used for rendering. Otherwise, a new ForkJoinPool with parallelism numRenderingThreads is created.
        useVolatileIfAvailable - whether volatile versions of sources should be used if available.
        cacheControl - the cache controls IO budgeting and fetcher queue.
    • Method Detail

      • kill

        public void kill()
        DON'T USE THIS.

        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...

      • paint

        public boolean paint​(ViewerState viewerState)
        Render image at the requested screen scale.