dear_imgui_rs/texture/reference.rs
1use super::{TextureData, TextureId};
2use crate::sys;
3use std::marker::PhantomData;
4
5/// A convenient, typed wrapper around ImGui's ImTextureRef (v1.92+)
6///
7/// Can reference either a plain `TextureId` (legacy path) or a managed `TextureData`.
8/// Managed texture references carry the lifetime of the referenced texture data; legacy
9/// `TextureId` references can be converted into any texture-reference lifetime because they do not
10/// borrow Rust texture data.
11///
12/// Examples
13/// - With a plain GPU handle (legacy path):
14/// ```no_run
15/// # use dear_imgui_rs::{Ui, TextureId};
16/// # fn demo(ui: &Ui) {
17/// let tex_id = TextureId::new(12345);
18/// ui.image(tex_id, [64.0, 64.0]);
19/// # }
20/// ```
21/// - With a managed texture (ImGui 1.92 texture system):
22/// ```no_run
23/// # use dear_imgui_rs::{Ui, texture::{TextureData, TextureFormat}};
24/// # fn demo(ui: &Ui) {
25/// let mut tex = TextureData::new();
26/// tex.create(TextureFormat::RGBA32, 256, 256);
27/// // Fill pixels or schedule updates...
28/// ui.image(&mut *tex, [256.0, 256.0]);
29/// // The renderer backend will honor WantCreate/WantUpdates/WantDestroy
30/// // via DrawData::textures_mut() when rendering this frame.
31/// # }
32/// ```
33///
34/// Managed references cannot be stored beyond the texture data they point at:
35///
36/// ```compile_fail
37/// # use dear_imgui_rs::texture::{TextureData, TextureRef};
38/// let leaked: TextureRef<'static>;
39/// {
40/// let mut tex = TextureData::new();
41/// leaked = (&mut tex).into();
42/// }
43/// let _ = leaked.raw();
44/// ```
45///
46/// Raw `ImTextureRef` values can contain arbitrary managed texture pointers, so constructing this
47/// wrapper from raw data is unsafe:
48///
49/// ```compile_fail
50/// # use dear_imgui_rs::{sys, texture::TextureRef};
51/// let raw = sys::ImTextureRef {
52/// _TexData: std::ptr::null_mut(),
53/// _TexID: 0,
54/// };
55/// let _ = TextureRef::from_raw(raw);
56/// ```
57#[derive(Copy, Clone, Debug)]
58#[repr(transparent)]
59pub struct TextureRef<'tex> {
60 raw: sys::ImTextureRef,
61 _marker: PhantomData<&'tex mut TextureData>,
62}
63
64// Ensure the wrapper stays layout-compatible with the sys bindings.
65const _: [(); std::mem::size_of::<sys::ImTextureRef>()] =
66 [(); std::mem::size_of::<TextureRef<'static>>()];
67const _: [(); std::mem::align_of::<sys::ImTextureRef>()] =
68 [(); std::mem::align_of::<TextureRef<'static>>()];
69
70impl<'tex> TextureRef<'tex> {
71 /// Create a texture reference from a raw ImGui texture ref.
72 ///
73 /// # Safety
74 ///
75 /// If `raw._TexData` is non-null, the caller must guarantee that it points to a valid
76 /// `ImTextureData` for the entire `'tex` lifetime and that using the resulting reference does
77 /// not violate Rust aliasing rules.
78 #[inline]
79 pub unsafe fn from_raw(raw: sys::ImTextureRef) -> Self {
80 Self {
81 raw,
82 _marker: PhantomData,
83 }
84 }
85
86 /// Get the underlying ImGui texture ref (by value)
87 #[inline]
88 pub fn raw(self) -> sys::ImTextureRef {
89 self.raw
90 }
91}
92
93impl<'tex> From<TextureId> for TextureRef<'tex> {
94 #[inline]
95 fn from(id: TextureId) -> Self {
96 TextureRef {
97 raw: sys::ImTextureRef {
98 _TexData: std::ptr::null_mut(),
99 _TexID: id.id() as sys::ImTextureID,
100 },
101 _marker: PhantomData,
102 }
103 }
104}
105
106impl<'tex> From<&TextureData> for TextureRef<'tex> {
107 #[inline]
108 fn from(td: &TextureData) -> Self {
109 // Safety: A shared `&TextureData` must not be used to give Dear ImGui a mutable
110 // `ImTextureData*` because ImGui/backends may mutate fields such as `Status`/`TexID`
111 // during the frame, which would violate Rust aliasing rules.
112 //
113 // We therefore treat `&TextureData` as a legacy reference: only forward the current
114 // `TexID` value (if any). For managed textures, pass `&mut TextureData` instead.
115 TextureRef {
116 raw: sys::ImTextureRef {
117 _TexData: std::ptr::null_mut(),
118 _TexID: td.tex_id().id() as sys::ImTextureID,
119 },
120 _marker: PhantomData,
121 }
122 }
123}
124
125impl<'tex> From<&'tex mut TextureData> for TextureRef<'tex> {
126 #[inline]
127 fn from(td: &'tex mut TextureData) -> Self {
128 TextureRef {
129 raw: sys::ImTextureRef {
130 _TexData: td.as_raw_mut(),
131 _TexID: 0,
132 },
133 _marker: PhantomData,
134 }
135 }
136}
137
138/// Create an ImTextureRef from a texture ID.
139///
140/// This is the safe way to create an ImTextureRef for use with Dear ImGui.
141/// Use this instead of directly constructing the sys::ImTextureRef structure.
142pub fn create_texture_ref(texture_id: TextureId) -> sys::ImTextureRef {
143 sys::ImTextureRef {
144 _TexData: std::ptr::null_mut(),
145 _TexID: texture_id.id() as sys::ImTextureID,
146 }
147}