embree3_arm/
buffer.rs

1use std::marker::PhantomData;
2use std::ops::{Index, IndexMut};
3use std::{mem, ptr};
4
5use device::Device;
6use sys::*;
7use BufferType;
8
9#[derive(Copy, Clone)]
10struct BufferAttachment {
11    geom: RTCGeometry,
12    buf_type: BufferType,
13    slot: u32,
14}
15
16impl BufferAttachment {
17    fn none() -> BufferAttachment {
18        BufferAttachment {
19            geom: ptr::null_mut(),
20            buf_type: BufferType::VERTEX,
21            slot: std::u32::MAX,
22        }
23    }
24    fn is_attached(&self) -> bool {
25        self.geom != ptr::null_mut()
26    }
27}
28
29// TODO: To handle this nicely for sharing/re-using/changing buffer views
30// we basically need an API/struct for making buffer views of existing
31// larger buffers.
32pub struct Buffer<'a, T> {
33    device: &'a Device,
34    pub(crate) handle: RTCBuffer,
35    // TODO: We need a list of RTCGeometry handles
36    // that we're attached to to mark buffers as updated on
37    // the geometries.
38    bytes: usize,
39    attachment: BufferAttachment,
40    marker: PhantomData<T>,
41}
42
43impl<'a, T> Buffer<'a, T> {
44    /// Allocate a buffer with some raw capacity in bytes
45    pub fn raw(device: &'a Device, bytes: usize) -> Buffer<'a, T> {
46        // Pad to a multiple of 16 bytes
47        let bytes = if bytes % 16 == 0 {
48            bytes
49        } else {
50            bytes + bytes / 16
51        };
52        Buffer {
53            device: device,
54            handle: unsafe { rtcNewBuffer(device.handle, bytes) },
55            bytes: bytes,
56            attachment: BufferAttachment::none(),
57            marker: PhantomData,
58        }
59    }
60    pub fn new(device: &'a Device, len: usize) -> Buffer<'a, T> {
61        let mut bytes = len * mem::size_of::<T>();
62        // Pad to a multiple of 16 bytes
63        bytes = if bytes % 16 == 0 {
64            bytes
65        } else {
66            bytes + bytes / 16
67        };
68        Buffer {
69            device: device,
70            handle: unsafe { rtcNewBuffer(device.handle, bytes) },
71            bytes: bytes,
72            attachment: BufferAttachment::none(),
73            marker: PhantomData,
74        }
75    }
76    pub fn map(&mut self) -> MappedBuffer<'a, T> {
77        let len = self.bytes / mem::size_of::<T>();
78        let slice = unsafe { rtcGetBufferData(self.handle) as *mut T };
79        MappedBuffer {
80            buffer: PhantomData,
81            attachment: self.attachment,
82            slice: slice,
83            len: len,
84        }
85    }
86    pub(crate) fn set_attachment(&mut self, geom: RTCGeometry, buf_type: BufferType, slot: u32) {
87        self.attachment.geom = geom;
88        self.attachment.buf_type = buf_type;
89        self.attachment.slot = slot;
90    }
91}
92
93impl<'a, T> Drop for Buffer<'a, T> {
94    fn drop(&mut self) {
95        unsafe {
96            rtcReleaseBuffer(self.handle);
97        }
98    }
99}
100
101unsafe impl<'a, T> Sync for Buffer<'a, T> {}
102
103pub struct MappedBuffer<'a, T: 'a> {
104    buffer: PhantomData<&'a mut Buffer<'a, T>>,
105    attachment: BufferAttachment,
106    slice: *mut T,
107    len: usize,
108}
109
110impl<'a, T: 'a> MappedBuffer<'a, T> {
111    pub fn len(&self) -> usize {
112        self.len
113    }
114}
115
116impl<'a, T: 'a> Drop for MappedBuffer<'a, T> {
117    fn drop(&mut self) {
118        if self.attachment.is_attached() {
119            // TODO: support for attaching one buffer to multiple geoms?
120            unsafe {
121                rtcUpdateGeometryBuffer(
122                    self.attachment.geom,
123                    self.attachment.buf_type,
124                    self.attachment.slot,
125                );
126            }
127        }
128    }
129}
130
131impl<'a, T: 'a> Index<usize> for MappedBuffer<'a, T> {
132    type Output = T;
133
134    fn index(&self, index: usize) -> &T {
135        // TODO: We should only check in debug build
136        if index >= self.len {
137            panic!("MappedBuffer index out of bounds");
138        }
139        unsafe { &*self.slice.offset(index as isize) }
140    }
141}
142
143impl<'a, T: 'a> IndexMut<usize> for MappedBuffer<'a, T> {
144    fn index_mut(&mut self, index: usize) -> &mut T {
145        if index >= self.len {
146            panic!("MappedBuffer index out of bounds");
147        }
148        unsafe { &mut *self.slice.offset(index as isize) }
149    }
150}