use std::marker::PhantomData;
use std::ops::{Index, IndexMut};
use std::{mem, ptr};
use device::Device;
use sys::*;
use BufferType;
#[derive(Copy, Clone)]
struct BufferAttachment {
geom: RTCGeometry,
buf_type: BufferType,
slot: u32,
}
impl BufferAttachment {
fn none() -> BufferAttachment {
BufferAttachment {
geom: ptr::null_mut(),
buf_type: BufferType::VERTEX,
slot: std::u32::MAX,
}
}
fn is_attached(&self) -> bool {
self.geom != ptr::null_mut()
}
}
pub struct Buffer<'a, T> {
device: &'a Device,
pub(crate) handle: RTCBuffer,
bytes: usize,
attachment: BufferAttachment,
marker: PhantomData<T>,
}
impl<'a, T> Buffer<'a, T> {
pub fn raw(device: &'a Device, bytes: usize) -> Buffer<'a, T> {
let bytes = if bytes % 16 == 0 {
bytes
} else {
bytes + bytes / 16
};
Buffer {
device: device,
handle: unsafe { rtcNewBuffer(device.handle, bytes) },
bytes: bytes,
attachment: BufferAttachment::none(),
marker: PhantomData,
}
}
pub fn new(device: &'a Device, len: usize) -> Buffer<'a, T> {
let mut bytes = len * mem::size_of::<T>();
bytes = if bytes % 16 == 0 {
bytes
} else {
bytes + bytes / 16
};
Buffer {
device: device,
handle: unsafe { rtcNewBuffer(device.handle, bytes) },
bytes: bytes,
attachment: BufferAttachment::none(),
marker: PhantomData,
}
}
pub fn map(&mut self) -> MappedBuffer<'a, T> {
let len = self.bytes / mem::size_of::<T>();
let slice = unsafe { rtcGetBufferData(self.handle) as *mut T };
MappedBuffer {
buffer: PhantomData,
attachment: self.attachment,
slice: slice,
len: len,
}
}
pub(crate) fn set_attachment(&mut self, geom: RTCGeometry, buf_type: BufferType, slot: u32) {
self.attachment.geom = geom;
self.attachment.buf_type = buf_type;
self.attachment.slot = slot;
}
}
impl<'a, T> Drop for Buffer<'a, T> {
fn drop(&mut self) {
unsafe {
rtcReleaseBuffer(self.handle);
}
}
}
unsafe impl<'a, T> Sync for Buffer<'a, T> {}
pub struct MappedBuffer<'a, T: 'a> {
buffer: PhantomData<&'a mut Buffer<'a, T>>,
attachment: BufferAttachment,
slice: *mut T,
len: usize,
}
impl<'a, T: 'a> MappedBuffer<'a, T> {
pub fn len(&self) -> usize {
self.len
}
}
impl<'a, T: 'a> Drop for MappedBuffer<'a, T> {
fn drop(&mut self) {
if self.attachment.is_attached() {
unsafe {
rtcUpdateGeometryBuffer(
self.attachment.geom,
self.attachment.buf_type,
self.attachment.slot,
);
}
}
}
}
impl<'a, T: 'a> Index<usize> for MappedBuffer<'a, T> {
type Output = T;
fn index(&self, index: usize) -> &T {
if index >= self.len {
panic!("MappedBuffer index out of bounds");
}
unsafe { &*self.slice.offset(index as isize) }
}
}
impl<'a, T: 'a> IndexMut<usize> for MappedBuffer<'a, T> {
fn index_mut(&mut self, index: usize) -> &mut T {
if index >= self.len {
panic!("MappedBuffer index out of bounds");
}
unsafe { &mut *self.slice.offset(index as isize) }
}
}