Skip to content

Commit

Permalink
Add feature requirement info to image loading docs (#13712)
Browse files Browse the repository at this point in the history
# Objective

- Add "Available on crate feature <image format> only." for docs of
image format related types/functions
- Add warning "WARN bevy_render::texture::image: feature "<image
format>" is not enabled" on load attempt
- Fixes #13468 .

## Solution

- Added #[cfg(feature = "<image format>")] for types and warn!("feature
\"<image format>\" is not enabled"); for ImageFormat enum conversions

## Testing

ran reproducing example from issue #13468 and saw in logs
`WARN bevy_render::texture::image: feature "exr" is not enabled`

generated docs with command `RUSTDOCFLAGS="-Zunstable-options
--cfg=docsrs" cargo +nightly doc --workspace --all-features --no-deps
--document-private-items --open` and saw

![image](https://github.com/bevyengine/bevy/assets/17225606/820262bb-b4e6-4a5e-a306-bddbe9c40852)
that docs contain `Available on crate feature <image format> only.`
marks

![image](https://github.com/bevyengine/bevy/assets/17225606/57463440-a2ea-435f-a2c2-50d34f7f55a9)

## Migration Guide
Image format related entities are feature gated, if there are
compilation errors about unknown names there are some of features in
list (`exr`, `hdr`, `basis-universal`, `png`, `dds`, `tga`, `jpeg`,
`bmp`, `ktx2`, `webp` and `pnm`) should be added.
  • Loading branch information
bugsweeper authored Aug 16, 2024
1 parent d7cb781 commit bc445bb
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 31 deletions.
2 changes: 2 additions & 0 deletions crates/bevy_render/src/texture/dds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use wgpu::{

use super::{CompressedImageFormats, Image, TextureError};

#[cfg(feature = "dds")]
pub fn dds_buffer_to_image(
#[cfg(debug_assertions)] name: String,
buffer: &[u8],
Expand Down Expand Up @@ -82,6 +83,7 @@ pub fn dds_buffer_to_image(
Ok(image)
}

#[cfg(feature = "dds")]
pub fn dds_format_to_texture_format(
dds: &Dds,
is_srgb: bool,
Expand Down
3 changes: 3 additions & 0 deletions crates/bevy_render/src/texture/exr_texture_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ use wgpu::{Extent3d, TextureDimension, TextureFormat};

/// Loads EXR textures as Texture assets
#[derive(Clone, Default)]
#[cfg(feature = "exr")]
pub struct ExrTextureLoader;

#[derive(Serialize, Deserialize, Default, Debug)]
#[cfg(feature = "exr")]
pub struct ExrTextureLoaderSettings {
pub asset_usage: RenderAssetUsages,
}

/// Possible errors that can be produced by [`ExrTextureLoader`]
#[non_exhaustive]
#[derive(Debug, Error)]
#[cfg(feature = "exr")]
pub enum ExrTextureLoaderError {
#[error(transparent)]
Io(#[from] std::io::Error),
Expand Down
97 changes: 66 additions & 31 deletions crates/bevy_render/src/texture/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,105 +27,140 @@ pub const SAMPLER_ASSET_INDEX: u64 = 1;
#[derive(Debug, Serialize, Deserialize, Copy, Clone)]
pub enum ImageFormat {
Avif,
#[cfg(feature = "basis-universal")]
Basis,
#[cfg(feature = "bmp")]
Bmp,
#[cfg(feature = "dds")]
Dds,
Farbfeld,
Gif,
#[cfg(feature = "exr")]
OpenExr,
#[cfg(feature = "hdr")]
Hdr,
Ico,
#[cfg(feature = "jpeg")]
Jpeg,
#[cfg(feature = "ktx2")]
Ktx2,
#[cfg(feature = "png")]
Png,
#[cfg(feature = "pnm")]
Pnm,
#[cfg(feature = "tga")]
Tga,
Tiff,
#[cfg(feature = "webp")]
WebP,
}

macro_rules! feature_gate {
($feature: tt, $value: ident) => {{
#[cfg(not(feature = $feature))]
{
bevy_utils::tracing::warn!("feature \"{}\" is not enabled", $feature);
return None;
}
#[cfg(feature = $feature)]
ImageFormat::$value
}};
}

impl ImageFormat {
pub fn from_mime_type(mime_type: &str) -> Option<Self> {
Some(match mime_type.to_ascii_lowercase().as_str() {
"image/avif" => ImageFormat::Avif,
"image/bmp" | "image/x-bmp" => ImageFormat::Bmp,
"image/vnd-ms.dds" => ImageFormat::Dds,
"image/vnd.radiance" => ImageFormat::Hdr,
"image/bmp" | "image/x-bmp" => feature_gate!("bmp", Bmp),
"image/vnd-ms.dds" => feature_gate!("dds", Dds),
"image/vnd.radiance" => feature_gate!("hdr", Hdr),
"image/gif" => ImageFormat::Gif,
"image/x-icon" => ImageFormat::Ico,
"image/jpeg" => ImageFormat::Jpeg,
"image/ktx2" => ImageFormat::Ktx2,
"image/png" => ImageFormat::Png,
"image/x-exr" => ImageFormat::OpenExr,
"image/jpeg" => feature_gate!("jpeg", Jpeg),
"image/ktx2" => feature_gate!("ktx2", Ktx2),
"image/png" => feature_gate!("png", Png),
"image/x-exr" => feature_gate!("exr", OpenExr),
"image/x-portable-bitmap"
| "image/x-portable-graymap"
| "image/x-portable-pixmap"
| "image/x-portable-anymap" => ImageFormat::Pnm,
"image/x-targa" | "image/x-tga" => ImageFormat::Tga,
| "image/x-portable-anymap" => feature_gate!("pnm", Pnm),
"image/x-targa" | "image/x-tga" => feature_gate!("tga", Tga),
"image/tiff" => ImageFormat::Tiff,
"image/webp" => ImageFormat::WebP,
"image/webp" => feature_gate!("webp", WebP),
_ => return None,
})
}

pub fn from_extension(extension: &str) -> Option<Self> {
Some(match extension.to_ascii_lowercase().as_str() {
"avif" => ImageFormat::Avif,
"basis" => ImageFormat::Basis,
"bmp" => ImageFormat::Bmp,
"dds" => ImageFormat::Dds,
"basis" => feature_gate!("basis-universal", Basis),
"bmp" => feature_gate!("bmp", Bmp),
"dds" => feature_gate!("dds", Dds),
"ff" | "farbfeld" => ImageFormat::Farbfeld,
"gif" => ImageFormat::Gif,
"exr" => ImageFormat::OpenExr,
"hdr" => ImageFormat::Hdr,
"exr" => feature_gate!("exr", OpenExr),
"hdr" => feature_gate!("hdr", Hdr),
"ico" => ImageFormat::Ico,
"jpg" | "jpeg" => ImageFormat::Jpeg,
"ktx2" => ImageFormat::Ktx2,
"pbm" | "pam" | "ppm" | "pgm" => ImageFormat::Pnm,
"png" => ImageFormat::Png,
"tga" => ImageFormat::Tga,
"jpg" | "jpeg" => feature_gate!("jpeg", Jpeg),
"ktx2" => feature_gate!("ktx2", Ktx2),
"pbm" | "pam" | "ppm" | "pgm" => feature_gate!("pnm", Pnm),
"png" => feature_gate!("png", Png),
"tga" => feature_gate!("tga", Tga),
"tif" | "tiff" => ImageFormat::Tiff,
"webp" => ImageFormat::WebP,
"webp" => feature_gate!("webp", WebP),
_ => return None,
})
}

pub fn as_image_crate_format(&self) -> Option<image::ImageFormat> {
Some(match self {
ImageFormat::Avif => image::ImageFormat::Avif,
#[cfg(feature = "bmp")]
ImageFormat::Bmp => image::ImageFormat::Bmp,
#[cfg(feature = "dds")]
ImageFormat::Dds => image::ImageFormat::Dds,
ImageFormat::Farbfeld => image::ImageFormat::Farbfeld,
ImageFormat::Gif => image::ImageFormat::Gif,
#[cfg(feature = "exr")]
ImageFormat::OpenExr => image::ImageFormat::OpenExr,
#[cfg(feature = "hdr")]
ImageFormat::Hdr => image::ImageFormat::Hdr,
ImageFormat::Ico => image::ImageFormat::Ico,
#[cfg(feature = "jpeg")]
ImageFormat::Jpeg => image::ImageFormat::Jpeg,
#[cfg(feature = "png")]
ImageFormat::Png => image::ImageFormat::Png,
#[cfg(feature = "pnm")]
ImageFormat::Pnm => image::ImageFormat::Pnm,
#[cfg(feature = "tga")]
ImageFormat::Tga => image::ImageFormat::Tga,
ImageFormat::Tiff => image::ImageFormat::Tiff,
#[cfg(feature = "webp")]
ImageFormat::WebP => image::ImageFormat::WebP,
ImageFormat::Basis | ImageFormat::Ktx2 => return None,
#[cfg(feature = "basis-universal")]
ImageFormat::Basis => return None,
#[cfg(feature = "ktx2")]
ImageFormat::Ktx2 => return None,
})
}

pub fn from_image_crate_format(format: image::ImageFormat) -> Option<ImageFormat> {
Some(match format {
image::ImageFormat::Avif => ImageFormat::Avif,
image::ImageFormat::Bmp => ImageFormat::Bmp,
image::ImageFormat::Dds => ImageFormat::Dds,
image::ImageFormat::Bmp => feature_gate!("bmp", Bmp),
image::ImageFormat::Dds => feature_gate!("dds", Dds),
image::ImageFormat::Farbfeld => ImageFormat::Farbfeld,
image::ImageFormat::Gif => ImageFormat::Gif,
image::ImageFormat::OpenExr => ImageFormat::OpenExr,
image::ImageFormat::Hdr => ImageFormat::Hdr,
image::ImageFormat::OpenExr => feature_gate!("exr", OpenExr),
image::ImageFormat::Hdr => feature_gate!("hdr", Hdr),
image::ImageFormat::Ico => ImageFormat::Ico,
image::ImageFormat::Jpeg => ImageFormat::Jpeg,
image::ImageFormat::Png => ImageFormat::Png,
image::ImageFormat::Pnm => ImageFormat::Pnm,
image::ImageFormat::Tga => ImageFormat::Tga,
image::ImageFormat::Jpeg => feature_gate!("jpeg", Jpeg),
image::ImageFormat::Png => feature_gate!("png", Png),
image::ImageFormat::Pnm => feature_gate!("pnm", Pnm),
image::ImageFormat::Tga => feature_gate!("tga", Tga),
image::ImageFormat::Tiff => ImageFormat::Tiff,
image::ImageFormat::WebP => ImageFormat::WebP,
image::ImageFormat::WebP => feature_gate!("webp", WebP),
_ => return None,
})
}
Expand Down
4 changes: 4 additions & 0 deletions crates/bevy_render/src/texture/ktx2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use wgpu::{

use super::{CompressedImageFormats, DataFormat, Image, TextureError, TranscodeFormat};

#[cfg(feature = "ktx2")]
pub fn ktx2_buffer_to_image(
buffer: &[u8],
supported_compressed_formats: CompressedImageFormats,
Expand Down Expand Up @@ -387,6 +388,7 @@ pub fn get_transcoded_formats(
}
}

#[cfg(feature = "ktx2")]
pub fn ktx2_get_texture_format<Data: AsRef<[u8]>>(
ktx2: &ktx2::Reader<Data>,
is_srgb: bool,
Expand Down Expand Up @@ -473,6 +475,7 @@ fn sample_information_to_data_type(
)
}

#[cfg(feature = "ktx2")]
pub fn ktx2_dfd_to_texture_format(
data_format_descriptor: &BasicDataFormatDescriptor,
sample_information: &[SampleInformation],
Expand Down Expand Up @@ -1194,6 +1197,7 @@ pub fn ktx2_dfd_to_texture_format(
})
}

#[cfg(feature = "ktx2")]
pub fn ktx2_format_to_texture_format(
ktx2_format: ktx2::Format,
is_srgb: bool,
Expand Down

0 comments on commit bc445bb

Please sign in to comment.