Package icyllis.arc3d.granite

# Class DrawAtlas

java.lang.Object
icyllis.arc3d.granite.DrawAtlas

All Implemented Interfaces:
  `AutoCloseable`

public class DrawAtlas extends Object implements AutoCloseable
This class manages one or more atlas textures on behalf of primitive draws in Device. The drawing processes that use the atlas add preceding UploadTasks when generating RenderPassTasks. The class provides facilities for using DrawTokens to detect data hazards. Plots that need uploads are tracked until it is impossible to add data without overwriting texels read by draws that have not yet been snapped to a RenderPassTask. At that point, the atlas will attempt to allocate a new atlas texture (or "page") of the same size, up to a maximum number of textures, and upload to that texture. If that's not possible, then the atlas will fail to add a subimage. This gives the Device the chance to end the current draw, snap a RenderpassTask, and begin a new one. Additional uploads will then succeed.

When the atlas has multiple pages, new uploads are prioritized to the lower index pages, i.e., it will try to upload to page 0 before page 1 or 2. To keep the atlas from continually using excess space, periodic garbage collection is needed to shift data from the higher index pages to the lower ones, and then eventually remove any pages that are no longer in use. "In use" is determined by using the AtlasToken system: After a DrawPass is snapped a subarea of the page, or "plot" is checked to see whether it was used in that DrawPass. If less than a quarter of the plots have been used recently (within kPlotRecentlyUsedCount iterations) and there are available plots in lower index pages, the higher index page will be deactivated, and its glyphs will gradually migrate to other pages via the usual upload system.

