2019-01-30 12:11:34 +00:00
|
|
|
// Standard
|
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
// Library
|
2019-04-29 20:37:19 +00:00
|
|
|
use gfx::{self, traits::Factory};
|
|
|
|
use image::{DynamicImage, GenericImageView};
|
2019-02-28 00:37:47 +00:00
|
|
|
use vek::Vec2;
|
2019-01-30 12:11:34 +00:00
|
|
|
|
|
|
|
// Local
|
2019-04-29 20:37:19 +00:00
|
|
|
use super::{gfx_backend, Pipeline, RenderError};
|
2019-01-30 12:11:34 +00:00
|
|
|
|
|
|
|
type ShaderFormat = (gfx::format::R8_G8_B8_A8, gfx::format::Srgb);
|
|
|
|
|
|
|
|
/// Represents an image that has been uploaded to the GPU.
|
|
|
|
pub struct Texture<P: Pipeline> {
|
2019-04-29 20:37:19 +00:00
|
|
|
pub tex: gfx::handle::Texture<
|
|
|
|
gfx_backend::Resources,
|
|
|
|
<ShaderFormat as gfx::format::Formatted>::Surface,
|
|
|
|
>,
|
|
|
|
pub srv: gfx::handle::ShaderResourceView<
|
|
|
|
gfx_backend::Resources,
|
|
|
|
<ShaderFormat as gfx::format::Formatted>::View,
|
|
|
|
>,
|
2019-01-30 12:11:34 +00:00
|
|
|
pub sampler: gfx::handle::Sampler<gfx_backend::Resources>,
|
|
|
|
_phantom: PhantomData<P>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<P: Pipeline> Texture<P> {
|
|
|
|
pub fn new(
|
|
|
|
factory: &mut gfx_backend::Factory,
|
|
|
|
image: &DynamicImage,
|
|
|
|
) -> Result<Self, RenderError> {
|
2019-04-29 20:37:19 +00:00
|
|
|
let (tex, srv) = factory
|
|
|
|
.create_texture_immutable_u8::<ShaderFormat>(
|
|
|
|
gfx::texture::Kind::D2(
|
|
|
|
image.width() as u16,
|
|
|
|
image.height() as u16,
|
|
|
|
gfx::texture::AaMode::Single,
|
|
|
|
),
|
|
|
|
gfx::texture::Mipmap::Provided,
|
|
|
|
&[&image.to_rgba().into_raw()],
|
|
|
|
)
|
2019-01-30 12:11:34 +00:00
|
|
|
.map_err(|err| RenderError::CombinedError(err))?;
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
tex,
|
|
|
|
srv,
|
|
|
|
sampler: factory.create_sampler(gfx::texture::SamplerInfo::new(
|
|
|
|
gfx::texture::FilterMethod::Scale,
|
|
|
|
gfx::texture::WrapMode::Clamp,
|
|
|
|
)),
|
|
|
|
_phantom: PhantomData,
|
|
|
|
})
|
|
|
|
}
|
2019-02-23 02:41:52 +00:00
|
|
|
pub fn new_dynamic(
|
|
|
|
factory: &mut gfx_backend::Factory,
|
|
|
|
width: u16,
|
|
|
|
height: u16,
|
|
|
|
) -> Result<Self, RenderError> {
|
|
|
|
let tex = factory.create_texture(
|
|
|
|
gfx::texture::Kind::D2(
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
gfx::texture::AaMode::Single,
|
|
|
|
),
|
|
|
|
1 as gfx::texture::Level,
|
|
|
|
gfx::memory::Bind::SHADER_RESOURCE,
|
|
|
|
gfx::memory::Usage::Dynamic,
|
|
|
|
Some(<<ShaderFormat as gfx::format::Formatted>::Channel as gfx::format::ChannelTyped>::get_channel_type()),
|
|
|
|
)
|
|
|
|
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Texture(err)))?;
|
|
|
|
|
2019-04-29 20:37:19 +00:00
|
|
|
let srv = factory
|
|
|
|
.view_texture_as_shader_resource::<ShaderFormat>(
|
|
|
|
&tex,
|
|
|
|
(0, 0),
|
|
|
|
gfx::format::Swizzle::new(),
|
|
|
|
)
|
2019-02-23 02:41:52 +00:00
|
|
|
.map_err(|err| RenderError::CombinedError(gfx::CombinedError::Resource(err)))?;
|
|
|
|
|
|
|
|
Ok(Self {
|
|
|
|
tex,
|
|
|
|
srv,
|
|
|
|
sampler: factory.create_sampler(gfx::texture::SamplerInfo::new(
|
2019-04-20 12:59:26 +00:00
|
|
|
gfx::texture::FilterMethod::Scale,
|
2019-02-23 02:41:52 +00:00
|
|
|
gfx::texture::WrapMode::Clamp,
|
|
|
|
)),
|
|
|
|
_phantom: PhantomData,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2019-02-23 03:16:12 +00:00
|
|
|
// Updates a texture with the given data (used for updating the glyph cache texture)
|
2019-02-23 02:41:52 +00:00
|
|
|
pub fn update(
|
|
|
|
&self,
|
|
|
|
encoder: &mut gfx::Encoder<gfx_backend::Resources, gfx_backend::CommandBuffer>,
|
|
|
|
offset: [u16; 2],
|
|
|
|
size: [u16; 2],
|
|
|
|
data: &[[u8; 4]],
|
|
|
|
) -> Result<(), RenderError> {
|
|
|
|
let info = gfx::texture::ImageInfoCommon {
|
|
|
|
xoffset: offset[0],
|
|
|
|
yoffset: offset[1],
|
|
|
|
zoffset: 0,
|
|
|
|
width: size[0],
|
|
|
|
height: size[1],
|
|
|
|
depth: 0,
|
|
|
|
format: (),
|
|
|
|
mipmap: 0,
|
|
|
|
};
|
|
|
|
encoder
|
2019-04-29 20:37:19 +00:00
|
|
|
.update_texture::<<ShaderFormat as gfx::format::Formatted>::Surface, ShaderFormat>(
|
|
|
|
&self.tex, None, info, data,
|
|
|
|
)
|
|
|
|
.map_err(|err| RenderError::TexUpdateError(err))
|
2019-02-23 02:41:52 +00:00
|
|
|
}
|
2019-02-28 00:37:47 +00:00
|
|
|
/// Get dimensions of the represented image
|
|
|
|
pub fn get_dimensions(&self) -> Vec2<u16> {
|
|
|
|
let (w, h, ..) = self.tex.get_info().kind.get_dimensions();
|
|
|
|
Vec2::new(w, h)
|
|
|
|
}
|
2019-01-30 12:11:34 +00:00
|
|
|
}
|