mallumo-gls 0.43.0

Small low level library for modern (4.5 Core) OpenGL
Documentation
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");
        }
        // the pow may panic but because it passed the test above, it should not
        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) };
    }
}