Skip to main content

gpui_wgpu/
imported_texture.rs

1//! The wgpu half of the imported-texture path.
2//!
3//! The engine transports a texture produced outside GPUI as an erased
4//! [`ImportedTextureHandle`], because it owns no GPU type
5//! (`crates/gpui_engine/src/custom_render.rs`). The payload and the extension that
6//! builds one live here, in the only crate that names a `wgpu` API; the renderer
7//! ([`crate::WgpuRenderer`]) is what downcasts it back.
8
9use gpui_engine::ImportedTextureHandle;
10
11/// The wgpu payload an [`ImportedTextureHandle`] carries.
12///
13/// The renderer binds the view at a fragment sampler slot; the sampler itself is
14/// the renderer's, shared by every imported texture, and the per-primitive values
15/// (bounds, clip, radii, opacity) travel in the scene's custom primitive rather
16/// than here.
17#[derive(Clone)]
18pub struct WgpuImportedTexture {
19    /// The view the imported-texture fragment samples.
20    pub view: wgpu::TextureView,
21}
22
23/// Builds an [`ImportedTextureHandle`] from a wgpu resource.
24pub trait ImportedTextureExt {
25    /// Wrap this view as a handle.
26    ///
27    /// Validates the colour-space and binding invariants up front, at the boundary where the
28    /// failure is a producer's mistake and the message can name it. Sampling a non-sRGB view
29    /// composites with a gamma error rather than crashing, so it has to be rejected here;
30    /// `TEXTURE_BINDING` is likewise a property of the view and is what the renderer's bind group
31    /// requires.
32    fn to_imported_handle(&self) -> anyhow::Result<ImportedTextureHandle>;
33}
34
35impl ImportedTextureExt for wgpu::TextureView {
36    fn to_imported_handle(&self) -> anyhow::Result<ImportedTextureHandle> {
37        let texture = self.texture();
38        let format = texture.format();
39        anyhow::ensure!(
40            matches!(
41                format,
42                wgpu::TextureFormat::Rgba8UnormSrgb | wgpu::TextureFormat::Bgra8UnormSrgb
43            ),
44            "an imported texture must sample as sRGB (Rgba8UnormSrgb or Bgra8UnormSrgb), \
45             but this view's texture is {format:?}"
46        );
47        anyhow::ensure!(
48            texture
49                .usage()
50                .contains(wgpu::TextureUsages::TEXTURE_BINDING),
51            "an imported texture must be created with wgpu::TextureUsages::TEXTURE_BINDING"
52        );
53
54        Ok(ImportedTextureHandle::new(WgpuImportedTexture {
55            view: self.clone(),
56        }))
57    }
58}