use std::error::Error;
use std::fmt;
use std::ops::{Deref, DerefMut};
use utils::range::RangeArgument;
use buffer::{Buffer, BufferSlice, BufferMutSlice, BufferAny, BufferType, BufferMode, BufferCreationError, Content};
use vertex::{Vertex, VerticesSource, PerInstance};
use vertex::format::VertexFormat;
use gl;
use GlObject;
use backend::Facade;
use version::{Api, Version};
use CapabilitiesSource;
#[derive(Copy, Clone, Debug)]
pub enum CreationError {
FormatNotSupported,
BufferCreationError(BufferCreationError),
}
impl From<BufferCreationError> for CreationError {
#[inline]
fn from(err: BufferCreationError) -> CreationError {
CreationError::BufferCreationError(err)
}
}
impl fmt::Display for CreationError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use self::CreationError::*;
let desc = match self {
FormatNotSupported => "The vertex format is not supported by the backend",
BufferCreationError(_) => "Error while creating the vertex buffer",
};
fmt.write_str(desc)
}
}
impl Error for CreationError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
use self::CreationError::*;
match *self {
BufferCreationError(ref error) => Some(error),
FormatNotSupported => None,
}
}
}
impl<T: Copy> GlObject for VertexBuffer<T> {
type Id = gl::types::GLuint;
#[inline]
fn get_id(&self) -> gl::types::GLuint {
self.buffer.get_id()
}
}
#[derive(Debug)]
pub struct VertexBuffer<T> where T: Copy {
buffer: Buffer<[T]>,
bindings: VertexFormat,
}
pub struct VertexBufferSlice<'b, T: 'b> where T: Copy {
buffer: BufferSlice<'b, [T]>,
bindings: &'b VertexFormat,
}
impl<'b, T: 'b> VertexBufferSlice<'b, T> where T: Copy + Content {
#[inline]
pub fn per_instance(&'b self) -> Result<PerInstance, InstancingNotSupported> {
if !(self.get_context().get_version() >= &Version(Api::Gl, 3, 3)) &&
!self.get_context().get_extensions().gl_arb_instanced_arrays
{
return Err(InstancingNotSupported);
}
Ok(PerInstance(self.buffer.as_slice_any(), &self.bindings))
}
}
impl<T> VertexBuffer<T> where T: Vertex {
#[inline]
pub fn new<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::new_impl(facade, data, BufferMode::Default)
}
#[inline]
pub fn dynamic<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::new_impl(facade, data, BufferMode::Dynamic)
}
#[inline]
pub fn persistent<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::new_impl(facade, data, BufferMode::Persistent)
}
#[inline]
pub fn immutable<F: ?Sized>(facade: &F, data: &[T]) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::new_impl(facade, data, BufferMode::Immutable)
}
#[inline]
fn new_impl<F: ?Sized>(facade: &F, data: &[T], mode: BufferMode)
-> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
if !T::is_supported(facade) {
return Err(CreationError::FormatNotSupported);
}
let buffer = Buffer::new(facade, data, BufferType::ArrayBuffer, mode)?;
Ok(buffer.into())
}
#[inline]
pub fn empty<F: ?Sized>(facade: &F, elements: usize) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::empty_impl(facade, elements, BufferMode::Default)
}
#[inline]
pub fn empty_dynamic<F: ?Sized>(facade: &F, elements: usize) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::empty_impl(facade, elements, BufferMode::Dynamic)
}
#[inline]
pub fn empty_persistent<F: ?Sized>(facade: &F, elements: usize)
-> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::empty_impl(facade, elements, BufferMode::Persistent)
}
#[inline]
pub fn empty_immutable<F: ?Sized>(facade: &F, elements: usize) -> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
VertexBuffer::empty_impl(facade, elements, BufferMode::Immutable)
}
#[inline]
fn empty_impl<F: ?Sized>(facade: &F, elements: usize, mode: BufferMode)
-> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
if !T::is_supported(facade) {
return Err(CreationError::FormatNotSupported);
}
let buffer = Buffer::empty_array(facade, BufferType::ArrayBuffer, elements, mode)?;
Ok(buffer.into())
}
}
impl<T> VertexBuffer<T> where T: Copy {
#[inline]
pub unsafe fn new_raw<F: ?Sized>(facade: &F, data: &[T],
bindings: VertexFormat, elements_size: usize)
-> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
Ok(VertexBuffer {
buffer: Buffer::new(facade, data, BufferType::ArrayBuffer,
BufferMode::Default)?,
bindings: bindings,
})
}
#[inline]
pub unsafe fn new_raw_dynamic<F: ?Sized>(facade: &F, data: &[T],
bindings: VertexFormat, elements_size: usize)
-> Result<VertexBuffer<T>, CreationError>
where F: Facade
{
Ok(VertexBuffer {
buffer: Buffer::new(facade, data, BufferType::ArrayBuffer,
BufferMode::Dynamic)?,
bindings: bindings,
})
}
#[inline]
pub fn slice<R: RangeArgument<usize>>(&self, range: R) -> Option<VertexBufferSlice<T>> {
let slice = match self.buffer.slice(range) {
None => return None,
Some(s) => s
};
Some(VertexBufferSlice {
buffer: slice,
bindings: &self.bindings,
})
}
#[inline]
pub fn get_bindings(&self) -> &VertexFormat {
&self.bindings
}
#[inline]
pub fn per_instance(&self) -> Result<PerInstance, InstancingNotSupported> {
if !(self.buffer.get_context().get_version() >= &Version(Api::Gl, 3, 3)) &&
!self.buffer.get_context().get_extensions().gl_arb_instanced_arrays
{
return Err(InstancingNotSupported);
}
Ok(PerInstance(self.buffer.as_slice_any(), &self.bindings))
}
}
impl<T> VertexBuffer<T> where T: Copy + Send + 'static {
#[inline]
#[deprecated(note = "use .into() instead.")]
pub fn into_vertex_buffer_any(self) -> VertexBufferAny {
self.into_vertex_buffer_any_inner()
}
#[inline]
fn into_vertex_buffer_any_inner(self) -> VertexBufferAny {
VertexBufferAny {
buffer: self.buffer.into(),
bindings: self.bindings,
}
}
}
impl<T> From<Buffer<[T]>> for VertexBuffer<T> where T: Vertex + Copy {
#[inline]
fn from(buffer: Buffer<[T]>) -> VertexBuffer<T> {
assert!(T::is_supported(buffer.get_context()));
let bindings = <T as Vertex>::build_bindings();
VertexBuffer {
buffer: buffer,
bindings: bindings,
}
}
}
impl<T> Deref for VertexBuffer<T> where T: Copy {
type Target = Buffer<[T]>;
#[inline]
fn deref(&self) -> &Buffer<[T]> {
&self.buffer
}
}
impl<T> DerefMut for VertexBuffer<T> where T: Copy {
#[inline]
fn deref_mut(&mut self) -> &mut Buffer<[T]> {
&mut self.buffer
}
}
impl<'a, T> From<&'a VertexBuffer<T>> for BufferSlice<'a, [T]> where T: Copy {
#[inline]
fn from(b: &'a VertexBuffer<T>) -> BufferSlice<'a, [T]> {
let b: &Buffer<[T]> = &*b;
b.as_slice()
}
}
impl<'a, T> From<&'a mut VertexBuffer<T>> for BufferMutSlice<'a, [T]> where T: Copy {
#[inline]
fn from(b: &'a mut VertexBuffer<T>) -> BufferMutSlice<'a, [T]> {
let b: &mut Buffer<[T]> = &mut *b;
b.as_mut_slice()
}
}
impl<'a, T> Into<VerticesSource<'a>> for &'a VertexBuffer<T> where T: Copy {
#[inline]
fn into(self) -> VerticesSource<'a> {
VerticesSource::VertexBuffer(self.buffer.as_slice_any(), &self.bindings, false)
}
}
impl<'a, T> Deref for VertexBufferSlice<'a, T> where T: Copy {
type Target = BufferSlice<'a, [T]>;
#[inline]
fn deref(&self) -> &BufferSlice<'a, [T]> {
&self.buffer
}
}
impl<'a, T> DerefMut for VertexBufferSlice<'a, T> where T: Copy {
#[inline]
fn deref_mut(&mut self) -> &mut BufferSlice<'a, [T]> {
&mut self.buffer
}
}
impl<'a, T> From<VertexBufferSlice<'a, T>> for BufferSlice<'a, [T]> where T: Copy {
#[inline]
fn from(b: VertexBufferSlice<'a, T>) -> BufferSlice<'a, [T]> {
b.buffer
}
}
impl<'a, T> Into<VerticesSource<'a>> for VertexBufferSlice<'a, T> where T: Copy {
#[inline]
fn into(self) -> VerticesSource<'a> {
VerticesSource::VertexBuffer(self.buffer.as_slice_any(), &self.bindings, false)
}
}
#[derive(Debug)]
pub struct VertexBufferAny {
buffer: BufferAny,
bindings: VertexFormat,
}
impl VertexBufferAny {
#[inline]
pub fn get_elements_size(&self) -> usize {
self.buffer.get_elements_size()
}
#[inline]
pub fn len(&self) -> usize {
self.buffer.get_elements_count()
}
#[inline]
pub fn get_bindings(&self) -> &VertexFormat {
&self.bindings
}
#[inline]
pub unsafe fn into_vertex_buffer<T: Copy>(self) -> VertexBuffer<T> {
unimplemented!();
}
#[inline]
pub fn per_instance(&self) -> Result<PerInstance, InstancingNotSupported> {
if !(self.buffer.get_context().get_version() >= &Version(Api::Gl, 3, 3)) &&
!self.buffer.get_context().get_extensions().gl_arb_instanced_arrays
{
return Err(InstancingNotSupported);
}
Ok(PerInstance(self.buffer.as_slice_any(), &self.bindings))
}
}
impl<T> From<VertexBuffer<T>> for VertexBufferAny where T: Copy + Send + 'static {
#[inline]
fn from(buf: VertexBuffer<T>) -> VertexBufferAny {
buf.into_vertex_buffer_any_inner()
}
}
impl<T> From<Buffer<[T]>> for VertexBufferAny where T: Vertex + Copy + Send + 'static {
#[inline]
fn from(buf: Buffer<[T]>) -> VertexBufferAny {
let buf: VertexBuffer<T> = buf.into();
buf.into_vertex_buffer_any_inner()
}
}
impl Deref for VertexBufferAny {
type Target = BufferAny;
#[inline]
fn deref(&self) -> &BufferAny {
&self.buffer
}
}
impl DerefMut for VertexBufferAny {
#[inline]
fn deref_mut(&mut self) -> &mut BufferAny {
&mut self.buffer
}
}
impl<'a> Into<VerticesSource<'a>> for &'a VertexBufferAny {
#[inline]
fn into(self) -> VerticesSource<'a> {
VerticesSource::VertexBuffer(self.buffer.as_slice_any(), &self.bindings, false)
}
}
#[derive(Debug, Copy, Clone)]
pub struct InstancingNotSupported;