• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use mesa_rust_gen::*;
2 
3 use std::{
4     marker::PhantomData,
5     mem,
6     ptr::{self, NonNull},
7 };
8 
9 use super::context::PipeContext;
10 
11 #[derive(PartialEq, Eq, Hash)]
12 #[repr(transparent)]
13 pub struct PipeResource {
14     pipe: NonNull<pipe_resource>,
15 }
16 
17 const PIPE_RESOURCE_FLAG_RUSTICL_IS_USER: u32 = PIPE_RESOURCE_FLAG_FRONTEND_PRIV;
18 
19 // SAFETY: pipe_resource is considered a thread safe type
20 unsafe impl Send for PipeResource {}
21 unsafe impl Sync for PipeResource {}
22 
23 /// A thread safe wrapper around [pipe_image_view]. It's purpose is to increase the reference count
24 /// on the [pipe_resource] this view belongs to.
25 #[repr(transparent)]
26 pub struct PipeImageView {
27     pub(super) pipe: pipe_image_view,
28 }
29 
30 impl PipeImageView {
new(pipe: pipe_image_view) -> Self31     fn new(pipe: pipe_image_view) -> Self {
32         unsafe { pipe_resource_reference(&mut ptr::null_mut(), pipe.resource) }
33         Self { pipe: pipe }
34     }
35 
slice_to_pipe(slice: &[PipeImageView]) -> &[pipe_image_view]36     pub fn slice_to_pipe(slice: &[PipeImageView]) -> &[pipe_image_view] {
37         // SAFETY: `PipeImageView` is a transparent wrapper around `pipe_image_view`, so transmute
38         //         on the slice is safe.
39         unsafe { mem::transmute(slice) }
40     }
41 }
42 
43 impl Drop for PipeImageView {
drop(&mut self)44     fn drop(&mut self) {
45         unsafe { pipe_resource_reference(&mut self.pipe.resource, ptr::null_mut()) }
46     }
47 }
48 
49 // SAFETY: pipe_image_view is just static data around a pipe_resource, which itself is a thread-safe
50 //         type.
51 unsafe impl Send for PipeImageView {}
52 unsafe impl Sync for PipeImageView {}
53 
54 // Image dimensions provide by application to be used in both
55 // image and sampler views when image is created from buffer
56 #[derive(PartialEq, Eq)]
57 pub struct AppImgInfo {
58     row_stride: u32,
59     width: u32,
60     height: u32,
61 }
62 
63 impl AppImgInfo {
new(row_stride: u32, width: u32, height: u32) -> AppImgInfo64     pub fn new(row_stride: u32, width: u32, height: u32) -> AppImgInfo {
65         AppImgInfo {
66             row_stride: row_stride,
67             width: width,
68             height: height,
69         }
70     }
71 }
72 
73 impl PipeResource {
new(res: *mut pipe_resource, is_user: bool) -> Option<Self>74     pub(super) fn new(res: *mut pipe_resource, is_user: bool) -> Option<Self> {
75         let mut res = NonNull::new(res)?;
76 
77         if is_user {
78             unsafe {
79                 res.as_mut().flags |= PIPE_RESOURCE_FLAG_RUSTICL_IS_USER;
80             }
81         }
82 
83         Some(Self { pipe: res })
84     }
85 
pipe(&self) -> *mut pipe_resource86     pub(super) fn pipe(&self) -> *mut pipe_resource {
87         self.pipe.as_ptr()
88     }
89 
as_ref(&self) -> &pipe_resource90     fn as_ref(&self) -> &pipe_resource {
91         // SAFETY: it contains a valid pointer
92         unsafe { self.pipe.as_ref() }
93     }
94 
width(&self) -> u3295     pub fn width(&self) -> u32 {
96         self.as_ref().width0
97     }
98 
height(&self) -> u1699     pub fn height(&self) -> u16 {
100         self.as_ref().height0
101     }
102 
depth(&self) -> u16103     pub fn depth(&self) -> u16 {
104         self.as_ref().depth0
105     }
106 
array_size(&self) -> u16107     pub fn array_size(&self) -> u16 {
108         self.as_ref().array_size
109     }
110 
is_buffer(&self) -> bool111     pub fn is_buffer(&self) -> bool {
112         self.as_ref().target() == pipe_texture_target::PIPE_BUFFER
113     }
114 
is_linear(&self) -> bool115     pub fn is_linear(&self) -> bool {
116         self.as_ref().bind & PIPE_BIND_LINEAR != 0
117     }
118 
is_staging(&self) -> bool119     pub fn is_staging(&self) -> bool {
120         self.as_ref().usage() == pipe_resource_usage::PIPE_USAGE_STAGING
121     }
122 
is_user(&self) -> bool123     pub fn is_user(&self) -> bool {
124         self.as_ref().flags & PIPE_RESOURCE_FLAG_RUSTICL_IS_USER != 0
125     }
126 
pipe_image_view(&self, read_write: bool, host_access: u16) -> PipeImageView127     pub fn pipe_image_view(&self, read_write: bool, host_access: u16) -> PipeImageView {
128         debug_assert!(!self.is_buffer());
129 
130         let pipe = self.as_ref();
131         let shader_access = if read_write {
132             PIPE_IMAGE_ACCESS_READ_WRITE
133         } else {
134             PIPE_IMAGE_ACCESS_WRITE
135         } as u16;
136 
137         let mut tex = pipe_image_view__bindgen_ty_1__bindgen_ty_1::default();
138         tex.set_level(0);
139         tex.set_first_layer(0);
140         if pipe.target() == pipe_texture_target::PIPE_TEXTURE_3D {
141             tex.set_last_layer((pipe.depth0 - 1).into());
142         } else {
143             tex.set_last_layer(pipe.array_size.saturating_sub(1).into());
144         }
145 
146         PipeImageView::new(pipe_image_view {
147             resource: self.pipe(),
148             format: pipe.format(),
149             access: host_access,
150             shader_access: shader_access,
151             u: pipe_image_view__bindgen_ty_1 { tex: tex },
152         })
153     }
154 
pipe_image_view_1d_buffer( &self, format: pipe_format, read_write: bool, host_access: u16, size: u32, ) -> PipeImageView155     pub fn pipe_image_view_1d_buffer(
156         &self,
157         format: pipe_format,
158         read_write: bool,
159         host_access: u16,
160         size: u32,
161     ) -> PipeImageView {
162         debug_assert!(self.is_buffer());
163 
164         let shader_access = if read_write {
165             PIPE_IMAGE_ACCESS_READ_WRITE
166         } else {
167             PIPE_IMAGE_ACCESS_WRITE
168         } as u16;
169 
170         PipeImageView::new(pipe_image_view {
171             resource: self.pipe(),
172             format: format,
173             access: host_access,
174             shader_access: shader_access,
175             u: pipe_image_view__bindgen_ty_1 {
176                 buf: pipe_image_view__bindgen_ty_1__bindgen_ty_2 {
177                     offset: 0,
178                     size: size,
179                 },
180             },
181         })
182     }
183 
pipe_image_view_2d_buffer( &self, format: pipe_format, read_write: bool, host_access: u16, app_img_info: &AppImgInfo, ) -> PipeImageView184     pub fn pipe_image_view_2d_buffer(
185         &self,
186         format: pipe_format,
187         read_write: bool,
188         host_access: u16,
189         app_img_info: &AppImgInfo,
190     ) -> PipeImageView {
191         debug_assert!(self.is_buffer());
192 
193         let shader_access = if read_write {
194             PIPE_IMAGE_ACCESS_READ_WRITE
195         } else {
196             PIPE_IMAGE_ACCESS_WRITE
197         } as u16;
198 
199         PipeImageView::new(pipe_image_view {
200             resource: self.pipe(),
201             format: format,
202             access: PIPE_IMAGE_ACCESS_TEX2D_FROM_BUFFER as u16 | host_access,
203             shader_access: shader_access,
204             u: pipe_image_view__bindgen_ty_1 {
205                 tex2d_from_buf: pipe_image_view__bindgen_ty_1__bindgen_ty_3 {
206                     offset: 0,
207                     row_stride: app_img_info.row_stride as u16,
208                     width: app_img_info.width as u16,
209                     height: app_img_info.height as u16,
210                 },
211             },
212         })
213     }
214 
pipe_sampler_view_template(&self) -> pipe_sampler_view215     pub fn pipe_sampler_view_template(&self) -> pipe_sampler_view {
216         debug_assert!(!self.is_buffer());
217 
218         let mut res = pipe_sampler_view::default();
219         unsafe {
220             u_sampler_view_default_template(&mut res, self.pipe(), self.as_ref().format());
221         }
222 
223         res
224     }
225 
pipe_sampler_view_template_1d_buffer( &self, format: pipe_format, size: u32, ) -> pipe_sampler_view226     pub fn pipe_sampler_view_template_1d_buffer(
227         &self,
228         format: pipe_format,
229         size: u32,
230     ) -> pipe_sampler_view {
231         debug_assert!(self.is_buffer());
232 
233         let mut res = pipe_sampler_view::default();
234         unsafe {
235             u_sampler_view_default_template(&mut res, self.pipe(), format);
236         }
237 
238         // write the entire union field because u_sampler_view_default_template might have left it
239         // in an undefined state.
240         res.u.buf = pipe_sampler_view__bindgen_ty_2__bindgen_ty_2 {
241             offset: 0,
242             size: size,
243         };
244 
245         res
246     }
247 
pipe_sampler_view_template_2d_buffer( &self, format: pipe_format, app_img_info: &AppImgInfo, ) -> pipe_sampler_view248     pub fn pipe_sampler_view_template_2d_buffer(
249         &self,
250         format: pipe_format,
251         app_img_info: &AppImgInfo,
252     ) -> pipe_sampler_view {
253         debug_assert!(self.is_buffer());
254 
255         let mut res = pipe_sampler_view::default();
256         unsafe {
257             u_sampler_view_default_template(&mut res, self.pipe(), format);
258         }
259 
260         // write the entire union field because u_sampler_view_default_template might have left it
261         // in an undefined state.
262         res.u.tex2d_from_buf = pipe_sampler_view__bindgen_ty_2__bindgen_ty_3 {
263             offset: 0,
264             row_stride: app_img_info.row_stride as u16,
265             width: app_img_info.width as u16,
266             height: app_img_info.height as u16,
267         };
268         res.set_is_tex2d_from_buf(true);
269 
270         res
271     }
272 }
273 
274 impl Drop for PipeResource {
drop(&mut self)275     fn drop(&mut self) {
276         unsafe { pipe_resource_reference(&mut self.pipe.as_ptr(), ptr::null_mut()) }
277     }
278 }
279 
280 /// Wrapper around gallium's pipe_sampler_view.
281 ///
282 /// It deals with the refcounting and frees the object automatically if not needed anymore.
283 #[repr(transparent)]
284 pub struct PipeSamplerView<'c, 'r> {
285     view: NonNull<pipe_sampler_view>,
286     // the pipe_sampler_view object references both a context and a resource.
287     _ctx: PhantomData<&'c PipeContext>,
288     _res: PhantomData<&'r PipeResource>,
289 }
290 
291 impl<'c, 'r> PipeSamplerView<'c, 'r> {
new( ctx: &'c PipeContext, res: &'r PipeResource, template: &pipe_sampler_view, ) -> Option<Self>292     pub fn new(
293         ctx: &'c PipeContext,
294         res: &'r PipeResource,
295         template: &pipe_sampler_view,
296     ) -> Option<Self> {
297         let view = unsafe {
298             ctx.pipe().as_ref().create_sampler_view.unwrap()(
299                 ctx.pipe().as_ptr(),
300                 res.pipe(),
301                 template,
302             )
303         };
304 
305         let view = NonNull::new(view)?;
306         unsafe {
307             debug_assert_eq!(view.as_ref().context, ctx.pipe().as_ptr());
308             debug_assert_eq!(view.as_ref().texture, res.pipe());
309         }
310 
311         Some(Self {
312             view: view,
313             _ctx: PhantomData,
314             _res: PhantomData,
315         })
316     }
317 
as_pipe(views: &mut [Self]) -> *mut *mut pipe_sampler_view318     pub(crate) fn as_pipe(views: &mut [Self]) -> *mut *mut pipe_sampler_view {
319         // We are transparent over *mut pipe_sample_view, so this is sound.
320         views.as_mut_ptr().cast()
321     }
322 }
323 
324 impl Drop for PipeSamplerView<'_, '_> {
drop(&mut self)325     fn drop(&mut self) {
326         unsafe {
327             pipe_sampler_view_reference(&mut ptr::null_mut(), self.view.as_ptr());
328         }
329     }
330 }
331