rust/lib-hedgewars-engine/src/render/gl.rs
changeset 15285 6382a14c9e83
parent 14719 abc6aaf481c4
child 15286 16bd389fc735
equal deleted inserted replaced
15284:ae8e14d14596 15285:6382a14c9e83
     1 use integral_geometry::Rect;
     1 use integral_geometry::{Rect, Size};
     2 
     2 
     3 use std::{ffi, ffi::CString, mem, ptr, slice};
     3 use std::{ffi, ffi::CString, mem, num::NonZeroU32, ptr, slice};
     4 
     4 
     5 #[derive(Default)]
     5 #[derive(Default)]
     6 pub struct PipelineState {
     6 pub struct PipelineState {
     7     blending: bool,
     7     blending: bool,
     8 }
     8 }
    30     }
    30     }
    31 }
    31 }
    32 
    32 
    33 #[derive(Debug)]
    33 #[derive(Debug)]
    34 pub struct Texture2D {
    34 pub struct Texture2D {
    35     pub handle: u32,
    35     pub handle: Option<NonZeroU32>,
    36 }
    36 }
    37 
    37 
    38 impl Drop for Texture2D {
    38 impl Drop for Texture2D {
    39     fn drop(&mut self) {
    39     fn drop(&mut self) {
    40         if self.handle != 0 {
    40         if let Some(handle) = self.handle {
    41             unsafe {
    41             unsafe {
    42                 gl::DeleteTextures(1, &self.handle);
    42                 gl::DeleteTextures(1, &handle.get());
    43             }
    43             }
    44         }
    44         }
       
    45     }
       
    46 }
       
    47 
       
    48 fn new_texture() -> Option<NonZeroU32> {
       
    49     let mut handle = 0;
       
    50     unsafe {
       
    51         gl::GenTextures(1, &mut handle);
       
    52     }
       
    53     NonZeroU32::new(handle)
       
    54 }
       
    55 
       
    56 fn tex_params(filter: u32) {
       
    57     unsafe {
       
    58         gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
       
    59         gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
       
    60         gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, filter as i32);
       
    61         gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, filter as i32);
    45     }
    62     }
    46 }
    63 }
    47 
    64 
    48 impl Texture2D {
    65 impl Texture2D {
       
    66     pub fn new(size: Size, internal_format: u32, format: u32, ty: u32, filter: u32) -> Self {
       
    67         if let Some(handle) = new_texture() {
       
    68             unsafe {
       
    69                 gl::BindTexture(gl::TEXTURE_2D, handle.get());
       
    70                 gl::TexImage2D(
       
    71                     gl::TEXTURE_2D,
       
    72                     0,
       
    73                     internal_format as i32,
       
    74                     size.width as i32,
       
    75                     size.height as i32,
       
    76                     0,
       
    77                     format as u32,
       
    78                     ty,
       
    79                     std::ptr::null(),
       
    80                 )
       
    81             }
       
    82 
       
    83             tex_params(filter);
       
    84             Self {
       
    85                 handle: Some(handle),
       
    86             }
       
    87         } else {
       
    88             Self { handle: None }
       
    89         }
       
    90     }
       
    91 
    49     pub fn with_data(
    92     pub fn with_data(
    50         data: &[u8],
    93         data: &[u8],
    51         data_stride: u32,
    94         data_stride: u32,
    52         width: u32,
    95         size: Size,
    53         height: u32,
       
    54         internal_format: u32,
    96         internal_format: u32,
    55         format: u32,
    97         format: u32,
    56         ty: u32,
    98         ty: u32,
    57         filter: u32,
    99         filter: u32,
    58     ) -> Self {
   100     ) -> Self {
    59         let mut handle = 0;
   101         if let Some(handle) = new_texture() {
    60 
   102             unsafe {
    61         unsafe {
   103                 gl::BindTexture(gl::TEXTURE_2D, handle.get());
    62             gl::GenTextures(1, &mut handle);
   104                 gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
    63 
   105                 gl::TexImage2D(
    64             gl::BindTexture(gl::TEXTURE_2D, handle);
   106                     gl::TEXTURE_2D,
    65             gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
   107                     0,
    66             gl::TexImage2D(
   108                     internal_format as i32,
    67                 gl::TEXTURE_2D,
   109                     size.width as i32,
    68                 0,
   110                     size.height as i32,
    69                 internal_format as i32,
   111                     0,
    70                 width as i32,
   112                     format as u32,
    71                 height as i32,
   113                     ty,
    72                 0,
   114                     data.as_ptr() as *const _,
    73                 format as u32,
   115                 )
    74                 ty,
   116             }
    75                 data.as_ptr() as *const _,
   117 
    76             );
   118             tex_params(filter);
    77 
   119             Self {
    78             gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
   120                 handle: Some(handle),
    79             gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
   121             }
    80             gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, filter as i32);
   122         } else {
    81             gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, filter as i32);
   123             Self { handle: None }
    82         }
   124         }
    83 
       
    84         Texture2D { handle }
       
    85     }
   125     }
    86 
   126 
    87     pub fn update(&self, region: Rect, data: &[u8], data_stride: u32, format: u32, ty: u32) {
   127     pub fn update(&self, region: Rect, data: &[u8], data_stride: u32, format: u32, ty: u32) {
    88         unsafe {
   128         if let Some(handle) = self.handle {
    89             gl::BindTexture(gl::TEXTURE_2D, self.handle);
   129             unsafe {
    90             gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
   130                 gl::BindTexture(gl::TEXTURE_2D, handle.get());
    91             gl::TexSubImage2D(
   131                 gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
    92                 gl::TEXTURE_2D,
   132                 gl::TexSubImage2D(
    93                 0,             // texture level
   133                     gl::TEXTURE_2D,
    94                 region.left(), // texture region
   134                     0,             // texture level
    95                 region.top(),
   135                     region.left(), // texture region
    96                 region.width() as i32 - 1,
   136                     region.top(),
    97                 region.height() as i32 - 1,
   137                     region.right(),
    98                 format,                    // data format
   138                     region.bottom(),
    99                 ty,                        // data type
   139                     format,                    // data format
   100                 data.as_ptr() as *const _, // data ptr
   140                     ty,                        // data type
   101             );
   141                     data.as_ptr() as *const _, // data ptr
       
   142                 );
       
   143             }
   102         }
   144         }
   103     }
   145     }
   104 }
   146 }
   105 
   147 
   106 #[derive(Debug)]
   148 #[derive(Debug)]
   350     }
   392     }
   351 
   393 
   352     pub fn bind_texture_2d(&self, index: u32, texture: &Texture2D) {
   394     pub fn bind_texture_2d(&self, index: u32, texture: &Texture2D) {
   353         self.bind();
   395         self.bind();
   354 
   396 
   355         unsafe {
   397         if let Some(handle) = texture.handle {
   356             gl::ActiveTexture(gl::TEXTURE0 + index);
   398             unsafe {
   357             gl::BindTexture(gl::TEXTURE_2D, texture.handle);
   399                 gl::ActiveTexture(gl::TEXTURE0 + index);
       
   400                 gl::BindTexture(gl::TEXTURE_2D, handle.get());
       
   401             }
   358         }
   402         }
   359     }
   403     }
   360 }
   404 }
   361 
   405 
   362 pub enum InputFormat {
   406 pub enum InputFormat {