add an empty texture constructor
authoralfadur
Sat, 03 Aug 2019 00:54:29 +0300
changeset 15285 6382a14c9e83
parent 15284 ae8e14d14596
child 15286 16bd389fc735
add an empty texture constructor
rust/lib-hedgewars-engine/src/render/gl.rs
--- a/rust/lib-hedgewars-engine/src/render/gl.rs	Fri Aug 02 13:35:23 2019 +0200
+++ b/rust/lib-hedgewars-engine/src/render/gl.rs	Sat Aug 03 00:54:29 2019 +0300
@@ -1,6 +1,6 @@
-use integral_geometry::Rect;
+use integral_geometry::{Rect, Size};
 
-use std::{ffi, ffi::CString, mem, ptr, slice};
+use std::{ffi, ffi::CString, mem, num::NonZeroU32, ptr, slice};
 
 #[derive(Default)]
 pub struct PipelineState {
@@ -32,73 +32,115 @@
 
 #[derive(Debug)]
 pub struct Texture2D {
-    pub handle: u32,
+    pub handle: Option<NonZeroU32>,
 }
 
 impl Drop for Texture2D {
     fn drop(&mut self) {
-        if self.handle != 0 {
+        if let Some(handle) = self.handle {
             unsafe {
-                gl::DeleteTextures(1, &self.handle);
+                gl::DeleteTextures(1, &handle.get());
             }
         }
     }
 }
 
+fn new_texture() -> Option<NonZeroU32> {
+    let mut handle = 0;
+    unsafe {
+        gl::GenTextures(1, &mut handle);
+    }
+    NonZeroU32::new(handle)
+}
+
+fn tex_params(filter: u32) {
+    unsafe {
+        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
+        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
+        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, filter as i32);
+        gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, filter as i32);
+    }
+}
+
 impl Texture2D {
+    pub fn new(size: Size, internal_format: u32, format: u32, ty: u32, filter: u32) -> Self {
+        if let Some(handle) = new_texture() {
+            unsafe {
+                gl::BindTexture(gl::TEXTURE_2D, handle.get());
+                gl::TexImage2D(
+                    gl::TEXTURE_2D,
+                    0,
+                    internal_format as i32,
+                    size.width as i32,
+                    size.height as i32,
+                    0,
+                    format as u32,
+                    ty,
+                    std::ptr::null(),
+                )
+            }
+
+            tex_params(filter);
+            Self {
+                handle: Some(handle),
+            }
+        } else {
+            Self { handle: None }
+        }
+    }
+
     pub fn with_data(
         data: &[u8],
         data_stride: u32,
-        width: u32,
-        height: u32,
+        size: Size,
         internal_format: u32,
         format: u32,
         ty: u32,
         filter: u32,
     ) -> Self {
-        let mut handle = 0;
-
-        unsafe {
-            gl::GenTextures(1, &mut handle);
+        if let Some(handle) = new_texture() {
+            unsafe {
+                gl::BindTexture(gl::TEXTURE_2D, handle.get());
+                gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
+                gl::TexImage2D(
+                    gl::TEXTURE_2D,
+                    0,
+                    internal_format as i32,
+                    size.width as i32,
+                    size.height as i32,
+                    0,
+                    format as u32,
+                    ty,
+                    data.as_ptr() as *const _,
+                )
+            }
 
-            gl::BindTexture(gl::TEXTURE_2D, handle);
-            gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
-            gl::TexImage2D(
-                gl::TEXTURE_2D,
-                0,
-                internal_format as i32,
-                width as i32,
-                height as i32,
-                0,
-                format as u32,
-                ty,
-                data.as_ptr() as *const _,
-            );
-
-            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::CLAMP_TO_EDGE as i32);
-            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as i32);
-            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, filter as i32);
-            gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, filter as i32);
+            tex_params(filter);
+            Self {
+                handle: Some(handle),
+            }
+        } else {
+            Self { handle: None }
         }
-
-        Texture2D { handle }
     }
 
     pub fn update(&self, region: Rect, data: &[u8], data_stride: u32, format: u32, ty: u32) {
-        unsafe {
-            gl::BindTexture(gl::TEXTURE_2D, self.handle);
-            gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
-            gl::TexSubImage2D(
-                gl::TEXTURE_2D,
-                0,             // texture level
-                region.left(), // texture region
-                region.top(),
-                region.width() as i32 - 1,
-                region.height() as i32 - 1,
-                format,                    // data format
-                ty,                        // data type
-                data.as_ptr() as *const _, // data ptr
-            );
+        if let Some(handle) = self.handle {
+            unsafe {
+                gl::BindTexture(gl::TEXTURE_2D, handle.get());
+                gl::PixelStorei(gl::UNPACK_ROW_LENGTH, data_stride as i32);
+                gl::TexSubImage2D(
+                    gl::TEXTURE_2D,
+                    0,             // texture level
+                    region.left(), // texture region
+                    region.top(),
+                    region.right(),
+                    region.bottom(),
+                    format,                    // data format
+                    ty,                        // data type
+                    data.as_ptr() as *const _, // data ptr
+                );
+            }
         }
     }
 }
@@ -352,9 +394,11 @@
     pub fn bind_texture_2d(&self, index: u32, texture: &Texture2D) {
         self.bind();
 
-        unsafe {
-            gl::ActiveTexture(gl::TEXTURE0 + index);
-            gl::BindTexture(gl::TEXTURE_2D, texture.handle);
+        if let Some(handle) = texture.handle {
+            unsafe {
+                gl::ActiveTexture(gl::TEXTURE0 + index);
+                gl::BindTexture(gl::TEXTURE_2D, handle.get());
+            }
         }
     }
 }