1use std::marker::PhantomData;
2use std::{mem, ptr};
3use std::ops::{Index, IndexMut};
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 { bytes } else { bytes + bytes / 16};
48 Buffer {
49 device: device,
50 handle: unsafe { rtcNewBuffer(device.handle, bytes) },
51 bytes: bytes,
52 attachment: BufferAttachment::none(),
53 marker: PhantomData,
54 }
55 }
56 pub fn new(device: &'a Device, len: usize) -> Buffer<'a, T> {
57 let mut bytes = len * mem::size_of::<T>();
58 bytes = if bytes % 16 == 0 { bytes } else { bytes + bytes / 16};
60 Buffer {
61 device: device,
62 handle: unsafe { rtcNewBuffer(device.handle, bytes) },
63 bytes: bytes,
64 attachment: BufferAttachment::none(),
65 marker: PhantomData,
66 }
67 }
68 pub fn map(&mut self) -> MappedBuffer<'a, T> {
69 let len = self.bytes / mem::size_of::<T>();
70 let slice = unsafe { rtcGetBufferData(self.handle) as *mut T };
71 MappedBuffer {
72 buffer: PhantomData,
73 attachment: self.attachment,
74 slice: slice,
75 len: len,
76 }
77 }
78 pub(crate) fn set_attachment(&mut self, geom: RTCGeometry,
79 buf_type: BufferType, slot: u32)
80 {
81 self.attachment.geom = geom;
82 self.attachment.buf_type = buf_type;
83 self.attachment.slot = slot;
84 }
85}
86
87impl<'a, T> Drop for Buffer<'a, T> {
88 fn drop(&mut self) {
89 unsafe {
90 rtcReleaseBuffer(self.handle);
91 }
92 }
93}
94
95unsafe impl<'a, T> Sync for Buffer<'a, T> {}
96
97pub struct MappedBuffer<'a, T: 'a> {
98 buffer: PhantomData<&'a mut Buffer<'a, T>>,
99 attachment: BufferAttachment,
100 slice: *mut T,
101 len: usize,
102}
103
104impl<'a, T: 'a> MappedBuffer<'a, T> {
105 pub fn len(&self) -> usize {
106 self.len
107 }
108}
109
110impl<'a, T: 'a> Drop for MappedBuffer<'a, T> {
111 fn drop(&mut self) {
112 if self.attachment.is_attached() {
113 unsafe {
115 rtcUpdateGeometryBuffer(
116 self.attachment.geom,
117 self.attachment.buf_type,
118 self.attachment.slot
119 );
120 }
121 }
122 }
123}
124
125impl<'a, T: 'a> Index<usize> for MappedBuffer<'a, T> {
126 type Output = T;
127
128 fn index(&self, index: usize) -> &T {
129 if index >= self.len {
131 panic!("MappedBuffer index out of bounds");
132 }
133 unsafe { &*self.slice.offset(index as isize) }
134 }
135}
136
137impl<'a, T: 'a> IndexMut<usize> for MappedBuffer<'a, T> {
138 fn index_mut(&mut self, index: usize) -> &mut T {
139 if index >= self.len {
140 panic!("MappedBuffer index out of bounds");
141 }
142 unsafe { &mut *self.slice.offset(index as isize) }
143 }
144}