| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- use ::context;
- use ::image;
- use context::Context;
- use image::GenericImage;
- use std::os::raw::c_void;
-
- #[derive(Clone, Debug)]
- pub struct Texture<'a> {
- cx: &'a Context,
- texture_obj: u32,
- width: u32,
- height: u32,
- format: TextureFormat,
- }
-
- #[derive(Clone, Debug)]
- pub struct TextureId {
- pub(crate) id: u32,
- }
-
- impl<'a> Texture<'a> {
- pub fn new(cx: &'a Context, img: &image::DynamicImage) -> Result<Texture<'a>, ()> {
- let format = match *img {
- image::ImageRgb8(_) => TextureFormat::Rgb8,
- image::ImageRgba8(_) => TextureFormat::Rgba8,
- _ => return Err(()),
- };
-
- Ok(Self::from_bytes(cx, img.width(), img.height(), format, &img.raw_pixels()))
- }
-
- pub fn empty(cx: &'a Context, width: u32, height: u32, format: TextureFormat) -> Texture<'a> {
- Self::from_ptr(cx, width, height, format, ::std::ptr::null() as *const _)
- }
-
- pub fn from_bytes(cx: &'a Context, width: u32, height: u32, format: TextureFormat, data: &[u8]) -> Texture<'a> {
- Self::from_ptr(cx, width, height, format, data.as_ptr() as *const _)
- }
-
- fn from_ptr(cx: &'a Context, width: u32, height: u32, format: TextureFormat, data_ptr: *const c_void) -> Texture<'a> {
- let mut texture_obj = 0_u32;
- unsafe {
- cx.gl.GenTextures(1, &mut texture_obj);
- cx.gl.BindTexture(context::gl::TEXTURE_2D, texture_obj);
-
- cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_MIN_FILTER, context::gl::LINEAR as i32);
- cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_MAG_FILTER, context::gl::LINEAR as i32);
- cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_WRAP_S, context::gl::CLAMP_TO_EDGE as i32);
- cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_WRAP_T, context::gl::CLAMP_TO_EDGE as i32);
-
- cx.gl.TexImage2D(
- context::gl::TEXTURE_2D,
- 0, // level
- format.to_gl_enum() as i32,
- width as i32,
- height as i32,
- 0, // border (must be zero)
- format.to_gl_enum(),
- context::gl::UNSIGNED_BYTE,
- data_ptr);
- }
-
- Texture {
- cx,
- texture_obj,
- width,
- height,
- format,
- }
- }
-
- pub fn sub_image(&mut self, x: i32, y: i32, img: &image::DynamicImage) {
- let format = match *img {
- image::ImageRgb8(_) => TextureFormat::Rgb8,
- image::ImageRgba8(_) => TextureFormat::Rgba8,
- _ => return,
- };
-
- unsafe {
- self.cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
- self.cx.gl.TexSubImage2D(
- context::gl::TEXTURE_2D,
- 0, // level
- x, // x offset
- y, // y offset
- img.width() as i32,
- img.height() as i32,
- format.to_gl_enum(),
- context::gl::UNSIGNED_BYTE,
- img.raw_pixels().as_ptr() as *const _,
- );
- }
- }
-
- pub fn resize(&mut self, width: u32, height: u32) {
- unsafe {
- self.cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
- self.cx.gl.TexImage2D(
- context::gl::TEXTURE_2D,
- 0, // level
- self.format.to_gl_enum() as i32,
- width as i32,
- height as i32,
- 0, // border (must be zero)
- self.format.to_gl_enum(),
- context::gl::UNSIGNED_BYTE,
- ::std::ptr::null() as *const _);
-
- self.width = width;
- self.height = height;
- }
- }
-
- pub fn id(&self) -> TextureId {
- TextureId {
- id: self.texture_obj,
- }
- }
-
- pub fn width(&self) -> u32 {
- self.width
- }
-
- pub fn height(&self) -> u32 {
- self.height
- }
-
- pub fn context(&self) -> &Context {
- self.cx
- }
- }
-
- #[derive(Copy, Clone, Debug, Eq, PartialEq)]
- pub enum TextureFormat {
- Rgb8,
- Rgba8,
- }
-
- impl TextureFormat {
- pub fn to_gl_enum(self) -> u32 {
- match self {
- TextureFormat::Rgb8 => context::gl::RGB,
- TextureFormat::Rgba8 => context::gl::RGBA,
- }
- }
- }
|