use super::*;
use super::errors::*;
use raw::*;
#[derive(Debug)]
pub struct Texture1D {
id: TextureId,
size: Texture1DSize,
internal_format: TextureInternalFormat,
format: TextureFormat,
data_type: TextureDataType,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Texture1DSize(pub usize);
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct Texture1DParameters {
pub min: TextureTexelFilter,
pub mag: TextureTexelFilter,
pub mipmap: TextureMipmapFilter,
pub wrap_s: TextureWrapMode,
}
impl Texture for Texture1D {
fn get_id(&self) -> TextureId {
self.id
}
fn get_target(&self) -> TextureTarget {
TextureTarget::Texture1D
}
}
impl Texture1D {
pub fn new<T: TextureDataPrimitive, M: Into<MipmapLevel>>(
size: Texture1DSize,
internal_format: TextureInternalFormat,
format: TextureFormat,
data_type: TextureDataType,
parameters: Texture1DParameters,
levels: M,
data: &[T],
) -> Result<Texture1D> {
if size.0 == 0 {
bail!("Texture size must be greater than 0");
}
let mut texture = Texture1D::new_empty(size, internal_format, format, data_type, parameters, levels)
.chain_err(|| "Could not create texture")?;
texture
.set_data(data)
.chain_err(|| "Could not set texture data")?;
Ok(texture)
}
pub fn new_empty<M: Into<MipmapLevel>>(
size: Texture1DSize,
internal_format: TextureInternalFormat,
format: TextureFormat,
data_type: TextureDataType,
parameters: Texture1DParameters,
levels: M,
) -> Result<Texture1D> {
if size.0 == 0 {
bail!("Texture size must be greater than 0");
}
let levels = levels.into().num_levels_1d(size);
unsafe {
let id = create_texture(TextureTarget::Texture1D);
let mut texture = Texture1D {
id: id,
size: size,
internal_format: internal_format,
format: format,
data_type: data_type,
};
texture_storage_1d(id, levels, internal_format, size.0)
.chain_err(|| "Unable to allocate memory for texture")?;
texture
.set_parameters(parameters)
.chain_err(|| "Unable to set texture parameters")?;
Ok(texture)
}
}
pub fn set_data<T: TextureDataPrimitive>(&mut self, data: &[T]) -> Result<()> {
if self.size.0 * self.format.n_components() != data.len() {
bail!("Data length does not match texture size");
}
unsafe {
texture_subimage_1d(
self.id,
0,
0,
self.size.0,
self.format.into(),
self.data_type.into(),
data,
).chain_err(|| "Could not set texture data")?;
}
Ok(())
}
pub fn set_subdata<T: TextureDataPrimitive>(
&mut self,
size: Texture1DSize,
offset: Texture1DSize,
data: &[T],
) -> Result<()> {
if size.0 * self.format.n_components() != data.len() {
bail!("Data length does not match proclaimed size");
}
if size.0 + offset.0 >= self.size.0 {
bail!("Size + offset is outside texture bounds");
}
unsafe {
texture_subimage_1d(
self.id,
0,
offset.0,
size.0,
self.format.into(),
self.data_type.into(),
data,
).chain_err(|| "Could not set texture data")?;
}
Ok(())
}
pub fn set_data_mipmap<T: TextureDataPrimitive>(&mut self, level: usize, data: &[T]) -> Result<()> {
if discrete_floored_log2(self.size.0) < level {
bail!("Mipmap level references greater level than texture has");
}
if texture_size_mipmap(self.size.0, level) * self.format.n_components() != data.len() {
bail!("Data length does not match texture size");
}
unsafe {
texture_subimage_1d(
self.id,
level,
0,
self.size.0,
self.format.into(),
self.data_type.into(),
data,
).chain_err(|| "Could not set texture data")?;
}
Ok(())
}
pub fn set_subdata_mipmap<T: TextureDataPrimitive>(
&mut self,
level: usize,
size: Texture1DSize,
offset: Texture1DSize,
data: &[T],
) -> Result<()> {
if discrete_floored_log2(self.size.0) < level {
bail!("Mipmap level references greater level than texture has");
}
if texture_size_mipmap(size.0, level) * self.format.n_components() != data.len() {
bail!("Data length does not match proclaimed size");
}
if size.0 + offset.0 >= texture_size_mipmap(self.size.0, level) {
bail!("Size + offset is outside texture bounds");
}
unsafe {
texture_subimage_1d(
self.id,
level,
offset.0,
size.0,
self.format.into(),
self.data_type.into(),
data,
).chain_err(|| "Could not set texture data")?;
}
Ok(())
}
pub fn generate_mipmap(&mut self) {
unsafe {
generate_texture_mipmap(self.id).unwrap();
}
}
fn set_parameters(&mut self, parameters: Texture1DParameters) -> Result<()> {
let min = TextureParameterOption::MinFilter(parameters.min, parameters.mipmap);
let mag = TextureParameterOption::MagFilter(parameters.mag);
let wrap_s = TextureParameterOption::WrapS(parameters.wrap_s);
unsafe {
texture_parameter_i(self.id, min).chain_err(|| "Could not set min parameter")?;
texture_parameter_i(self.id, mag).chain_err(|| "Could not set mag parameter")?;
texture_parameter_i(self.id, wrap_s).chain_err(|| "Could not set wrap s parameter")?;
}
Ok(())
}
}
impl Drop for Texture1D {
fn drop(&mut self) {
unsafe { delete_texture(self.id) };
}
}