use draw_state::target;
use super::{attrib, shade, tex, Resources};
type Offset = u32;
type Size = u32;
#[derive(Clone, Copy, PartialEq, Debug)]
pub struct DataPointer(Offset, Size);
pub struct DataBuffer {
buf: Vec<u8>,
}
impl DataBuffer {
pub fn new() -> DataBuffer {
DataBuffer {
buf: Vec::new(),
}
}
pub fn clear(&mut self) {
unsafe { self.buf.set_len(0); }
}
#[cfg(unstable)]
#[inline(always)]
pub fn add_struct<T: Copy>(&mut self, v: &T) -> DataPointer {
use std::slice::ref_slice;
self.add_vec(ref_slice(v))
}
#[cfg(not(unstable))]
pub fn add_struct<T: Copy>(&mut self, v: &T) -> DataPointer {
use std::{intrinsics, mem};
let offset = self.buf.len();
let size = mem::size_of::<T>();
self.buf.reserve(size);
unsafe {
self.buf.set_len(offset + size);
intrinsics::copy((v as *const T) as *const u8,
&mut self.buf[offset] as *mut u8,
size);
};
DataPointer(offset as Offset, size as Size)
}
pub fn add_vec<T: Copy>(&mut self, v: &[T]) -> DataPointer {
use std::{intrinsics, mem};
let offset = self.buf.len();
let size = mem::size_of::<T>() * v.len();
self.buf.reserve(size);
unsafe {
self.buf.set_len(offset + size);
intrinsics::copy(v.as_ptr() as *const u8,
&mut self.buf[offset] as *mut u8,
size);
}
DataPointer(offset as Offset, size as Size)
}
pub fn get_ref(&self, data: DataPointer) -> &[u8] {
let DataPointer(offset, size) = data;
&self.buf[offset as usize ..offset as usize + size as usize]
}
}
pub type InstanceOption = Option<(super::InstanceCount, super::VertexCount)>;
#[allow(missing_docs)]
pub trait CommandBuffer<R: Resources> {
fn new() -> Self;
fn clear(&mut self);
fn bind_program(&mut self, R::Program);
fn bind_array_buffer(&mut self, R::ArrayBuffer);
fn bind_attribute(&mut self, super::AttributeSlot, R::Buffer, attrib::Format);
fn bind_index(&mut self, R::Buffer);
fn bind_frame_buffer(&mut self, Access, R::FrameBuffer, Gamma);
fn unbind_target(&mut self, Access, Target);
fn bind_target_surface(&mut self, Access, Target, R::Surface);
fn bind_target_texture(&mut self, Access, Target, R::Texture,
target::Level, Option<target::Layer>);
fn bind_uniform_block(&mut self, R::Program,
super::UniformBufferSlot, super::UniformBlockIndex,
R::Buffer);
fn bind_uniform(&mut self, shade::Location, shade::UniformValue);
fn bind_texture(&mut self, super::TextureSlot, tex::TextureKind,
R::Texture, Option<(R::Sampler, tex::SamplerInfo)>);
fn set_draw_color_buffers(&mut self, usize);
fn set_primitive(&mut self, ::state::Primitive);
fn set_viewport(&mut self, target::Rect);
fn set_multi_sample(&mut self, Option<::state::MultiSample>);
fn set_scissor(&mut self, Option<target::Rect>);
fn set_depth_stencil(&mut self, Option<::state::Depth>,
Option<::state::Stencil>, ::state::CullFace);
fn set_blend(&mut self, Option<::state::Blend>);
fn set_color_mask(&mut self, ::state::ColorMask);
fn update_buffer(&mut self, R::Buffer, DataPointer, usize);
fn update_texture(&mut self, tex::TextureKind, R::Texture,
tex::ImageInfo, DataPointer);
fn call_clear(&mut self, target::ClearData, target::Mask);
fn call_draw(&mut self, super::PrimitiveType, super::VertexCount,
super::VertexCount, InstanceOption);
fn call_draw_indexed(&mut self, super::PrimitiveType, super::IndexType,
super::VertexCount, super::VertexCount,
super::VertexCount, InstanceOption);
fn call_blit(&mut self, target::Rect, target::Rect, target::Mirror, target::Mask);
}
#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Access {
Draw,
Read,
}
#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Gamma {
Original,
Convert,
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Target {
Color(u8),
Depth,
Stencil,
DepthStencil,
}
#[cfg(test)]
mod tests {
#[test]
fn test_data_buffer() {
let mut buf = super::DataBuffer::new();
assert_eq!(buf.add_struct(&(0u8, false)), super::DataPointer(0, 2));
assert_eq!(buf.add_vec(&[5i32, 6i32]), super::DataPointer(2, 8));
}
}