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