A simple map viewer

texture.rs 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. use ::context;
  2. use ::image;
  3. use context::Context;
  4. use image::GenericImage;
  5. use std::os::raw::c_void;
  6. #[derive(Clone, Debug)]
  7. pub struct Texture<'a> {
  8. cx: &'a Context,
  9. texture_obj: u32,
  10. width: u32,
  11. height: u32,
  12. format: TextureFormat,
  13. }
  14. #[derive(Clone, Debug)]
  15. pub struct TextureId {
  16. pub(crate) id: u32,
  17. }
  18. impl<'a> Texture<'a> {
  19. pub fn new(cx: &'a Context, img: &image::DynamicImage) -> Result<Texture<'a>, ()> {
  20. let format = match *img {
  21. image::ImageRgb8(_) => TextureFormat::Rgb8,
  22. image::ImageRgba8(_) => TextureFormat::Rgba8,
  23. _ => return Err(()),
  24. };
  25. Ok(Self::from_bytes(cx, img.width(), img.height(), format, &img.raw_pixels()))
  26. }
  27. pub fn empty(cx: &'a Context, width: u32, height: u32, format: TextureFormat) -> Texture<'a> {
  28. Self::from_ptr(cx, width, height, format, ::std::ptr::null() as *const _)
  29. }
  30. pub fn from_bytes(cx: &'a Context, width: u32, height: u32, format: TextureFormat, data: &[u8]) -> Texture<'a> {
  31. Self::from_ptr(cx, width, height, format, data.as_ptr() as *const _)
  32. }
  33. fn from_ptr(cx: &'a Context, width: u32, height: u32, format: TextureFormat, data_ptr: *const c_void) -> Texture<'a> {
  34. let mut texture_obj = 0_u32;
  35. unsafe {
  36. cx.gl.GenTextures(1, &mut texture_obj);
  37. cx.gl.BindTexture(context::gl::TEXTURE_2D, texture_obj);
  38. cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_MIN_FILTER, context::gl::LINEAR as i32);
  39. cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_MAG_FILTER, context::gl::LINEAR as i32);
  40. cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_WRAP_S, context::gl::CLAMP_TO_EDGE as i32);
  41. cx.gl.TexParameteri(context::gl::TEXTURE_2D, context::gl::TEXTURE_WRAP_T, context::gl::CLAMP_TO_EDGE as i32);
  42. cx.gl.TexImage2D(
  43. context::gl::TEXTURE_2D,
  44. 0, // level
  45. format.to_gl_enum() as i32,
  46. width as i32,
  47. height as i32,
  48. 0, // border (must be zero)
  49. format.to_gl_enum(),
  50. context::gl::UNSIGNED_BYTE,
  51. data_ptr);
  52. }
  53. Texture {
  54. cx,
  55. texture_obj,
  56. width,
  57. height,
  58. format,
  59. }
  60. }
  61. pub fn sub_image(&mut self, x: i32, y: i32, img: &image::DynamicImage) {
  62. let format = match *img {
  63. image::ImageRgb8(_) => TextureFormat::Rgb8,
  64. image::ImageRgba8(_) => TextureFormat::Rgba8,
  65. _ => return,
  66. };
  67. unsafe {
  68. self.cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
  69. self.cx.gl.TexSubImage2D(
  70. context::gl::TEXTURE_2D,
  71. 0, // level
  72. x, // x offset
  73. y, // y offset
  74. img.width() as i32,
  75. img.height() as i32,
  76. format.to_gl_enum(),
  77. context::gl::UNSIGNED_BYTE,
  78. img.raw_pixels().as_ptr() as *const _,
  79. );
  80. }
  81. }
  82. pub fn resize(&mut self, width: u32, height: u32) {
  83. unsafe {
  84. self.cx.gl.BindTexture(context::gl::TEXTURE_2D, self.texture_obj);
  85. self.cx.gl.TexImage2D(
  86. context::gl::TEXTURE_2D,
  87. 0, // level
  88. self.format.to_gl_enum() as i32,
  89. width as i32,
  90. height as i32,
  91. 0, // border (must be zero)
  92. self.format.to_gl_enum(),
  93. context::gl::UNSIGNED_BYTE,
  94. ::std::ptr::null() as *const _);
  95. self.width = width;
  96. self.height = height;
  97. }
  98. }
  99. pub fn id(&self) -> TextureId {
  100. TextureId {
  101. id: self.texture_obj,
  102. }
  103. }
  104. pub fn width(&self) -> u32 {
  105. self.width
  106. }
  107. pub fn height(&self) -> u32 {
  108. self.height
  109. }
  110. pub fn context(&self) -> &Context {
  111. self.cx
  112. }
  113. }
  114. #[derive(Copy, Clone, Debug, Eq, PartialEq)]
  115. pub enum TextureFormat {
  116. Rgb8,
  117. Rgba8,
  118. }
  119. impl TextureFormat {
  120. pub fn to_gl_enum(self) -> u32 {
  121. match self {
  122. TextureFormat::Rgb8 => context::gl::RGB,
  123. TextureFormat::Rgba8 => context::gl::RGBA,
  124. }
  125. }
  126. }