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