xref: /aosp_15_r20/external/mesa3d/src/gallium/frontends/rusticl/mesa/pipe/resource.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 use mesa_rust_gen::*;
2 
3 use std::{mem, ptr};
4 
5 #[derive(PartialEq, Eq, Hash)]
6 #[repr(transparent)]
7 pub struct PipeResource {
8     pipe: *mut pipe_resource,
9 }
10 
11 const PIPE_RESOURCE_FLAG_RUSTICL_IS_USER: u32 = PIPE_RESOURCE_FLAG_FRONTEND_PRIV;
12 
13 // SAFETY: pipe_resource is considered a thread safe type
14 unsafe impl Send for PipeResource {}
15 unsafe impl Sync for PipeResource {}
16 
17 /// A thread safe wrapper around [pipe_image_view]. It's purpose is to increase the reference count
18 /// on the [pipe_resource] this view belongs to.
19 #[repr(transparent)]
20 pub struct PipeImageView {
21     pub(super) pipe: pipe_image_view,
22 }
23 
24 impl PipeImageView {
new(pipe: pipe_image_view) -> Self25     fn new(pipe: pipe_image_view) -> Self {
26         unsafe { pipe_resource_reference(&mut ptr::null_mut(), pipe.resource) }
27         Self { pipe: pipe }
28     }
29 
slice_to_pipe(slice: &[PipeImageView]) -> &[pipe_image_view]30     pub fn slice_to_pipe(slice: &[PipeImageView]) -> &[pipe_image_view] {
31         // SAFETY: `PipeImageView` is a transparent wrapper around `pipe_image_view`, so transmute
32         //         on the slice is safe.
33         unsafe { mem::transmute(slice) }
34     }
35 }
36 
37 impl Drop for PipeImageView {
drop(&mut self)38     fn drop(&mut self) {
39         unsafe { pipe_resource_reference(&mut self.pipe.resource, ptr::null_mut()) }
40     }
41 }
42 
43 // SAFETY: pipe_image_view is just static data around a pipe_resource, which itself is a thread-safe
44 //         type.
45 unsafe impl Send for PipeImageView {}
46 unsafe impl Sync for PipeImageView {}
47 
48 // Image dimensions provide by application to be used in both
49 // image and sampler views when image is created from buffer
50 #[derive(PartialEq, Eq)]
51 pub struct AppImgInfo {
52     row_stride: u32,
53     width: u32,
54     height: u32,
55 }
56 
57 impl AppImgInfo {
new(row_stride: u32, width: u32, height: u32) -> AppImgInfo58     pub fn new(row_stride: u32, width: u32, height: u32) -> AppImgInfo {
59         AppImgInfo {
60             row_stride: row_stride,
61             width: width,
62             height: height,
63         }
64     }
65 }
66 
67 impl PipeResource {
new(res: *mut pipe_resource, is_user: bool) -> Option<Self>68     pub(super) fn new(res: *mut pipe_resource, is_user: bool) -> Option<Self> {
69         if res.is_null() {
70             return None;
71         }
72 
73         if is_user {
74             unsafe {
75                 res.as_mut().unwrap().flags |= PIPE_RESOURCE_FLAG_RUSTICL_IS_USER;
76             }
77         }
78 
79         Some(Self { pipe: res })
80     }
81 
pipe(&self) -> *mut pipe_resource82     pub(super) fn pipe(&self) -> *mut pipe_resource {
83         self.pipe
84     }
85 
as_ref(&self) -> &pipe_resource86     fn as_ref(&self) -> &pipe_resource {
87         unsafe { self.pipe.as_ref().unwrap() }
88     }
89 
width(&self) -> u3290     pub fn width(&self) -> u32 {
91         unsafe { self.pipe.as_ref().unwrap().width0 }
92     }
93 
height(&self) -> u1694     pub fn height(&self) -> u16 {
95         unsafe { self.pipe.as_ref().unwrap().height0 }
96     }
97 
depth(&self) -> u1698     pub fn depth(&self) -> u16 {
99         unsafe { self.pipe.as_ref().unwrap().depth0 }
100     }
101 
array_size(&self) -> u16102     pub fn array_size(&self) -> u16 {
103         unsafe { self.pipe.as_ref().unwrap().array_size }
104     }
105 
is_buffer(&self) -> bool106     pub fn is_buffer(&self) -> bool {
107         self.as_ref().target() == pipe_texture_target::PIPE_BUFFER
108     }
109 
is_linear(&self) -> bool110     pub fn is_linear(&self) -> bool {
111         self.as_ref().bind & PIPE_BIND_LINEAR != 0
112     }
113 
is_staging(&self) -> bool114     pub fn is_staging(&self) -> bool {
115         self.as_ref().usage() == pipe_resource_usage::PIPE_USAGE_STAGING
116     }
117 
is_user(&self) -> bool118     pub fn is_user(&self) -> bool {
119         self.as_ref().flags & PIPE_RESOURCE_FLAG_RUSTICL_IS_USER != 0
120     }
121 
pipe_image_view( &self, format: pipe_format, read_write: bool, host_access: u16, app_img_info: Option<&AppImgInfo>, ) -> PipeImageView122     pub fn pipe_image_view(
123         &self,
124         format: pipe_format,
125         read_write: bool,
126         host_access: u16,
127         app_img_info: Option<&AppImgInfo>,
128     ) -> PipeImageView {
129         let pipe = PipeResource::as_ref(self);
130         let u = if let Some(app_img_info) = app_img_info {
131             pipe_image_view__bindgen_ty_1 {
132                 tex2d_from_buf: pipe_image_view__bindgen_ty_1__bindgen_ty_3 {
133                     offset: 0,
134                     row_stride: app_img_info.row_stride as u16,
135                     width: app_img_info.width as u16,
136                     height: app_img_info.height as u16,
137                 },
138             }
139         } else if self.is_buffer() {
140             pipe_image_view__bindgen_ty_1 {
141                 buf: pipe_image_view__bindgen_ty_1__bindgen_ty_2 {
142                     offset: 0,
143                     size: pipe.width0,
144                 },
145             }
146         } else {
147             let mut tex = pipe_image_view__bindgen_ty_1__bindgen_ty_1::default();
148             tex.set_level(0);
149             tex.set_first_layer(0);
150             if pipe.target() == pipe_texture_target::PIPE_TEXTURE_3D {
151                 tex.set_last_layer((pipe.depth0 - 1).into());
152             } else if pipe.array_size > 0 {
153                 tex.set_last_layer((pipe.array_size - 1).into());
154             } else {
155                 tex.set_last_layer(0);
156             }
157 
158             pipe_image_view__bindgen_ty_1 { tex: tex }
159         };
160 
161         let shader_access = if read_write {
162             PIPE_IMAGE_ACCESS_READ_WRITE
163         } else {
164             PIPE_IMAGE_ACCESS_WRITE
165         } as u16;
166 
167         let access = if app_img_info.is_some() {
168             PIPE_IMAGE_ACCESS_TEX2D_FROM_BUFFER
169         } else {
170             0
171         } as u16;
172 
173         PipeImageView::new(pipe_image_view {
174             resource: self.pipe(),
175             format: format,
176             access: access | host_access,
177             shader_access: shader_access,
178             u: u,
179         })
180     }
181 
pipe_sampler_view_template( &self, format: pipe_format, app_img_info: Option<&AppImgInfo>, ) -> pipe_sampler_view182     pub fn pipe_sampler_view_template(
183         &self,
184         format: pipe_format,
185         app_img_info: Option<&AppImgInfo>,
186     ) -> pipe_sampler_view {
187         let mut res = pipe_sampler_view::default();
188         unsafe {
189             u_sampler_view_default_template(&mut res, self.pipe, format);
190         }
191 
192         if let Some(app_img_info) = app_img_info {
193             res.u.tex2d_from_buf.offset = 0;
194             res.u.tex2d_from_buf.row_stride = app_img_info.row_stride as u16;
195             res.u.tex2d_from_buf.width = app_img_info.width as u16;
196             res.u.tex2d_from_buf.height = app_img_info.height as u16;
197 
198             res.set_is_tex2d_from_buf(true);
199         } else if res.target() == pipe_texture_target::PIPE_BUFFER {
200             res.u.buf.offset = 0;
201             res.u.buf.size = self.as_ref().width0;
202         }
203 
204         res
205     }
206 }
207 
208 impl Drop for PipeResource {
drop(&mut self)209     fn drop(&mut self) {
210         unsafe { pipe_resource_reference(&mut self.pipe, ptr::null_mut()) }
211     }
212 }
213