IOLink  IOL_v1.6.1_release
View Extensions

What are View Extensions ?

View extensions are a way to add new functionnalities for views without breaking the current ABI. If a view support a kind of extension, you can get it to access more information or services. You can get an extension this way:

std::shared_ptr<Extension> extension = view->extension(SomeExtension::EXTENSION_ID);
std::shared_ptr<SomeExtension> someExtension = ExtensionProvider::toTilingInfo(extension);
// we can now use the extension services
someExtension->someService();

This may seem a little complicated at first, but the nature of extensions make them this way. Usually shortcuts will be defined in the View class or its descendants, which will make them transparent for the user.

Tiling Info

There is an extension for tiling-related informations called TilingInfoExtension. It defines multiple services to know the number of tiles, their location, and their topology. You can get this extension using this code:

std::shared_ptr<Extension> extension = view->extension(TilingInfoExtension::EXTENSION_ID);
std::shared_ptr<TilingInfoExtension> tilingInfo = ExtensionProvider::toTilingInfo(extension);
// we can now use the extension services
size_t count = tilingInfo->tileCount();

There is a shortcut in ImageView that does all the conversion work:

std::shared_ptr<TilingInfoExtension> tilingInfo = image->tilingInfo();
// we can now use the extension services
size_t count = tilingInfo->tileCount();

The extension provides the following services:

  • maxTileSize(): Return the maximum size of the tiles used for the tiling grid, as tiles can be cropped on the sides of the image, tiles can be smaller in usage.
  • tileCount(): Simply the number of tiles in the image.
  • tileRegion(tileIndex): Get the region corresponding to a tile. The tile index goes from 0 to tileCount - 1, all indices outside this range are undefined and will throw an exception if given as an argument to this method.
  • tilingGrid(): return an array that shows how the tiles indices are distributed in the image. Each element of the returned array shows the tile index corresponding to the region.
  • readTile(tileIndex, dst): Read data from a tile into a memory buffer buffer. The image must support the READ capability. Indexation rules are the same as tileRegion.
  • writeTile(tileIndex, src): Write data of a memory buffer into a tile. The image must support the WRITE capability. Indexation rules are the same as tileRegion.

Parallel Access

The ParallelAccessExtension extension provides information about parallelism capabilities of an ImageView. You can get this extension using this code:

std::shared_ptr<Extension> extension = view->extension(ParallelAccessExtension::EXTENSION_ID);
std::shared_ptr<ParallelAccessExtension> parallAccess = ExtensionProvider::toParallelAccess(extension);
// we can now use the extension services
auto capabilities = parallAccess->capabilities();

There is a shortcut in ImageView that does all the conversion work:

std::shared_ptr<ParallelAccessExtension> parallelAccess = image->parallelAccess();
// we can now use the extension services
auto capabilities = parallelAccess->capabilities();

In order to accelerate processing when handling an ImageView, you may have to use multi-threading to access your data. However, a given ImageView instance can have various support for parallel multithreaded operations, and may, or may not be performant when doing so.

In some cases, it can be more efficient to read multiple regions of the ImageView instance in parallel.

For all these cases, the ParallelAccessExtension extension provides a set of capabilities:

  • THREAD_SAFE: ImageView is protected (thanks to its implementation or some locks) and can be used safely in a multi-threaded environment. No risk of race conditions, but as the order of operations in different thread can not be known, if different threads work on overlapping areas, the operations may yield undefined results.
  • PARALLEL_READ: Non-overlapping regions can be read in parallel to gain performance benefits without any risk.
  • PARALLEL_WRITE: Non-overlapping regions can be written in parallel to gain performance benefits without any risk.
  • PARALLEL_TILE_READ: In case of tiled image (see TilingInfoExtension), distinct tiles can be simultaneously read to gain performance benefits.
  • PARALLEL_TILE_WRITE: In case of tiled image (see TilingInfoExtension), distinct tiles can be simultaneously written to gain performance benefits.

Warning: In any case a same region of an ImageView should be read and written at the same time, or even written by separated threads. In addition to the risk of race conditions, the result of such operation would be totally unpredictable.

THREAD_SAFE

If an ImageView has PARALLEL_READ capability, you can execute parallel reads on separated regions with a likely performance boost.

PARALLEL_READ

If an ImageView has PARALLEL_WRITE capability, you can execute parallel writes on separated regions with a likely performance boost.

PARALLEL_WRITE

If a tiled ImageView has PARALLEL_TILE_READ capability, you can execute parallel reads on separated tiles with a likely performance boost.

PARALLEL_TILE_READ

If a tiled ImageView has PARALLEL_TILE_WRITE capability, you can execute parallel writes on separated tiles with a likely performance boost.

PARALLEL_TILE_WRITE

View Origin

The ViewOriginExtension extension provides information about the data origin of a view. You can get this extension using this code:

std::shared_ptr<Extension> extension = view->extension(ViewOriginExtension::EXTENSION_ID);
std::shared_ptr<ViewOriginExtension> viewOrigin = ExtensionProvider::toViewOrigin(extension);
// we can now use the extension services
auto origin = viewOrigin->dataOrigin();

There is a shortcut in View that does all the conversion work:

std::shared_ptr<ViewOriginExtension> viewOrigin = view->viewOrigin();
// we can now use the extension services
auto origin = viewOrigin->dataOrigin();

Views allow to access data, but they don't give any information about where it comes from. For example, if a view A was "adapted" to create two distinct views B and C. And C is used with another view D to create E, it is not possible to know the connection between these 4 views from the actual interface.

B, and C are created from the same view A.

A, B, C and E share the same data.

D shares data with E only.

With this extension, from any view it is possible to navigate through parents (adapters, proxy...) til the original view(s).

A -> B

A -> C -> E

D -> E

Each view can give information about the origin of its data:

  • In CPU memory
  • In GPU memory
  • On a Drive (Hard Disk, SSD, ...)
  • On a Network
  • Generated (no data is stored)

Data origin may also be COMPOSITE if the view is composed of data from multiple sources, or simply UNKNOWN when IOLink has no information about the source of the data.

The extension also provides an uid which allows to identify a view.

Thanks to this extension, when parsing the parents of different views, it is possible to determine if these views share the same data source. This can be decisive, for example, to allow parallel access on these views.

LIMITATION: As of now, view origin only takes into account 'view' instances as sources of data. Different views created from the same resource, i.e. a file, won't be identified as the same data source, and will have different UIDs