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.

288 lines
6.8 KiB

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