arcdps_imgui\render/
draw_data.rs
1use std::slice;
2
3use crate::internal::{RawCast, RawWrapper};
4use crate::render::renderer::TextureId;
5use crate::sys;
6
7#[repr(C)]
9pub struct DrawData {
10 valid: bool,
12 cmd_lists: *mut *mut DrawList,
14 cmd_lists_count: i32,
16 pub total_idx_count: i32,
18 pub total_vtx_count: i32,
20 pub display_pos: [f32; 2],
24 pub display_size: [f32; 2],
28 pub framebuffer_scale: [f32; 2],
33}
34
35unsafe impl RawCast<sys::ImDrawData> for DrawData {}
36
37impl DrawData {
38 #[inline]
40 pub fn draw_lists(&self) -> DrawListIterator<'_> {
41 unsafe {
42 DrawListIterator {
43 iter: self.cmd_lists().iter(),
44 }
45 }
46 }
47 #[inline]
49 pub fn draw_lists_count(&self) -> usize {
50 use std::convert::TryInto;
51 self.cmd_lists_count.try_into().unwrap()
52 }
53 #[inline]
54 pub(crate) unsafe fn cmd_lists(&self) -> &[*const DrawList] {
55 slice::from_raw_parts(
56 self.cmd_lists as *const *const DrawList,
57 self.cmd_lists_count as usize,
58 )
59 }
60 #[doc(alias = "DeIndexAllBuffers")]
65 pub fn deindex_all_buffers(&mut self) {
66 unsafe {
67 sys::ImDrawData_DeIndexAllBuffers(self.raw_mut());
68 }
69 }
70 #[doc(alias = "ScaleClipRects")]
75 pub fn scale_clip_rects(&mut self, fb_scale: [f32; 2]) {
76 unsafe {
77 sys::ImDrawData_ScaleClipRects(self.raw_mut(), fb_scale.into());
78 }
79 }
80}
81
82pub struct DrawListIterator<'a> {
84 iter: std::slice::Iter<'a, *const DrawList>,
85}
86
87impl<'a> Iterator for DrawListIterator<'a> {
88 type Item = &'a DrawList;
89
90 fn next(&mut self) -> Option<Self::Item> {
91 self.iter.next().map(|&ptr| unsafe { &*ptr })
92 }
93}
94
95#[test]
96#[cfg(test)]
97fn test_drawdata_memory_layout() {
98 use std::mem;
99 assert_eq!(
100 mem::size_of::<DrawData>(),
101 mem::size_of::<sys::ImDrawData>()
102 );
103 assert_eq!(
104 mem::align_of::<DrawData>(),
105 mem::align_of::<sys::ImDrawData>()
106 );
107 use sys::ImDrawData;
108 macro_rules! assert_field_offset {
109 ($l:ident, $r:ident) => {
110 assert_eq!(
111 memoffset::offset_of!(DrawData, $l),
112 memoffset::offset_of!(ImDrawData, $r)
113 );
114 };
115 }
116 assert_field_offset!(valid, Valid);
117 assert_field_offset!(cmd_lists, CmdLists);
118 assert_field_offset!(cmd_lists_count, CmdListsCount);
119 assert_field_offset!(total_idx_count, TotalIdxCount);
120 assert_field_offset!(total_vtx_count, TotalVtxCount);
121 assert_field_offset!(display_pos, DisplayPos);
122 assert_field_offset!(display_size, DisplaySize);
123 assert_field_offset!(framebuffer_scale, FramebufferScale);
124}
125
126#[repr(transparent)]
128pub struct DrawList(sys::ImDrawList);
129
130impl RawWrapper for DrawList {
131 type Raw = sys::ImDrawList;
132 #[inline]
133 unsafe fn raw(&self) -> &sys::ImDrawList {
134 &self.0
135 }
136 #[inline]
137 unsafe fn raw_mut(&mut self) -> &mut sys::ImDrawList {
138 &mut self.0
139 }
140}
141
142impl DrawList {
143 #[inline]
144 pub(crate) unsafe fn cmd_buffer(&self) -> &[sys::ImDrawCmd] {
145 slice::from_raw_parts(
146 self.0.CmdBuffer.Data as *const sys::ImDrawCmd,
147 self.0.CmdBuffer.Size as usize,
148 )
149 }
150 #[inline]
151 pub fn idx_buffer(&self) -> &[DrawIdx] {
152 unsafe {
153 slice::from_raw_parts(
154 self.0.IdxBuffer.Data as *const DrawIdx,
155 self.0.IdxBuffer.Size as usize,
156 )
157 }
158 }
159 #[inline]
160 pub fn vtx_buffer(&self) -> &[DrawVert] {
161 unsafe {
162 slice::from_raw_parts(
163 self.0.VtxBuffer.Data as *const DrawVert,
164 self.0.VtxBuffer.Size as usize,
165 )
166 }
167 }
168
169 pub unsafe fn transmute_vtx_buffer<VTy: Copy>(&self) -> &[VTy] {
174 assert_eq!(
176 core::mem::size_of::<VTy>(),
177 core::mem::size_of::<DrawVert>(),
178 );
179 assert!(core::mem::align_of::<VTy>() <= core::mem::align_of::<DrawVert>());
180 slice::from_raw_parts(self.0.VtxBuffer.Data.cast(), self.0.VtxBuffer.Size as usize)
181 }
182
183 #[inline]
184 pub fn commands(&self) -> DrawCmdIterator<'_> {
185 unsafe {
186 DrawCmdIterator {
187 iter: self.cmd_buffer().iter(),
188 }
189 }
190 }
191}
192
193pub struct DrawCmdIterator<'a> {
194 iter: std::slice::Iter<'a, sys::ImDrawCmd>,
195}
196
197impl<'a> Iterator for DrawCmdIterator<'a> {
198 type Item = DrawCmd;
199
200 #[inline]
201 fn next(&mut self) -> Option<Self::Item> {
202 self.iter.next().map(|cmd| {
203 let cmd_params = DrawCmdParams {
204 clip_rect: cmd.ClipRect.into(),
205 texture_id: TextureId::from(cmd.TextureId),
206 vtx_offset: cmd.VtxOffset as usize,
207 idx_offset: cmd.IdxOffset as usize,
208 };
209 match cmd.UserCallback {
210 Some(raw_callback) if raw_callback as usize == -1isize as usize => {
211 DrawCmd::ResetRenderState
212 }
213 Some(raw_callback) => DrawCmd::RawCallback {
214 callback: raw_callback,
215 raw_cmd: cmd,
216 },
217 None => DrawCmd::Elements {
218 count: cmd.ElemCount as usize,
219 cmd_params,
220 },
221 }
222 })
223 }
224}
225
226pub type DrawIdx = sys::ImDrawIdx;
228
229#[derive(Copy, Clone, Debug, PartialEq)]
230pub struct DrawCmdParams {
231 pub clip_rect: [f32; 4],
233 pub texture_id: TextureId,
234 pub vtx_offset: usize,
235 pub idx_offset: usize,
236}
237
238pub enum DrawCmd {
240 Elements {
241 count: usize,
243 cmd_params: DrawCmdParams,
244 },
245 ResetRenderState,
246 RawCallback {
247 callback: unsafe extern "C" fn(*const sys::ImDrawList, cmd: *const sys::ImDrawCmd),
248 raw_cmd: *const sys::ImDrawCmd,
249 },
250}
251
252#[repr(C)]
254#[derive(Copy, Clone, Debug, PartialEq)]
255pub struct DrawVert {
256 pub pos: [f32; 2],
257 pub uv: [f32; 2],
258 pub col: [u8; 4],
259}
260
261#[test]
262#[cfg(test)]
263fn test_drawvert_memory_layout() {
264 use std::mem;
265 assert_eq!(
266 mem::size_of::<DrawVert>(),
267 mem::size_of::<sys::ImDrawVert>()
268 );
269 assert_eq!(
270 mem::align_of::<DrawVert>(),
271 mem::align_of::<sys::ImDrawVert>()
272 );
273 use sys::ImDrawVert;
274 macro_rules! assert_field_offset {
275 ($l:ident, $r:ident) => {
276 assert_eq!(
277 memoffset::offset_of!(DrawVert, $l),
278 memoffset::offset_of!(ImDrawVert, $r)
279 );
280 };
281 }
282 assert_field_offset!(pos, pos);
283 assert_field_offset!(uv, uv);
284 assert_field_offset!(col, col);
285}