#![allow(unreachable_code)]
use std::borrow::Cow;
use std::convert::From;
use {gl, framebuffer};
#[cfg(feature = "image")]
use image;
use backend::Facade;
use pixel_buffer::PixelBuffer;
use uniforms::{UniformValue, AsUniformValue, UniformType, Sampler};
use {Surface, GlObject};
use FboAttachments;
use fbo::ValidatedAttachments;
use Rect;
use BlitTarget;
use uniforms;
use image_format::{TextureFormatRequest, FormatNotSupportedError};
pub use image_format::{ClientFormat, TextureFormat};
pub use image_format::{UncompressedFloatFormat, UncompressedIntFormat, UncompressedUintFormat};
pub use image_format::{CompressedFormat, DepthFormat, DepthStencilFormat, StencilFormat};
pub use image_format::{CompressedSrgbFormat, SrgbFormat};
pub use self::any::{TextureAny, TextureAnyMipmap, TextureType};
pub use self::get_format::{InternalFormat, InternalFormatType};
pub use self::pixel::PixelValue;
mod any;
mod get_format;
mod pixel;
include!(concat!(env!("OUT_DIR"), "/textures.rs"));
pub trait Texture {
fn get_width(&self) -> u32;
fn get_height(&self) -> Option<u32>;
fn get_depth(&self) -> Option<u32>;
fn get_array_size(&self) -> Option<u32>;
}
pub trait Texture1dDataSource<'a> {
type Data: Send + Copy + Clone + 'a;
fn into_raw(self) -> RawImage1d<'a, Self::Data>;
}
pub trait Texture1dDataSink<T> {
fn from_raw(data: Cow<[T]>, width: u32) -> Self;
}
pub struct RawImage1d<'a, T: Clone + 'a> {
pub data: Cow<'a, [T]>,
pub width: u32,
pub format: ClientFormat,
}
impl<'a, P: PixelValue> Texture1dDataSource<'a> for Vec<P> where P: Copy + Clone + Send + 'static {
type Data = P;
fn into_raw(self) -> RawImage1d<'a, P> {
let width = self.len() as u32;
RawImage1d {
data: Cow::Owned(self),
width: width,
format: <P as PixelValue>::get_format(),
}
}
}
impl<'a, P: PixelValue + Clone> Texture1dDataSource<'a> for RawImage1d<'a, P> {
type Data = P;
fn into_raw(self) -> RawImage1d<'a, P> {
self
}
}
impl<P> Texture1dDataSink<P> for Vec<P> where P: Copy + Clone + Send {
fn from_raw(data: Cow<[P]>, _width: u32) -> Self {
data.into_owned()
}
}
impl<'a, P: PixelValue> Texture1dDataSource<'a> for &'a[P] where P: Copy + Clone + Send + 'static {
type Data = P;
fn into_raw(self) -> RawImage1d<'a, P> {
let width = self.len();
RawImage1d {
data: Cow::Borrowed(self),
width: width as u32,
format: <P as PixelValue>::get_format(),
}
}
}
pub trait Texture2dDataSource<'a> {
type Data: Send + Copy + Clone + 'a;
fn into_raw(self) -> RawImage2d<'a, Self::Data>;
}
pub trait Texture2dDataSink<T> {
fn from_raw(data: Cow<[T]>, width: u32, height: u32) -> Self;
}
pub struct RawImage2d<'a, T: Clone + 'a> {
pub data: Cow<'a, [T]>,
pub width: u32,
pub height: u32,
pub format: ClientFormat,
}
impl<'a, T: Clone + 'a> RawImage2d<'a, T> {
pub fn from_vec_raw1d(arr: &Vec<RawImage1d<'a, T>>) -> RawImage2d<'a, T> {
let width = arr[0].width;
let height = arr.len() as u32;
let format = arr[0].format;
let raw_data = {
let mut vec = Vec::<T>::with_capacity((width * height) as usize);
for i in arr {
if width != i.width {
panic!("Varying dimensions were found.");
} else if format != i.format {
panic!("Varying formats were found.");
}
for j in i.data.iter() {
vec.push(j.clone());
}
}
vec
};
RawImage2d {
data: Cow::Owned(raw_data),
width: width,
height: height,
format: format,
}
}
}
impl<'a, P: PixelValue + Clone> Texture2dDataSource<'a> for Vec<Vec<P>> {
type Data = P;
fn into_raw(self) -> RawImage2d<'a, P> {
let width = self.iter().next().map(|e| e.len()).unwrap_or(0) as u32;
let height = self.len() as u32;
RawImage2d {
data: Cow::Owned(self.into_iter().flat_map(|e| e.into_iter()).collect()),
width: width,
height: height,
format: <P as PixelValue>::get_format(),
}
}
}
impl<'a, P: PixelValue + Clone> Texture2dDataSource<'a> for RawImage2d<'a, P> {
type Data = P;
fn into_raw(self) -> RawImage2d<'a, P> {
self
}
}
impl<P> Texture2dDataSink<P> for Vec<Vec<P>> where P: Copy + Clone {
fn from_raw(data: Cow<[P]>, width: u32, height: u32) -> Self {
data.chunks(width as usize).map(|e| e.to_vec()).collect()
}
}
#[cfg(feature = "image")]
impl<'a, T, P> Texture2dDataSource<'a> for image::ImageBuffer<P, Vec<T>>
where T: image::Primitive + Send + 'static,
P: PixelValue + image::Pixel<Subpixel = T> + Clone + Copy
{
type Data = T;
fn into_raw(self) -> RawImage2d<'a, T> {
use image::GenericImage;
let (width, height) = self.dimensions();
let data = self.into_raw()
.chunks(width as usize * <P as image::Pixel>::channel_count() as usize)
.rev()
.flat_map(|row| row.iter())
.map(|p| p.clone())
.collect();
RawImage2d {
data: data,
width: width,
height: height,
format: <P as PixelValue>::get_format(),
}
}
}
#[cfg(feature = "image")]
impl<T, P> Texture2dDataSink<P> for image::ImageBuffer<P, Vec<T>>
where T: image::Primitive + Send + 'static,
P: PixelValue + image::Pixel<Subpixel = T> + Clone + Copy
{
fn from_raw(data: Cow<[P]>, width: u32, height: u32) -> Self {
let data = data
.chunks(width as usize)
.rev()
.flat_map(|row| row.iter())
.flat_map(|pixel| pixel.channels().iter())
.cloned()
.collect();
image::ImageBuffer::from_raw(width, height, data).unwrap()
}
}
#[cfg(feature = "image")]
impl<'a> Texture2dDataSource<'a> for image::DynamicImage {
type Data = u8;
fn into_raw(self) -> RawImage2d<'a, u8> {
Texture2dDataSource::into_raw(self.to_rgba())
}
}
#[cfg(feature = "image")]
impl Texture2dDataSink<(u8, u8, u8, u8)> for image::DynamicImage {
fn from_raw(data: Cow<[(u8, u8, u8, u8)]>, w: u32, h: u32) -> image::DynamicImage {
let data = unsafe { ::std::mem::transmute(data) }; image::DynamicImage::ImageRgba8(Texture2dDataSink::from_raw(data, w, h))
}
}
pub trait Texture3dDataSource<'a> {
type Data: Send + Copy + Clone + 'a;
fn into_raw(self) -> RawImage3d<'a, Self::Data>;
}
pub trait Texture3dDataSink<T> {
fn from_raw(data: Cow<[T]>, width: u32, height: u32, depth: u32) -> Self;
}
pub struct RawImage3d<'a, T: Clone + 'a> {
pub data: Cow<'a, [T]>,
pub width: u32,
pub height: u32,
pub depth: u32,
pub format: ClientFormat,
}
impl<'a, T: Clone + 'a> RawImage3d<'a, T> {
pub fn from_vec_raw2d(arr: &Vec<RawImage2d<'a, T>>) -> RawImage3d<'a, T> {
let depth = arr.len() as u32;
let width = arr[0].width;
let height = arr[0].height;
let format = arr[0].format;
let raw_data = {
let mut vec = Vec::<T>::with_capacity((width * height * depth) as usize);
for i in arr {
if width != i.width || height != i.height {
panic!("Varying dimensions were found.");
} else if format != i.format {
panic!("Varying formats were found.");
}
for j in i.data.iter() {
vec.push(j.clone());
}
}
vec
};
RawImage3d {
data: Cow::Owned(raw_data),
width: width,
height: height,
depth: depth,
format: format,
}
}
}
impl<'a, P: PixelValue + Clone> Texture3dDataSource<'a> for Vec<Vec<Vec<P>>> {
type Data = P;
fn into_raw(self) -> RawImage3d<'a, P> {
let width = self.iter().next().and_then(|e| e.iter().next()).map(|e| e.len()).unwrap_or(0)
as u32;
let height = self.iter().next().map(|e| e.len()).unwrap_or(0) as u32;
let depth = self.len() as u32;
RawImage3d {
data: self.into_iter().flat_map(|e| e.into_iter()).flat_map(|e| e.into_iter())
.collect(),
width: width,
height: height,
depth: depth,
format: <P as PixelValue>::get_format(),
}
}
}
impl<'a, P: PixelValue + Clone> Texture3dDataSource<'a> for RawImage3d<'a, P> {
type Data = P;
fn into_raw(self) -> RawImage3d<'a, P> {
self
}
}
impl<P> Texture3dDataSink<P> for Vec<Vec<Vec<P>>> where P: Copy + Clone {
fn from_raw(_data: Cow<[P]>, _width: u32, _height: u32, _depth: u32) -> Self {
unimplemented!()
}
}
pub struct TextureSurface<'a>(framebuffer::SimpleFrameBuffer<'a>);
impl<'a> Surface for TextureSurface<'a> {
fn clear(&mut self, rect: Option<&Rect>, color: Option<(f32, f32, f32, f32)>,
depth: Option<f32>, stencil: Option<i32>)
{
self.0.clear(rect, color, depth, stencil)
}
fn get_dimensions(&self) -> (u32, u32) {
self.0.get_dimensions()
}
fn get_depth_buffer_bits(&self) -> Option<u16> {
self.0.get_depth_buffer_bits()
}
fn get_stencil_buffer_bits(&self) -> Option<u16> {
self.0.get_stencil_buffer_bits()
}
fn draw<'b, 'v, V, I, U>(&mut self, vb: V, ib: I, program: &::Program,
uniforms: &U, draw_parameters: &::DrawParameters) -> Result<(), ::DrawError>
where I: Into<::index::IndicesSource<'b>>,
U: ::uniforms::Uniforms, V: ::vertex::MultiVerticesSource<'v>
{
self.0.draw(vb, ib, program, uniforms, draw_parameters)
}
fn blit_color<S>(&self, source_rect: &Rect, target: &S, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter) where S: Surface
{
target.blit_from_simple_framebuffer(&self.0, source_rect, target_rect, filter)
}
fn blit_from_frame(&self, source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
self.0.blit_from_frame(source_rect, target_rect, filter)
}
fn blit_from_simple_framebuffer(&self, source: &framebuffer::SimpleFrameBuffer,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
self.0.blit_from_simple_framebuffer(source, source_rect, target_rect, filter)
}
fn blit_from_multioutput_framebuffer(&self, source: &framebuffer::MultiOutputFrameBuffer,
source_rect: &Rect, target_rect: &BlitTarget,
filter: uniforms::MagnifySamplerFilter)
{
self.0.blit_from_multioutput_framebuffer(source, source_rect, target_rect, filter)
}
}
impl<'a> FboAttachments for TextureSurface<'a> {
fn get_attachments(&self) -> Option<&ValidatedAttachments> {
self.0.get_attachments()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextureCreationError {
UnsupportedFormat,
DimensionsNotSupported,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextureMaybeSupportedCreationError {
CreationError(TextureCreationError),
NotSupported,
}
impl From<FormatNotSupportedError> for TextureMaybeSupportedCreationError {
fn from(_: FormatNotSupportedError) -> TextureMaybeSupportedCreationError {
TextureMaybeSupportedCreationError::NotSupported
}
}