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
29pub struct Buffer<'a, T> {
33 device: &'a Device,
34 pub(crate) handle: RTCBuffer,
35 bytes: usize,
39 attachment: BufferAttachment,
40 marker: PhantomData<T>,
41}
42
43impl<'a, T> Buffer<'a, T> {
44 pub fn raw(device: &'a Device, bytes: usize) -> Buffer<'a, T> {
46 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 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 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 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}