You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

329 lines
7.5 KiB

  1. use std::cell::{Ref, RefCell};
  2. use std::mem::size_of;
  3. use std::ops::{Deref, DerefMut};
  4. use std::ptr::null;
  5. use std::rc::Rc;
  6. use std::slice::from_raw_parts_mut;
  7. use crate::{
  8. error::Error,
  9. misc::{AsEnum, Bindable},
  10. };
  11. /* Buffer */
  12. pub struct Buffer {
  13. id: gl::GLuint,
  14. size: usize,
  15. }
  16. impl Buffer {
  17. pub fn new() -> Result<Self, Error> {
  18. let mut id = 0;
  19. Error::checked(|| gl::create_buffers(1, &mut id))?;
  20. Ok(Self { id, size: 0 })
  21. }
  22. pub fn id(&self) -> gl::GLuint {
  23. self.id
  24. }
  25. pub fn size(&self) -> usize {
  26. self.size
  27. }
  28. pub fn buffer_data<T>(&mut self, usage: Usage, data: &[T]) -> Result<(), Error> {
  29. let size = data.len() * size_of::<T>();
  30. Error::checked(|| {
  31. gl::named_buffer_data(
  32. self.id,
  33. size as gl::GLsizeiptr,
  34. data.as_ptr() as *const _,
  35. usage.as_enum(),
  36. )
  37. })?;
  38. self.size = size;
  39. Ok(())
  40. }
  41. pub fn buffer_size(&mut self, usage: Usage, size: usize) -> Result<(), Error> {
  42. Error::checked(|| {
  43. gl::named_buffer_data(self.id, size as gl::GLsizeiptr, null(), usage.as_enum())
  44. })?;
  45. self.size = size;
  46. Ok(())
  47. }
  48. pub fn map<T>(&self) -> Result<Map<'_, T>, Error> {
  49. Ok(Map {
  50. data: self.inner_map(gl::READ_ONLY)?,
  51. buf: self,
  52. })
  53. }
  54. pub fn map_mut<T>(&mut self, write_only: bool) -> Result<MapMut<'_, T>, Error> {
  55. Ok(MapMut {
  56. data: self.inner_map(if write_only {
  57. gl::WRITE_ONLY
  58. } else {
  59. gl::READ_WRITE
  60. })?,
  61. buf: self,
  62. })
  63. }
  64. pub fn map_range<T>(
  65. &self,
  66. byte_offset: usize,
  67. value_count: Option<usize>,
  68. ) -> Result<Map<'_, T>, Error> {
  69. Ok(Map {
  70. data: self.inner_map_range(gl::READ_ONLY, byte_offset, value_count)?,
  71. buf: self,
  72. })
  73. }
  74. pub fn map_range_mut<T>(
  75. &mut self,
  76. write_only: bool,
  77. byte_offset: usize,
  78. value_count: Option<usize>,
  79. ) -> Result<MapMut<'_, T>, Error> {
  80. let access = if write_only {
  81. gl::WRITE_ONLY
  82. } else {
  83. gl::READ_WRITE
  84. };
  85. Ok(MapMut {
  86. data: self.inner_map_range(access, byte_offset, value_count)?,
  87. buf: self,
  88. })
  89. }
  90. pub fn bind_buffer_base(&self, target: Target, index: gl::GLuint) {
  91. gl::bind_buffer_base(target.as_enum(), index, self.id);
  92. }
  93. pub fn bind_buffer_range(
  94. &self,
  95. target: Target,
  96. index: gl::GLuint,
  97. offset: gl::GLintptr,
  98. size: gl::GLsizeiptr,
  99. ) {
  100. gl::bind_buffer_range(target.as_enum(), index, self.id, offset, size);
  101. }
  102. fn inner_map<T>(&self, access: gl::GLenum) -> Result<&mut [T], Error> {
  103. let ptr = Error::err_if(&null(), gl::map_named_buffer(self.id, access))?;
  104. let count = self.size / size_of::<T>();
  105. Ok(unsafe { from_raw_parts_mut(ptr as *mut T, count) })
  106. }
  107. pub fn inner_map_range<T>(
  108. &self,
  109. access: gl::GLenum,
  110. byte_offset: usize,
  111. value_count: Option<usize>,
  112. ) -> Result<&mut [T], Error> {
  113. let count = value_count.unwrap_or_else(|| {
  114. if self.size > byte_offset {
  115. (self.size - byte_offset) / size_of::<T>()
  116. } else {
  117. 0
  118. }
  119. });
  120. if byte_offset + count * size_of::<T>() > self.size {
  121. return Err(Error::InvalidParameter);
  122. }
  123. let size = count * size_of::<T>();
  124. let ptr = Error::err_if(
  125. &null(),
  126. gl::map_named_buffer_range(self.id, byte_offset as isize, size as isize, access),
  127. )?;
  128. Ok(unsafe { from_raw_parts_mut(ptr as *mut T, count) })
  129. }
  130. }
  131. impl Drop for Buffer {
  132. fn drop(&mut self) {
  133. gl::delete_buffers(1, &self.id);
  134. }
  135. }
  136. impl<T> Bindable for (Target, T)
  137. where
  138. T: Deref<Target = Buffer>,
  139. {
  140. fn bind(&self) {
  141. gl::bind_buffer(self.0.as_enum(), self.1.id);
  142. }
  143. fn unbind(&self) {
  144. gl::bind_buffer(self.0.as_enum(), 0);
  145. }
  146. }
  147. /* Map */
  148. pub struct Map<'a, T> {
  149. buf: &'a Buffer,
  150. data: &'a [T],
  151. }
  152. impl<T> Drop for Map<'_, T> {
  153. fn drop(&mut self) {
  154. gl::unmap_named_buffer(self.buf.id);
  155. }
  156. }
  157. impl<T> Deref for Map<'_, T> {
  158. type Target = [T];
  159. fn deref(&self) -> &Self::Target {
  160. self.data
  161. }
  162. }
  163. /* MapMut */
  164. pub struct MapMut<'a, T> {
  165. buf: &'a Buffer,
  166. data: &'a mut [T],
  167. }
  168. impl<T> Drop for MapMut<'_, T> {
  169. fn drop(&mut self) {
  170. gl::unmap_named_buffer(self.buf.id);
  171. }
  172. }
  173. impl<T> Deref for MapMut<'_, T> {
  174. type Target = [T];
  175. fn deref(&self) -> &Self::Target {
  176. self.data
  177. }
  178. }
  179. impl<T> DerefMut for MapMut<'_, T> {
  180. fn deref_mut(&mut self) -> &mut Self::Target {
  181. self.data
  182. }
  183. }
  184. /* BufferRef */
  185. pub trait BufferRef {
  186. type Output: Deref<Target = Buffer>;
  187. fn as_ref(self) -> Self::Output;
  188. }
  189. impl<'a> BufferRef for &'a Buffer {
  190. type Output = &'a Buffer;
  191. fn as_ref(self) -> Self::Output {
  192. self
  193. }
  194. }
  195. impl<'a> BufferRef for &'a RefCell<Buffer> {
  196. type Output = Ref<'a, Buffer>;
  197. fn as_ref(self) -> Self::Output {
  198. self.borrow()
  199. }
  200. }
  201. impl<'a> BufferRef for &'a Rc<RefCell<Buffer>> {
  202. type Output = Ref<'a, Buffer>;
  203. fn as_ref(self) -> Self::Output {
  204. self.borrow()
  205. }
  206. }
  207. /* Target */
  208. #[derive(Debug, Copy, Clone, Eq, PartialEq)]
  209. pub enum Target {
  210. ArrayBuffer,
  211. AtomicCounterBuffer,
  212. CopyReadBuffer,
  213. CopyWriteBuffer,
  214. DispatchIndirectBuffer,
  215. DrawIndirectBuffer,
  216. ElementArrayBuffer,
  217. PixelPackBuffer,
  218. PixelUnpackBuffer,
  219. QueryBuffer,
  220. ShaderStorageBuffer,
  221. TextureBuffer,
  222. TransformFeedbackBuffer,
  223. UniformBuffer,
  224. }
  225. impl AsEnum for Target {
  226. fn as_enum(&self) -> gl::GLenum {
  227. match self {
  228. Self::ArrayBuffer => gl::ARRAY_BUFFER,
  229. Self::AtomicCounterBuffer => gl::ATOMIC_COUNTER_BUFFER,
  230. Self::CopyReadBuffer => gl::COPY_READ_BUFFER,
  231. Self::CopyWriteBuffer => gl::COPY_WRITE_BUFFER,
  232. Self::DispatchIndirectBuffer => gl::DISPATCH_INDIRECT_BUFFER,
  233. Self::DrawIndirectBuffer => gl::DRAW_INDIRECT_BUFFER,
  234. Self::ElementArrayBuffer => gl::ELEMENT_ARRAY_BUFFER,
  235. Self::PixelPackBuffer => gl::PIXEL_PACK_BUFFER,
  236. Self::PixelUnpackBuffer => gl::PIXEL_UNPACK_BUFFER,
  237. Self::QueryBuffer => gl::QUERY_BUFFER,
  238. Self::ShaderStorageBuffer => gl::SHADER_STORAGE_BUFFER,
  239. Self::TextureBuffer => gl::TEXTURE_BUFFER,
  240. Self::TransformFeedbackBuffer => gl::TRANSFORM_FEEDBACK_BUFFER,
  241. Self::UniformBuffer => gl::UNIFORM_BUFFER,
  242. }
  243. }
  244. }
  245. /* Usage */
  246. pub enum Usage {
  247. StreamDraw,
  248. StreamRead,
  249. StreamCopy,
  250. StaticDraw,
  251. StaticRead,
  252. StatidCopy,
  253. DynamicDraw,
  254. DynamicRead,
  255. DynamicCopy,
  256. }
  257. impl AsEnum for Usage {
  258. fn as_enum(&self) -> gl::GLenum {
  259. match self {
  260. Self::StreamDraw => gl::STREAM_DRAW,
  261. Self::StreamRead => gl::STREAM_READ,
  262. Self::StreamCopy => gl::STREAM_COPY,
  263. Self::StaticDraw => gl::STATIC_DRAW,
  264. Self::StaticRead => gl::STATIC_READ,
  265. Self::StatidCopy => gl::STATIC_COPY,
  266. Self::DynamicDraw => gl::DYNAMIC_DRAW,
  267. Self::DynamicRead => gl::DYNAMIC_READ,
  268. Self::DynamicCopy => gl::DYNAMIC_COPY,
  269. }
  270. }
  271. }