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}