Garbage collection is initiated by the DrawAtlas's client via the compact() method.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static class`
  `DrawAtlas.AtlasGenerationCounter`
  Keep track of generation number for atlases and Plots.
  `static class`
  `DrawAtlas.AtlasLocator`
  AtlasLocator handles atlas position information.
  `static class`
  `DrawAtlas.AtlasToken`
  AtlasToken is used to sequence uploads relative to each other and to batches of draws.
  `static class`
  `DrawAtlas.AtlasTokenTracker`
  The TokenTracker encapsulates the incrementing and distribution of AtlasTokens.
  `static class`
  `DrawAtlas.Plot`
  The backing texture for an atlas is broken into a spatial grid of Plots.
  `static class`
  `DrawAtlas.PlotBulkUseUpdater`
  A class which can be handed back to an atlas for updating plots in bulk.
  `static interface`
  `DrawAtlas.PlotEvictionCallback`
  An interface for eviction callbacks.
  `static class`
  `DrawAtlas.PlotLocator`
  Used to locate a plot in a `DrawAtlas`.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final int`
  `RESULT_FAILURE`
  `static final int`
  `RESULT_SUCCESS`
  `static final int`
  `RESULT_TRY_AGAIN`

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `DrawAtlas(int ct, int width, int height, int plotWidth, int plotHeight, DrawAtlas.AtlasGenerationCounter generationCounter, boolean useMultiPages, boolean useStorageTextures, String label)`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `int`
  `addRect(RecordingContext context, int width, int height, DrawAtlas.AtlasLocator atlasLocator)`
  Adds a width x height sub-image to the atlas.
  `int`
  `addToAtlas(RecordingContext context, int width, int height, Object imageBase, long imageAddr, DrawAtlas.AtlasLocator atlasLocator)`
  This is a combination of `addRect(RecordingContext, int, int, AtlasLocator)`, and copy the existing data to `getDataAt(AtlasLocator)` if success.
  `void`
  `close()`
  `void`
  `compact(long startTokenForNextFlush)`
  `boolean`
  `contains(DrawAtlas.PlotLocator plotLocator)`
  `void`
  `evictAllPlots()`
  `long`
  `getAtlasGeneration()`
  `long`
  `getDataAt(DrawAtlas.AtlasLocator atlasLocator)`
  Returns the pointer to the plot data at the given position.
  `int`
  `getMaxPages()`
  `int`
  `getNumActivePages()`
  `int`
  `getNumPlots()`
  `int`
  `getPlotHeight()`
  `int`
  `getPlotWidth()`
  `@RawPtr ImageViewProxy`
  `getTexture(int pageIndex)`
  `static DrawAtlas`
  `make(int ct, int width, int height, int plotWidth, int plotHeight, DrawAtlas.AtlasGenerationCounter generationCounter, boolean useMultiPages, boolean useStorageTextures, DrawAtlas.PlotEvictionCallback evictor, String label)`
  Creates a DrawAtlas.
  `void`
  `purge(long startTokenForNextFlush)`
  `boolean`
  `recordUploads(RecordingContext context, SurfaceDrawContext sdc)`
  `void`
  `setLastUseToken(DrawAtlas.AtlasLocator atlasLocator, long token)`
  `void`
  `setLastUseTokenBulk(DrawAtlas.PlotBulkUseUpdater updater, long token)`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### RESULT_SUCCESS

    public static final int RESULT_SUCCESS
    See Also:
      - Constant Field Values

  - ### RESULT_FAILURE

    public static final int RESULT_FAILURE
    See Also:
      - Constant Field Values

  - ### RESULT_TRY_AGAIN

    public static final int RESULT_TRY_AGAIN
    See Also:
      - Constant Field Values

- ## Constructor Details

  - ### DrawAtlas

    public DrawAtlas(int ct, int width, int height, int plotWidth, int plotHeight, @Nonnull DrawAtlas.AtlasGenerationCounter generationCounter, boolean useMultiPages, boolean useStorageTextures, String label)

- ## Method Details

  - ### make

    @Nonnull public static DrawAtlas make(int ct, int width, int height, int plotWidth, int plotHeight, @Nonnull DrawAtlas.AtlasGenerationCounter generationCounter, boolean useMultiPages, boolean useStorageTextures, DrawAtlas.PlotEvictionCallback evictor, String label)
    Creates a DrawAtlas.
    Parameters:
      `ct` - The colorType which this atlas will store.
      `width` - Width in pixels of the atlas.
      `height` - Height in pixels of the atlas.
      `plotWidth` - The width of each plot. width/plotWidth should be an integer.
      `plotHeight` - The height of each plot. height/plotHeight should be an integer.
      `generationCounter` - A pointer to the context's generation counter.
      `useMultiPages` - Can the atlas use more than one texture.
      `useStorageTextures` - Should the atlas use storage textures.
      `evictor` - A pointer to an eviction callback class.
      `label` - Label for texture resources.

  - ### close

    public void close()
    Specified by:
      `close` in interface `AutoCloseable`

  - ### addRect

    public int addRect(@Nonnull RecordingContext context, int width, int height, @Nonnull DrawAtlas.AtlasLocator atlasLocator)
    Adds a width x height sub-image to the atlas. Upon success, it returns `RESULT_SUCCESS` and returns the plot location and the sub-image's coordinates in the backing texture. `RESULT_TRY_AGAIN` is returned if the sub-image cannot fit in the atlas without overwriting texels that will be read in the current list of draws. This indicates that the `GraniteDevice` should end its current draw, snap a `DrawPass`, and begin another before adding more data. `RESULT_FAILURE` will be returned when some unrecoverable error was encountered while trying to add the sub-image. In this case the draw being created should be discarded.

    This tracking does not generate `UploadTasks` per se. Instead, when the `RenderPassTask` is ready to be snapped, `recordUploads(icyllis.arc3d.engine.RecordingContext, icyllis.arc3d.granite.SurfaceDrawContext)` will be called by the `GraniteDevice` and that will generate the necessary `UploadTasks`.

    NOTE: When a draw that reads from the atlas is added to the DrawList, the client using this DrawAtlas must immediately call 'setLastUseToken' with the currentToken from the Recorder, otherwise the next call to addToAtlas might cause the previous data to be overwritten before it has been read.

  - ### getDataAt

    public long getDataAt(@Nonnull DrawAtlas.AtlasLocator atlasLocator)
    Returns the pointer to the plot data at the given position. The row bytes of the dst is bpp * plotWidth in the constructor. This must be called and can only be called once after `addRect(RecordingContext, int, int, AtlasLocator)` to update the data.

  - ### addToAtlas

    public int addToAtlas(@Nonnull RecordingContext context, int width, int height, Object imageBase, long imageAddr, @Nonnull DrawAtlas.AtlasLocator atlasLocator)
    This is a combination of `addRect(RecordingContext, int, int, AtlasLocator)`, and copy the existing data to `getDataAt(AtlasLocator)` if success.

  - ### recordUploads

    public boolean recordUploads(RecordingContext context, SurfaceDrawContext sdc)

  - ### getTexture

    @RawPtr public @RawPtr ImageViewProxy getTexture(int pageIndex)

  - ### getAtlasGeneration

    public long getAtlasGeneration()

  - ### getNumActivePages

    public int getNumActivePages()

  - ### getNumPlots

    public int getNumPlots()

  - ### getMaxPages

    public int getMaxPages()

  - ### getPlotWidth

    public int getPlotWidth()

  - ### getPlotHeight

    public int getPlotHeight()

  - ### contains

    public boolean contains(@Nonnull DrawAtlas.PlotLocator plotLocator)

  - ### setLastUseToken

    public void setLastUseToken(@Nonnull DrawAtlas.AtlasLocator atlasLocator, long token)

  - ### setLastUseTokenBulk

    public void setLastUseTokenBulk(@Nonnull DrawAtlas.PlotBulkUseUpdater updater, long token)

  - ### compact

    public void compact(long startTokenForNextFlush)

  - ### purge

    public void purge(long startTokenForNextFlush)

  - ### evictAllPlots

    public void evictAllPlots()