use gl;
use super::traits::*;
use std::mem;
use std::ptr;
use std::slice;
use std::thread::ThreadId;
use std::marker::PhantomData;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
bitflags!{
pub struct MapReadFlags: u32{
const COHERENT = gl::MAP_COHERENT_BIT;
const UNSYNCHRONIZED = gl::MAP_UNSYNCHRONIZED_BIT;
}
}
#[cfg(feature = "gles")]
bitflags!{
pub struct MapReadFlags: u32{
const COHERENT = gl::MAP_COHERENT_BIT_EXT;
const UNSYNCHRONIZED = gl::MAP_UNSYNCHRONIZED_BIT;
}
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
bitflags!{
pub struct MapWriteFlags: u32{
const COHERENT = gl::MAP_COHERENT_BIT;
const UNSYNCHRONIZED = gl::MAP_UNSYNCHRONIZED_BIT;
const INVALIDATE_BUFFER = gl::MAP_INVALIDATE_BUFFER_BIT;
const INVALIDATE_RANGE = gl::MAP_INVALIDATE_RANGE_BIT;
const FLUSH_EXPLICIT = gl::MAP_FLUSH_EXPLICIT_BIT;
}
}
#[cfg(feature = "gles")]
bitflags!{
pub struct MapWriteFlags: u32{
const COHERENT = gl::MAP_COHERENT_BIT_EXT;
const UNSYNCHRONIZED = gl::MAP_UNSYNCHRONIZED_BIT;
const INVALIDATE_BUFFER = gl::MAP_INVALIDATE_BUFFER_BIT;
const INVALIDATE_RANGE = gl::MAP_INVALIDATE_RANGE_BIT;
const FLUSH_EXPLICIT = gl::MAP_FLUSH_EXPLICIT_BIT;
}
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
bitflags!{
pub struct MapReadWriteFlags: u32{
const COHERENT = gl::MAP_COHERENT_BIT;
const UNSYNCHRONIZED = gl::MAP_UNSYNCHRONIZED_BIT;
const FLUSH_EXPLICIT = gl::MAP_FLUSH_EXPLICIT_BIT;
}
}
#[cfg(feature = "gles")]
bitflags!{
pub struct MapReadWriteFlags: u32{
const COHERENT = gl::MAP_COHERENT_BIT_EXT;
const UNSYNCHRONIZED = gl::MAP_UNSYNCHRONIZED_BIT;
const FLUSH_EXPLICIT = gl::MAP_FLUSH_EXPLICIT_BIT;
}
}
#[derive(Debug)]
struct SendBufferDropper<T, B: TypedBuffer<T>>{
buffer: B,
thread_id: Option<ThreadId>,
marker: PhantomData<T>,
}
unsafe impl<T, B: TypedBuffer<T>> Send for SendBufferDropper<T, B> {}
unsafe impl<T, B: TypedBuffer<T>> Sync for SendBufferDropper<T, B> {}
impl<T, B: TypedBuffer<T>> Drop for SendBufferDropper<T,B> {
fn drop(&mut self) {
if self.thread_id.is_some() {
if self.thread_id != Some(std::thread::current().id()) {
panic!( "Dropped persistent map from a different thread to the one it was created from.")
}else{
unsafe{ self.buffer.unmap() };
}
}
}
}
impl<T, B: TypedBuffer<T>> SendBufferDropper<T,B> {
fn destructure(self) -> (B, Option<ThreadId>){
let maybe_uninit = ::std::mem::MaybeUninit::new(self);
unsafe {
let self_ref = &*maybe_uninit.as_ptr();
(::std::ptr::read(&self_ref.buffer), ::std::ptr::read(&self_ref.thread_id))
}
}
}
#[derive(Debug)]
pub struct MapPersistentRead<T: 'static, B: TypedBuffer<T>> {
map: &'static [T],
buffer: SendBufferDropper<T,B>,
}
impl<T: 'static, B: TypedBuffer<T>> MapPersistentRead<T,B>{
pub(super) fn new(map: &'static [T], buffer: B) -> MapPersistentRead<T, B>{
MapPersistentRead{
map,
buffer: SendBufferDropper{
buffer,
thread_id: Some(std::thread::current().id()),
marker: PhantomData,
},
}
}
pub fn data(&self) -> &[T]{
self.map
}
}
impl<T: 'static, B: BufferRange<T>> MapPersistentRead<T,B>
where for<'a> &'a B: TypedBuffer<T>
{
pub fn range<R: InputRange>(&self, range: R) -> MapPersistentRead<T, &B> {
MapPersistentRead {
map: &self.map[range.to_range(&self.buffer.buffer)],
buffer: SendBufferDropper{
buffer: &self.buffer.buffer,
thread_id: None,
marker: PhantomData,
}
}
}
}
impl<T: 'static, B: BufferRange<T>> MapPersistentRead<T,B>{
pub fn into_range<R: InputRange>(self, range: R) -> MapPersistentRead<T, B> {
MapPersistentRead {
map: &self.map[range.to_range(&self.buffer.buffer)],
buffer: self.buffer,
}
}
}
impl<B: BufferRange<u8>> MapPersistentRead<u8,B> {
pub fn cast<T>(self) -> MapPersistentRead<T, <B as Cast<T>>::CastTo>
where
B: Cast<T>,
<B as Cast<T>>::CastTo: TypedBuffer<T>
{
let (buffer, thread_id) = self.buffer.destructure();
let buffer = buffer.cast();
let len = self.map.len() / mem::size_of::<T>();
let map = unsafe{ slice::from_raw_parts(self.map.as_ptr() as *const T, len) };
MapPersistentRead{
buffer: SendBufferDropper{
buffer,
thread_id,
marker: PhantomData,
},
map,
}
}
}
#[derive(Debug)]
pub struct MapPersistentWrite<T: 'static, B: TypedBuffer<T>> {
map: &'static mut [T],
buffer: SendBufferDropper<T, B>,
}
impl<T: 'static, B: TypedBuffer<T>> MapPersistentWrite<T,B>{
pub(super) fn new(map: &'static mut [T], buffer: B) -> MapPersistentWrite<T, B>{
MapPersistentWrite{
map,
buffer: SendBufferDropper{
buffer,
thread_id: Some(std::thread::current().id()),
marker: PhantomData,
},
}
}
pub fn update(&mut self, data: &[T]) {
assert!(data.len() <= self.map.len());
unsafe{ ptr::copy_nonoverlapping(data.as_ptr(), self.map.as_mut_ptr(), data.len()) }
}
pub unsafe fn data_mut(&mut self) -> &mut [T]{
self.map
}
}
impl<T: 'static, B: BufferRange<T>> MapPersistentWrite<T,B>
where for<'a> &'a B: TypedBuffer<T>
{
pub fn range_mut<R: InputRange>(&mut self, range: R) -> MapPersistentWrite<T, &B> {
MapPersistentWrite {
map: unsafe{ mem::transmute(&mut self.map[range.to_range(&self.buffer.buffer)]) },
buffer: SendBufferDropper {
buffer: &self.buffer.buffer,
thread_id: None,
marker: PhantomData,
}
}
}
}
impl<T: 'static, B: BufferRange<T> + TypedBuffer<T>> MapPersistentWrite<T,B>{
pub fn into_range_mut<R: InputRange>(self, range: R) -> MapPersistentWrite<T, B> {
MapPersistentWrite {
map: &mut self.map[range.to_range(&self.buffer.buffer)],
buffer: self.buffer,
}
}
}
impl<B: BufferRange<u8>> MapPersistentWrite<u8, B>{
pub fn cast<T>(self) -> MapPersistentWrite<T, <B as Cast<T>>::CastTo>
where
B: Cast<T>,
<B as Cast<T>>::CastTo: TypedBuffer<T>,
{
let (buffer, thread_id) = self.buffer.destructure();
let buffer = buffer.cast();
let len = self.map.len() / mem::size_of::<T>();
let map = unsafe{ slice::from_raw_parts_mut(self.map.as_mut_ptr() as *mut T, len) };
MapPersistentWrite{
buffer: SendBufferDropper{
buffer,
thread_id,
marker: PhantomData,
},
map,
}
}
}
#[derive(Debug)]
pub struct MapPersistentReadWrite<T: 'static, B: TypedBuffer<T>> {
map: &'static mut [T],
buffer: SendBufferDropper<T, B>,
}
impl<T: 'static, B: TypedBuffer<T>> MapPersistentReadWrite<T,B>{
pub(super) fn new(map: &'static mut [T], buffer: B) -> MapPersistentReadWrite<T, B>{
MapPersistentReadWrite{
map,
buffer: SendBufferDropper{
buffer,
thread_id: Some(std::thread::current().id()),
marker: PhantomData,
},
}
}
pub fn data(&self) -> &[T]{
self.map
}
pub fn data_mut(&mut self) -> &mut [T]{
self.map
}
pub fn update(&mut self, data: &[T]) {
assert!(data.len() <= self.map.len());
unsafe{ ptr::copy_nonoverlapping(data.as_ptr(), self.map.as_mut_ptr(), data.len()) }
}
}
impl<T: 'static, B: BufferRange<T>> MapPersistentReadWrite<T,B>
where for<'a> &'a B: TypedBuffer<T>
{
pub fn range_mut<R: InputRange>(&mut self, range: R) -> MapPersistentReadWrite<T, &B> {
MapPersistentReadWrite {
map: unsafe{ mem::transmute(&mut self.map[range.to_range(&self.buffer.buffer)]) },
buffer: SendBufferDropper {
buffer: &self.buffer.buffer,
thread_id: None,
marker: PhantomData,
}
}
}
}
impl<T: 'static, B: BufferRange<T> + TypedBuffer<T>> MapPersistentReadWrite<T,B>{
pub fn into_range_mut<R: InputRange>(self, range: R) -> MapPersistentReadWrite<T, B> {
MapPersistentReadWrite {
map: &mut self.map[range.to_range(&self.buffer.buffer)],
buffer: self.buffer,
}
}
}
impl<B: BufferRange<u8>> MapPersistentReadWrite<u8,B>{
pub fn cast<T>(self) -> MapPersistentReadWrite<T, <B as Cast<T>>::CastTo>
where
B: Cast<T>,
<B as Cast<T>>::CastTo: TypedBuffer<T>,
{
let (buffer, thread_id) = self.buffer.destructure();
let buffer = buffer.cast();
let len = self.map.len() / mem::size_of::<T>();
let map = unsafe{ slice::from_raw_parts_mut(self.map.as_mut_ptr() as *mut T, len) };
MapPersistentReadWrite{
buffer: SendBufferDropper{
buffer,
thread_id,
marker: PhantomData,
},
map,
}
}
}
#[derive(Debug)]
pub struct MapRead<'a, T: 'static, B: WithBackend> {
pub(super) map: &'a [T],
pub(super) buffer: &'a B,
}
impl<'a, T:'static, B: WithBackend> Drop for MapRead<'a,T,B>{
fn drop(&mut self){
self.buffer.with_backend(|b| unsafe{ b.unmap() });
}
}
impl<'a, T: 'static, B: WithBackend> MapRead<'a,T,B>{
pub fn data(&self) -> &'a [T]{
self.map
}
}
impl<'a, T: 'static, B: BufferRange<T> + WithBackend> MapRead<'a, T,B>{
pub fn into_range<R: InputRange>(self, range: R) -> MapRead<'a, T, B> {
MapRead {
map: &self.map[range.to_range(self.buffer)],
buffer: self.buffer,
}
}
}
#[derive(Debug)]
pub struct MapWrite<'a, T: 'static, B: WithBackend> {
pub(super) map: &'a mut [T],
pub(super) dropper: MapDropper<'a, B>,
}
#[derive(Debug)]
pub(super) struct MapDropper<'a, B: WithBackend>{
pub(super) buffer: &'a B,
}
impl<'a, B: WithBackend> Drop for MapDropper<'a,B>{
fn drop(&mut self){
self.buffer.with_backend(|b| unsafe{ b.unmap() });
}
}
impl<'a, T: 'static, B: WithBackend> MapWrite<'a, T,B>{
pub fn update(&mut self, data: &[T]) {
assert!(data.len() <= self.map.len());
unsafe{ ptr::copy_nonoverlapping(data.as_ptr(), self.map.as_mut_ptr(), data.len()) }
}
pub unsafe fn data_mut(&mut self) -> &mut [T]{
self.map
}
}
impl<'a, T: 'static, B: BufferRange<T> + WithBackend> MapWrite<'a, T, B>{
pub fn into_range_mut<R: InputRange>(self, range: R) -> MapWrite<'a, T, B> {
MapWrite {
map: &mut self.map[range.to_range(self.dropper.buffer)],
dropper: self.dropper,
}
}
}
#[derive(Debug)]
pub struct MapReadWrite<'a, T: 'static, B: WithBackend> {
pub(super) map: &'a mut [T],
pub(super) dropper: MapDropper<'a, B>,
}
impl<'a, T: 'static, B: WithBackend> MapReadWrite<'a, T, B>{
pub fn data(&self) -> &[T]{
self.map
}
pub fn data_mut(&mut self) -> &mut [T]{
self.map
}
pub fn update(&mut self, data: &[T]) {
assert!(data.len() <= self.map.len());
unsafe{ ptr::copy_nonoverlapping(data.as_ptr(), self.map.as_mut_ptr(), data.len()) }
}
}