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.

118 lines
2.4 KiB

  1. use crate::{
  2. buffer::{Buffer, BufferRef, Target},
  3. error::Error,
  4. misc::{BindGuard, Bindable},
  5. };
  6. /* TransformFeedback */
  7. pub struct TransformFeedback<T = Buffer> {
  8. id: gl::GLuint,
  9. buffers: Vec<T>,
  10. }
  11. impl<T> TransformFeedback<T> {
  12. pub fn builder() -> Builder<T> {
  13. Builder::default()
  14. }
  15. pub fn id(&self) -> gl::GLuint {
  16. self.id
  17. }
  18. pub fn buffers(&self) -> &[T] {
  19. &self.buffers
  20. }
  21. pub fn buffers_mut(&mut self) -> &mut [T] {
  22. &mut self.buffers
  23. }
  24. }
  25. impl<T> Drop for TransformFeedback<T> {
  26. fn drop(&mut self) {
  27. gl::delete_transform_feedbacks(1, &self.id);
  28. }
  29. }
  30. impl<T> Bindable for TransformFeedback<T> {
  31. fn bind(&self) {
  32. gl::bind_transform_feedback(gl::TRANSFORM_FEEDBACK, self.id);
  33. }
  34. fn unbind(&self) {
  35. gl::bind_transform_feedback(gl::TRANSFORM_FEEDBACK, 0);
  36. }
  37. }
  38. /* Builder */
  39. pub struct Builder<T> {
  40. bindings: Vec<Binding<T>>,
  41. }
  42. impl<T> Builder<T>
  43. where
  44. for<'a> &'a T: BufferRef,
  45. {
  46. pub fn bind_buffer(mut self, index: gl::GLuint, buffer: T) -> Result<Builder<T>, Error> {
  47. for binding in &self.bindings {
  48. if binding.index == index {
  49. return Err(Error::TransformFeedbackIndexAlreadyInUse(index));
  50. }
  51. }
  52. let binding = Binding { buffer, index };
  53. self.bindings.push(binding);
  54. Ok(self)
  55. }
  56. pub fn build(self) -> Result<TransformFeedback<T>, Error> {
  57. let mut id = 0;
  58. Error::checked(|| gl::create_transform_feedbacks(1, &mut id))?;
  59. let mut transform_feedback = TransformFeedback {
  60. id,
  61. buffers: Vec::new(),
  62. };
  63. let guard = BindGuard::new(&transform_feedback);
  64. let mut buffers = Vec::new();
  65. for binding in self.bindings {
  66. Error::checked(|| {
  67. binding
  68. .buffer
  69. .as_ref()
  70. .bind_buffer_base(Target::TransformFeedbackBuffer, binding.index)
  71. })?;
  72. buffers.push(binding.buffer);
  73. }
  74. drop(guard);
  75. transform_feedback.buffers = buffers;
  76. Ok(transform_feedback)
  77. }
  78. }
  79. impl<T> Default for Builder<T> {
  80. fn default() -> Self {
  81. Self {
  82. bindings: Vec::new(),
  83. }
  84. }
  85. }
  86. /* Binding */
  87. struct Binding<T> {
  88. buffer: T,
  89. index: gl::GLuint,
  90. }