|
|
|
|
@ -48,7 +48,7 @@ namespace Magnum { namespace Trade {
|
|
|
|
|
|
|
|
|
|
@see @ref ImporterFeatures, @ref AbstractImporter::features() |
|
|
|
|
*/ |
|
|
|
|
enum class ImporterFeature: UnsignedByte { |
|
|
|
|
enum class ImporterFeature: UnsignedShort { |
|
|
|
|
/**
|
|
|
|
|
* Opening files from raw data or non-temporary memory using |
|
|
|
|
* @ref AbstractImporter::openData() or |
|
|
|
|
@ -68,7 +68,121 @@ enum class ImporterFeature: UnsignedByte {
|
|
|
|
|
* See @ref Trade-AbstractImporter-usage-callbacks and particular importer |
|
|
|
|
* documentation for more information. |
|
|
|
|
*/ |
|
|
|
|
FileCallback = 1 << 2 |
|
|
|
|
FileCallback = 1 << 2, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing animations without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the animation data doesn't need |
|
|
|
|
* to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::animation() will then return an |
|
|
|
|
* @ref AnimationData that's a view on the memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()}, indicated with |
|
|
|
|
* @ref DataFlag::ExternallyOwned in @ref AnimationData::dataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopyAnimations |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopyAnimations = 1 << 3, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing images without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the image data doesn't need to be |
|
|
|
|
* processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::image1D() / @relativeref{AbstractImporter,image2D()} |
|
|
|
|
* / @relativeref{AbstractImporter,image3D()} will then return an |
|
|
|
|
* @ref ImageData that's a view on the memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()}, indicated with |
|
|
|
|
* @ref DataFlag::ExternallyOwned in @ref ImageData::dataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopyImages |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopyImages = 1 << 4, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing material attributes without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the material attribute data |
|
|
|
|
* doesn't need to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::material() will then return a |
|
|
|
|
* @ref MaterialData with attributes being a view on the memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()}, indicated with |
|
|
|
|
* @ref DataFlag::ExternallyOwned in @ref MaterialData::attributeDataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopyMaterialAttributes |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopyMaterialAttributes = 1 << 5, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing material layers without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the material layer data doesn't |
|
|
|
|
* need to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::material() will then return a |
|
|
|
|
* @ref MaterialData with layers being a view on the memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()}, indicated with |
|
|
|
|
* @ref DataFlag::ExternallyOwned in @ref MaterialData::layerDataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopyMaterialLayers |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopyMaterialLayers = 1 << 6, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing mesh indices without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the mesh index data doesn't need |
|
|
|
|
* to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::mesh() will then return a @ref MeshData with |
|
|
|
|
* indices being a view on the memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()}, indicated with |
|
|
|
|
* @ref DataFlag::ExternallyOwned in @ref MeshData::indexDataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopyMeshIndices |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopyMeshIndices = 1 << 7, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing mesh vertices without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the mesh vertex data doesn't need |
|
|
|
|
* to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::mesh() will then return a @ref MeshData with |
|
|
|
|
* vertices being a view on the memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()}, indicated with |
|
|
|
|
* @ref DataFlag::ExternallyOwned in @ref MeshData::vertexDataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopyMeshVertices |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopyMeshVertices = 1 << 8, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing skin joints without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the skin joint data doesn't need |
|
|
|
|
* to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::skin2D() / @relativeref{AbstractImporter,skin3D()} |
|
|
|
|
* will then return a @ref SkinData with vertices being a view on the |
|
|
|
|
* memory passed to @relativeref{AbstractImporter,openMemory()}, indicated |
|
|
|
|
* with @ref DataFlag::ExternallyOwned in @ref SkinData::jointDataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopySkinJoints |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopySkinJoints = 1 << 9, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Importing skin inverse bind matrices without data copies. If the |
|
|
|
|
* @ref AbstractImporter::openMemory() function is used, |
|
|
|
|
* @ref ImporterFlag::ZeroCopy is set and the skin joint data doesn't need |
|
|
|
|
* to be processed in any way during the import, |
|
|
|
|
* @ref AbstractImporter::skin2D() / @relativeref{AbstractImporter,skin3D()} |
|
|
|
|
* will then return a @ref SkinData with vertices being a view on the |
|
|
|
|
* memory passed to @relativeref{AbstractImporter,openMemory()}, indicated |
|
|
|
|
* with @ref DataFlag::ExternallyOwned in |
|
|
|
|
* @ref SkinData::inverseBindMatrixDataFlags(). |
|
|
|
|
* @see @ref ImporterFlag::ForceZeroCopySkinInverseBindMatrices |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopySkinInverseBindMatrices = 1 << 10 |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -100,7 +214,7 @@ typedef CORRADE_DEPRECATED("use InputFileCallbackPolicy instead") InputFileCallb
|
|
|
|
|
|
|
|
|
|
@see @ref ImporterFlags, @ref AbstractImporter::setFlags() |
|
|
|
|
*/ |
|
|
|
|
enum class ImporterFlag: UnsignedByte { |
|
|
|
|
enum class ImporterFlag: UnsignedShort { |
|
|
|
|
/**
|
|
|
|
|
* Print verbose diagnostic during import. By default the importer only |
|
|
|
|
* prints messages on error or when some operation might cause unexpected |
|
|
|
|
@ -113,6 +227,144 @@ enum class ImporterFlag: UnsignedByte {
|
|
|
|
|
*/ |
|
|
|
|
Verbose = 1 << 0, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Opt-in to zero-copy import, if possible. When this flag is set and |
|
|
|
|
* @ref AbstractImporter::openMemory() is used, returned @ref AnimationData, |
|
|
|
|
* @ref ImageData, @ref MaterialData, @ref MeshData and @ref SkinData |
|
|
|
|
* instances may be views on memory passed to |
|
|
|
|
* @relativeref{AbstractImporter,openMemory()} instead of allocated copies, |
|
|
|
|
* indicated with @ref DataFlag::ExternallyOwned. |
|
|
|
|
* |
|
|
|
|
* Since it's not always possible to directly reference the input memory |
|
|
|
|
* (for example because the input data may need to be parsed from text, |
|
|
|
|
* gathered from an incompatible data layout or patched in some way), this |
|
|
|
|
* flag doesn't put any requirement on the importer --- plugins that don't |
|
|
|
|
* support zero-copy import will behave the same as if this flag was not |
|
|
|
|
* set. |
|
|
|
|
* |
|
|
|
|
* Setting this flag however means you're responsible to keep the memory |
|
|
|
|
* passed to @relativeref{AbstractImporter,openMemory()} in scope for as |
|
|
|
|
* long as any `*Data` instances referencing it are alive. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ZeroCopy = 1 << 1, |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of animation data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopyAnimations. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::animation() to fail |
|
|
|
|
* if it can't perform a zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopyAnimations = ZeroCopy|(1 << 2), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of image data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopyImages. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::image1D() / |
|
|
|
|
* @relativeref{AbstractImporter,image2D()} / |
|
|
|
|
* @relativeref{AbstractImporter,image3D()} to fail if it can't perform a |
|
|
|
|
* zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopyImages = ZeroCopy|(1 << 3), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of material attribute data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopyMaterialAttributes. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::material() to fail |
|
|
|
|
* if it can't perform a zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopyMaterialAttributes = ZeroCopy|(1 << 4), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of material layer data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopyMaterialLayers. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::material() to fail |
|
|
|
|
* if it can't perform a zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopyMaterialLayers = ZeroCopy|(1 << 5), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of mesh index data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopyMeshIndices. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::mesh() to fail if it |
|
|
|
|
* can't perform a zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopyMeshIndices = ZeroCopy|(1 << 6), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of mesh vertex data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopyMeshVertices. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::mesh() to fail if it |
|
|
|
|
* can't perform a zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopyMeshVertices = ZeroCopy|(1 << 7), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of skin joint data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopySkinJoints. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::skin2D() / |
|
|
|
|
* @relativeref{AbstractImporter,skin3D()} to fail if it can't perform a |
|
|
|
|
* zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopySkinJoints = ZeroCopy|(1 << 8), |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Force zero-copy import of skin inverse bind matrix data opened through |
|
|
|
|
* @ref AbstractImporter::openMemory(). Implies |
|
|
|
|
* @ref ImporterFlag::ZeroCopy, can be set only if the importer supports |
|
|
|
|
* @ref ImporterFeature::ZeroCopySkinInverseBindMatrices. |
|
|
|
|
* |
|
|
|
|
* By default, if the data has to be processed in some way, preventing |
|
|
|
|
* zero-copy import, the importer will return a modified copy of the data. |
|
|
|
|
* Setting this flag will cause @ref AbstractImporter::skin2D() / |
|
|
|
|
* @relativeref{AbstractImporter,skin3D()} to fail if it can't perform a |
|
|
|
|
* zero-copy import. |
|
|
|
|
* @m_since_latest |
|
|
|
|
*/ |
|
|
|
|
ForceZeroCopySkinInverseBindMatrices = ZeroCopy|(1 << 9) |
|
|
|
|
|
|
|
|
|
/** @todo ~~Y flip~~ Y up for images, "I want to import just once, don't copy" ... */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
@ -311,6 +563,41 @@ name doesn't exist.
|
|
|
|
|
- Texture names using @ref textureName() & @ref textureForName(), imported |
|
|
|
|
with @ref texture(const std::string&) |
|
|
|
|
|
|
|
|
|
@subsection Trade-AbstractImporter-usage-zerocopy Zero-copy data import |
|
|
|
|
|
|
|
|
|
Some file formats have the data structured in a way that allows them to be |
|
|
|
|
loaded directly into memory or onto the GPU and used as-is. If you memory-map |
|
|
|
|
such a a file and open it with a capable importer, it can give you a view on a |
|
|
|
|
sub-range of the memory-mapped file instead of allocating a copy. Importers |
|
|
|
|
advertise such capabilities with @ref ImporterFeature::ZeroCopyImages, |
|
|
|
|
@relativeref{ImporterFeature,ZeroCopyMeshIndices}, |
|
|
|
|
@relativeref{ImporterFeature,ZeroCopyMeshVertices} and related flags. Because |
|
|
|
|
this puts additional constraints on data lifetime, you have to explicitly |
|
|
|
|
enable the behavior with @ref ImporterFlag::ZeroCopy. Then use |
|
|
|
|
@ref openMemory() to open the memory and ensure it stays in scope for as long |
|
|
|
|
as you operate on the instances returned from the importer: |
|
|
|
|
|
|
|
|
|
@snippet MagnumTrade.cpp AbstractImporter-usage-zerocopy |
|
|
|
|
|
|
|
|
|
Returned instances that reference the original memory are indicated with a |
|
|
|
|
presence of @ref DataFlag::ExternallyOwned. If you use the mutable |
|
|
|
|
@ref openMemory(Containers::ArrayView<void>) overload, the returned data will |
|
|
|
|
have also @ref DataFlag::Mutable set, allowing you to do in-place modifications |
|
|
|
|
on the original file. |
|
|
|
|
|
|
|
|
|
In some cases the importer might still need to process the data on import --- |
|
|
|
|
for example converting image endianness or flipping image origin, and in that |
|
|
|
|
case it'll still return a copy of the data, indicated with |
|
|
|
|
@ref DataFlag::Owned instead. To enforce zero-copy behavior, enable one of the |
|
|
|
|
@ref ImporterFlag::ForceZeroCopyImages, ... flags, providing the plugin |
|
|
|
|
actually supports the corresponding feature. In that case import of particular |
|
|
|
|
data will fail instead of returning a copy, which is useful when you want to, |
|
|
|
|
for example, operate in-place on the imported file or when it's needed to avoid |
|
|
|
|
accidental slowdowns. |
|
|
|
|
|
|
|
|
|
See documentation of a particular importer plugin for information about |
|
|
|
|
provided zero-copy features and their limitations. |
|
|
|
|
|
|
|
|
|
@subsection Trade-AbstractImporter-usage-state Internal importer state |
|
|
|
|
|
|
|
|
|
Some importers, especially ones that make use of well-known external libraries, |
|
|
|
|
@ -644,7 +931,8 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
|
|
|
|
|
* scope until the importer is destructed, @ref close() is called or |
|
|
|
|
* another file is opened. This allows the implementation to directly |
|
|
|
|
* operate on the provided memory, without having to allocate a local |
|
|
|
|
* copy to extend its lifetime. |
|
|
|
|
* copy to extend its lifetime. See also @ref ImporterFlag::ZeroCopy |
|
|
|
|
* for a possibility of further optimizations. |
|
|
|
|
* @see @ref features(), @ref openFile(), @ref openState() |
|
|
|
|
*/ |
|
|
|
|
bool openMemory(Containers::ArrayView<const void> memory); |
|
|
|
|
@ -1697,6 +1985,34 @@ class MAGNUM_TRADE_EXPORT AbstractImporter: public PluginManager::AbstractManagi
|
|
|
|
|
const void* importerState() const; |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
/**
|
|
|
|
|
* @brief Open data that originated elsewhere |
|
|
|
|
* @m_since_latest |
|
|
|
|
* |
|
|
|
|
* Closes previous file, if it was opened, and tries to open given raw |
|
|
|
|
* data. Available only if @ref ImporterFeature::OpenData is supported. |
|
|
|
|
* Returns @cpp true @ce on success, @cpp false @ce otherwise. |
|
|
|
|
* |
|
|
|
|
* Designed to be called instead of the public |
|
|
|
|
* @ref openData(Containers::ArrayView<const void>) by importers that |
|
|
|
|
* proxy loading to other plugins, with the intent of enabling |
|
|
|
|
* zero-copy import in the proxied-to implementations as well. Possible |
|
|
|
|
* scenarios: |
|
|
|
|
* |
|
|
|
|
* - Called from inside a @ref doOpenData() implementation that |
|
|
|
|
* proxies loading to other plugins (for example based on file |
|
|
|
|
* type). In this case it's meant to pass through the @p data and |
|
|
|
|
* @p dataFlags unchanged. |
|
|
|
|
* - Called from inside (for example) a @ref doImage2D() in a scene |
|
|
|
|
* importer that delegates image loading to specialized plugins. |
|
|
|
|
* Assuming the delegated-to importer receives a subrange of the |
|
|
|
|
* data held by the originating importer and its lifetime doesn't |
|
|
|
|
* exceed the originating importer lifetime, the @p data should |
|
|
|
|
* have a no-op deleter and @p dataFlags should be |
|
|
|
|
* @ref DataFlag::Owned. |
|
|
|
|
*/ |
|
|
|
|
bool openData(Containers::Array<char>&& data, DataFlags dataFlags); |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Implementation for @ref openFile() |
|
|
|
|
* |
|
|
|
|
|