cgl_rs/graphics/
texture.rs

1//! The txture module of CGL
2
3#![allow(non_camel_case_types)]
4use libc::{c_void, c_int, c_uint, size_t};
5
6/// The internal handle used by CGL
7#[repr(C)]
8pub(crate) struct CGL_texture {
9    _private: c_void
10}
11
12/// The texture format used by CGL
13/// These are reflections of OpenGL's enum values
14/// You can also use the _i version of methods to pass integers directly instead of enums
15pub enum TextureFormat {
16    RED     = 0x1903,
17    GREEN   = 0x1904,
18    BLUE    = 0x1905,
19    ALPHA   = 0x1906,
20    RGB     = 0x1907,
21    RGBA    = 0x1908,
22    BGR     = 0x80E0,
23    BGRA    = 0x80E1
24}
25
26/// The texture internal format used by CGL
27/// These are reflections of OpenGL's enum values
28/// You can also use the _i version of methods to pass integers directly instead of enums
29pub enum TextureInternalFormat {
30    RGBA32F             = 0x8814,
31    RGB32F              = 0x8815,
32    RGBA16F             = 0x881A,
33    RGB16F              = 0x881B,
34    RGBA32UI            = 0x8D70,
35    RGB32UI             = 0x8D71,
36    RGBA16UI            = 0x8D76,
37    RGB16UI             = 0x8D77,
38    RGBA8UI             = 0x8D7C,
39    RGB8UI              = 0x8D7D,
40    RGBA32I             = 0x8D82,
41    RGB32I              = 0x8D83,
42    RGBA16I             = 0x8D88,
43    RGB16I              = 0x8D89,
44    RGBA8I              = 0x8D8E,
45    RGB8I               = 0x8D8F,
46    RED_INTEGER         = 0x8D94,
47    GREEN_INTEGER       = 0x8D95,
48    BLUE_INTEGER        = 0x8D96,
49    RGB_INTEGER         = 0x8D98,
50    RGBA_INTEGER        = 0x8D99,
51    BGR_INTEGER         = 0x8D9A,
52    BGRA_INTEGER        = 0x8D9B
53}
54
55
56/// The texture data type used by CGL
57/// These are reflections of OpenGL's enum values
58/// You can also use the _i version of methods to pass integers directly instead of enums
59pub enum TextureDataType {
60    BYTE              = 0x1400,
61    UNSIGNED_BYTE     = 0x1401,
62    SHORT             = 0x1402,
63    UNSIGNED_SHORT    = 0x1403,
64    INT               = 0x1404,
65    UNSIGNED_INT      = 0x1405,
66    FLOAT             = 0x1406
67}
68
69/// The texture scaling mode used by CGL
70/// These are reflections of OpenGL's enum values
71/// You can also use the _i version of methods to pass integers directly instead of enums
72pub enum TextureScalingMode {
73    NEAREST                 = 0x2600,
74    LINEAR                  = 0x2601,
75    NEAREST_MIPMAP_NEAREST  = 0x2700,
76    LINEAR_MIPMAP_NEAREST   = 0x2701,
77    NEAREST_MIPMAP_LINEAR   = 0x2702,
78    LINEAR_MIPMAP_LINEAR    = 0x2703
79}
80
81
82/// The texture wrapping mode used by CGL
83/// These are reflections of OpenGL's enum values
84/// You can also use the _i version of methods to pass integers directly instead of enums
85pub enum TextureWrappingMode {
86    REPEAT              = 0x2901,
87    MIRRORED_REPEAT     = 0x8370,
88    CLAMP_TO_EDGE       = 0x812F,
89    CLAMP_TO_BORDER     = 0x812D
90}
91
92/// The texture object
93pub struct Texture {
94    pub(crate) handle: *mut CGL_texture,
95    pub(crate) has_been_destroyed: bool
96}
97
98
99#[repr(C)]
100pub(crate) struct CGL_image {
101    pub(crate) data: *mut c_void,
102    pub(crate) height: c_int,
103    pub(crate) width: c_int,
104    pub(crate) bytes_per_channel: c_int,
105    pub(crate) channels: c_int
106}
107
108extern {
109    fn CGL_texture_create(image: *mut CGL_image) -> *mut CGL_texture;
110    fn CGL_texture_create_blank(width: c_int, height: c_int, format: c_uint, internal_format: c_uint, data_type: c_uint) -> *mut CGL_texture;
111    fn CGL_texture_create_array(width: c_int, height: c_int, layers: c_int, format: c_uint, internal_format: c_uint, data_type: c_uint) -> *mut CGL_texture;
112    fn CGL_texture_create_3d(width: c_int, height: c_int, depth: c_int, format: c_uint, internal_format: c_uint, data_type: c_uint) -> *mut CGL_texture;
113    fn CGL_texture_create_cubemap() -> *mut CGL_texture;
114    fn CGL_texture_cubemap_set_face(texture: *mut CGL_texture, face: c_int, image: *mut CGL_image);
115    fn CGL_texture_array_set_layer_data(texture: *mut CGL_texture, layer: c_int, data: *mut c_void);
116    fn CGL_texture_destroy(texture: *mut CGL_texture);
117    fn CGL_texture_bind(texture: *mut CGL_texture, unit: c_int) -> c_int;
118    fn CGL_texture_set_data(texture: *mut CGL_texture, data: *mut c_void);
119    fn CGL_texture_set_sub_data(texture: *mut CGL_texture, offset_x: size_t, offset_y: size_t, size_x: size_t, size_y: size_t, data: *mut c_void);
120    fn CGL_texture_set_pixel_data(texture: *mut CGL_texture, x: c_int, y: c_int, data: *mut c_void);
121    fn CGL_texture_set_user_data(texture: *mut CGL_texture, user_data: *mut c_void);
122    fn CGL_texture_get_user_data(texture: *mut CGL_texture) -> *mut c_void;
123    fn CGL_texture_get_internal_handle(texture: *mut CGL_texture) -> c_uint;
124    fn CGL_texture_get_size(texture: *mut CGL_texture, width: *mut c_int, height: *mut c_int);
125    fn CGL_texture_set_scaling_method(texture: *mut CGL_texture, method: c_int);
126    fn CGL_texture_set_wrapping_method(texture: *mut CGL_texture, method: c_int);
127}
128
129
130
131impl Texture {
132    
133     /// Creates a new blank texture with the specified dimensions and format.
134    /// 
135    /// # Arguments
136    /// 
137    /// * `width` - The width of the texture in pixels.
138    /// * `height` - The height of the texture in pixels.
139    /// * `format` - The format of the texture data.
140    /// * `internal_format` - The internal format of the texture data.
141    /// * `data_type` - The data type of the texture data.
142    /// 
143    /// # Returns
144    /// 
145    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
146    /// 
147    /// # Example
148    /// 
149    /// ```
150    /// cgl_rs::init();
151    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
152    /// cgl_rs::graphics::init();
153    /// {
154    ///     let texture = cgl_rs::graphics::Texture::blank_i(256, 256, cgl_rs::graphics::TextureFormat::RGBA as u32, cgl_rs::graphics::TextureInternalFormat::RGBA8UI as u32, cgl_rs::graphics::TextureDataType::UNSIGNED_BYTE as u32).unwrap();
155    /// }
156    /// cgl_rs::graphics::shutdown();
157    /// window.destroy();
158    /// cgl_rs::shutdown();
159    /// ```
160    pub fn blank_i(width: i32, height: i32, format: u32, internal_format: u32, data_type: u32) -> Result<Texture, &'static str> {
161        let handle = unsafe {
162            CGL_texture_create_blank(width, height, format as c_uint, internal_format as c_uint, data_type as c_uint)
163        };
164        if handle.is_null() {
165            Err("Failed to create texture")
166        } else {
167            Ok(Texture {
168                handle,
169                has_been_destroyed: false
170            })
171        }
172    }
173
174    /// Creates a new blank texture with the specified dimensions and format.
175    /// 
176    /// # Arguments
177    /// 
178    /// * `width` - The width of the texture in pixels.
179    /// * `height` - The height of the texture in pixels.
180    /// * `format` - The format of the texture data.
181    /// * `internal_format` - The internal format of the texture data.
182    /// * `data_type` - The data type of the texture data.
183    /// 
184    /// # Returns
185    /// 
186    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
187    /// 
188    /// # Example
189    /// 
190    /// ```
191    /// cgl_rs::init();
192    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
193    /// cgl_rs::graphics::init();
194    /// {
195    ///     let texture = cgl_rs::graphics::Texture::blank(256, 256, cgl_rs::graphics::TextureFormat::RGBA, cgl_rs::graphics::TextureInternalFormat::RGBA8UI, cgl_rs::graphics::TextureDataType::UNSIGNED_BYTE).unwrap();
196    /// }
197    /// cgl_rs::graphics::shutdown();
198    /// window.destroy();
199    /// cgl_rs::shutdown();
200    pub fn blank(width: i32, height: i32, format: TextureFormat, internal_format: TextureInternalFormat, data_type: TextureDataType) -> Result<Texture, &'static str> {
201        Texture::blank_i(width, height, format as u32, internal_format as u32, data_type as u32)
202    }
203
204    /// Creates a new dummy texture with a single pixel.
205    /// 
206    /// # Returns
207    /// 
208    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
209    /// 
210    /// # Example
211    /// 
212    /// ```
213    /// cgl_rs::init();
214    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
215    /// cgl_rs::graphics::init();
216    /// {
217    ///     let texture = cgl_rs::graphics::Texture::dummy().unwrap();
218    /// }
219    /// cgl_rs::graphics::shutdown();
220    /// window.destroy();
221    /// cgl_rs::shutdown();
222    pub fn dummy() -> Result<Texture, &'static str> {
223        Texture::blank(1, 1, TextureFormat::RGBA, TextureInternalFormat::RGBA8UI, TextureDataType::UNSIGNED_BYTE)
224    }
225
226    /// Creates a new dummy texture with the specified dimensions.
227    /// 
228    /// # Arguments
229    /// 
230    /// * `width` - The width of the texture in pixels.
231    /// * `height` - The height of the texture in pixels.
232    /// 
233    /// # Returns
234    /// 
235    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
236    /// 
237    /// # Example
238    /// 
239    /// ```
240    /// cgl_rs::init();
241    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
242    /// cgl_rs::graphics::init();
243    /// {
244    ///     let texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
245    /// }
246    /// cgl_rs::graphics::shutdown();
247    /// window.destroy();
248    /// cgl_rs::shutdown();
249    pub fn dummy2(width: i32, height: i32) -> Result<Texture, &'static str> {
250        Texture::blank(width, height, TextureFormat::RGBA, TextureInternalFormat::RGBA8UI, TextureDataType::UNSIGNED_BYTE)
251    }
252
253    /// Creates a new texture array with the specified dimensions and format.
254    /// 
255    /// # Arguments
256    /// 
257    /// * `width` - The width of the texture in pixels.
258    /// * `height` - The height of the texture in pixels.
259    /// * `depth` - The depth of the texture array.
260    /// * `format` - The format of the texture data.
261    /// * `internal_format` - The internal format of the texture data.
262    /// * `data_type` - The data type of the texture data.
263    /// 
264    /// # Returns
265    /// 
266    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
267    /// 
268    /// # Example
269    /// 
270    /// ```
271    /// cgl_rs::init();
272    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
273    /// cgl_rs::graphics::init();
274    /// {
275    ///     let texture = cgl_rs::graphics::Texture::array_i(256, 256, 6, cgl_rs::graphics::TextureFormat::RGBA as u32, cgl_rs::graphics::TextureInternalFormat::RGBA8UI as u32, cgl_rs::graphics::TextureDataType::UNSIGNED_BYTE as u32).unwrap();
276    /// }
277    /// cgl_rs::graphics::shutdown();
278    /// window.destroy();
279    /// cgl_rs::shutdown();
280    pub fn array_i(width: i32, height: i32, depth: i32, format: u32, internal_format: u32, data_type: u32) -> Result<Texture, &'static str> {
281        let handle = unsafe {
282            CGL_texture_create_array(width, height, depth, format as c_uint, internal_format as c_uint, data_type as c_uint)
283        };
284        if handle.is_null() {
285            Err("Failed to create texture")
286        } else {
287            Ok(Texture {
288                handle,
289                has_been_destroyed: false
290            })
291        }
292    }
293
294    // Creates a new texture array with the specified dimensions and format.
295    /// 
296    /// # Arguments
297    /// 
298    /// * `width` - The width of the texture in pixels.
299    /// * `height` - The height of the texture in pixels.
300    /// * `depth` - The depth of the texture array.
301    /// * `format` - The format of the texture data.
302    /// * `internal_format` - The internal format of the texture data.
303    /// * `data_type` - The data type of the texture data.
304    /// 
305    /// # Returns
306    /// 
307    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
308    /// 
309    /// # Example
310    /// 
311    /// ```
312    /// cgl_rs::init();
313    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
314    /// cgl_rs::graphics::init();
315    /// {
316    ///     let texture = cgl_rs::graphics::Texture::array(256, 256, 6, cgl_rs::graphics::TextureFormat::RGBA, cgl_rs::graphics::TextureInternalFormat::RGBA8UI, cgl_rs::graphics::TextureDataType::UNSIGNED_BYTE).unwrap();
317    /// }
318    /// cgl_rs::graphics::shutdown();
319    /// window.destroy();
320    /// cgl_rs::shutdown();
321    pub fn array(width: i32, height: i32, depth: i32, format: TextureFormat, internal_format: TextureInternalFormat, data_type: TextureDataType) -> Result<Texture, &'static str> {
322        Texture::array_i(width, height, depth, format as u32, internal_format as u32, data_type as u32)
323    }
324
325    /// Creates a new cubemap texture.
326    /// 
327    /// # Returns
328    /// 
329    /// A `Result` containing the newly created `Texture` if successful, or an error message if creation failed.
330    /// 
331    /// # Example
332    /// 
333    /// ```
334    /// cgl_rs::init();
335    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
336    /// cgl_rs::graphics::init();
337    /// {
338    ///     let texture = cgl_rs::graphics::Texture::cubemap().unwrap();
339    /// }
340    /// cgl_rs::graphics::shutdown();
341    /// window.destroy();
342    /// cgl_rs::shutdown();
343    pub fn cubemap() -> Result<Texture, &'static str> {
344        let handle = unsafe {
345            CGL_texture_create_cubemap()
346        };
347        if handle.is_null() {
348            Err("Failed to create texture")
349        } else {
350            Ok(Texture {
351                handle,
352                has_been_destroyed: false
353            })
354        }
355    }
356
357    // TODO : Implement cubemap_set_face
358
359    /// Sets the data for a single layer of a texture array.
360    /// 
361    /// # Arguments
362    /// 
363    /// * `layer` - The index of the layer to set the data for.
364    /// * `data` - A slice containing the data to set for the layer.
365    /// 
366    /// # Example
367    /// 
368    /// ```
369    /// cgl_rs::init();
370    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
371    /// cgl_rs::graphics::init();
372    /// {
373    ///     let mut texture = cgl_rs::graphics::Texture::array(256, 256, 6, cgl_rs::graphics::TextureFormat::RGBA, cgl_rs::graphics::TextureInternalFormat::RGBA8UI, cgl_rs::graphics::TextureDataType::UNSIGNED_BYTE).unwrap();
374    ///     let data = vec![0u8; 256 * 256 * 4];
375    ///     texture.array_set_layer_data(0, &data);
376    /// }
377    /// cgl_rs::graphics::shutdown();
378    /// window.destroy();
379    /// cgl_rs::shutdown();
380    pub fn array_set_layer_data(&self, layer: i32, data: &[u8]) {
381        unsafe {
382            CGL_texture_array_set_layer_data(self.handle, layer, data.as_ptr() as *mut c_void);
383        }
384    }
385
386    /// Binds the texture to a texture unit.
387    /// 
388    /// # Arguments
389    /// 
390    /// * `unit` - The texture unit to bind the texture to.
391    /// 
392    /// # Example
393    /// 
394    /// ```
395    /// cgl_rs::init();
396    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
397    /// cgl_rs::graphics::init();
398    /// {
399    ///     let texture = cgl_rs::graphics::Texture::dummy().unwrap();
400    ///     texture.bind(0);
401    /// }
402    /// cgl_rs::graphics::shutdown();
403    /// window.destroy();
404    /// cgl_rs::shutdown();
405    pub fn bind(&self, unit: u32) {
406        unsafe {
407            CGL_texture_bind(self.handle, unit as i32);
408        }
409    }
410
411    /// Sets the data for the texture.
412    /// 
413    /// # Arguments
414    /// 
415    /// * `data` - A slice containing the data to set for the texture.
416    /// 
417    /// # Example
418    /// 
419    /// ```
420    /// cgl_rs::init();
421    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
422    /// cgl_rs::graphics::init();
423    /// {
424    ///     let mut texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
425    ///     let data = vec![0u8; 256 * 256 * 4];
426    ///     texture.set_data(data.as_ptr());
427    /// }
428    /// cgl_rs::graphics::shutdown();
429    /// window.destroy();
430    /// cgl_rs::shutdown();
431    pub fn set_data(&self, data: *const u8) {
432        unsafe {
433            CGL_texture_set_data(self.handle, data as *mut c_void);
434        }
435    }
436
437    /// Sets a rectangular subregion of the texture with new data.
438    ///
439    /// # Arguments
440    ///
441    /// * `x` - The x-coordinate of the lower left corner of the subregion.
442    /// * `y` - The y-coordinate of the lower left corner of the subregion.
443    /// * `width` - The width of the subregion.
444    /// * `height` - The height of the subregion.
445    /// * `data` - A slice containing the new data to set for the subregion.
446    ///
447    /// # Example
448    ///
449    /// ```
450    /// cgl_rs::init();
451    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
452    /// cgl_rs::graphics::init();
453    /// {
454    ///     let mut texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
455    ///     let data = vec![255u8; 100 * 100 * 4];
456    ///     texture.set_sub_data(0, 0, 100, 100, data.as_ptr());
457    /// }
458    /// cgl_rs::graphics::shutdown();
459    /// window.destroy();
460    /// cgl_rs::shutdown();
461    /// ```
462    pub fn set_sub_data(&self, x: usize, y: usize, width: usize, height: usize, data: *const u8) {
463        unsafe {
464            CGL_texture_set_sub_data(self.handle, x, y, width, height, data as *mut c_void);
465        }
466    }
467
468    /// Returns the internal OpenGL handle of the texture.
469    ///
470    /// # Example
471    ///
472    /// ```
473    /// cgl_rs::init();
474    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
475    /// cgl_rs::graphics::init();
476    /// {
477    ///     let texture = cgl_rs::graphics::Texture::dummy().unwrap();
478    ///     let handle = texture.get_internal_gl_handle();
479    ///     println!("Internal OpenGL handle: {}", handle);
480    /// }
481    /// cgl_rs::graphics::shutdown();
482    /// window.destroy();
483    /// cgl_rs::shutdown();
484    /// ```
485    pub fn get_internal_gl_handle(&self) -> u32 {
486        unsafe {
487            CGL_texture_get_internal_handle(self.handle) as u32
488        }
489    }
490
491    /// Sets the scaling method of the texture.
492    ///
493    /// # Arguments
494    ///
495    /// * `method` - The scaling method to use for the texture.
496    ///
497    /// # Example
498    ///
499    /// ```
500    /// cgl_rs::init();
501    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
502    /// cgl_rs::graphics::init();
503    /// {
504    ///     let mut texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
505    ///     texture.set_scaling_method_i(1);
506    /// }
507    /// cgl_rs::graphics::shutdown();
508    /// window.destroy();
509    /// cgl_rs::shutdown();
510    /// ```
511    pub fn set_scaling_method_i(&self, method: i32) {
512        unsafe {
513            CGL_texture_set_scaling_method(self.handle, method as i32);
514        }
515    }
516
517    // Sets the scaling method of the texture.
518    ///
519    /// # Arguments
520    ///
521    /// * `method` - The scaling method to use for the texture.
522    ///
523    /// # Example
524    ///
525    /// ```
526    /// cgl_rs::init();
527    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
528    /// cgl_rs::graphics::init();
529    /// {
530    ///     let mut texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
531    ///     texture.set_scaling_method(cgl_rs::graphics::TextureScalingMode::LINEAR);
532    /// }
533    /// cgl_rs::graphics::shutdown();
534    /// window.destroy();
535    /// cgl_rs::shutdown();
536    /// ```
537    pub fn set_scaling_method(&self, method: TextureScalingMode) {
538        self.set_scaling_method_i(method as i32);
539    }
540
541    /// Sets the wrapping method of the texture.
542    ///
543    /// # Arguments
544    ///
545    /// * `method` - The wrapping method to use for the texture.
546    ///
547    /// # Example
548    ///
549    /// ```
550    /// cgl_rs::init();
551    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
552    /// cgl_rs::graphics::init();
553    /// {
554    ///    let mut texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
555    ///    texture.set_wrapping_method_i(1);
556    /// }
557    /// cgl_rs::graphics::shutdown();
558    /// window.destroy();
559    /// cgl_rs::shutdown();
560    /// ```
561    pub fn set_wrapping_method_i(&self, method: i32) {
562        unsafe {
563            CGL_texture_set_wrapping_method(self.handle, method as i32);
564        }
565    }
566
567    /// Sets the wrapping method of the texture.
568    ///
569    /// # Arguments
570    ///
571    /// * `method` - The wrapping method to use for the texture.
572    ///
573    /// # Example
574    ///
575    /// ```
576    /// cgl_rs::init();
577    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
578    /// cgl_rs::graphics::init();
579    /// {
580    ///    let mut texture = cgl_rs::graphics::Texture::dummy2(256, 256).unwrap();
581    ///    texture.set_wrapping_method(cgl_rs::graphics::TextureWrappingMode::CLAMP_TO_EDGE);
582    /// }
583    /// cgl_rs::graphics::shutdown();
584    /// window.destroy();
585    /// cgl_rs::shutdown();
586    /// ```
587    pub fn set_wrapping_method(&self, method: TextureWrappingMode) {
588        self.set_wrapping_method_i(method as i32);
589    }
590
591
592    /// Destroys the texture and frees its resources. If the texture has already been destroyed, this method does nothing.
593    /// 
594    /// # Example
595    /// 
596    /// ```
597    /// cgl_rs::init();
598    /// let mut window = cgl_rs::Window::new("Hello, World!", 800, 600).unwrap();
599    /// cgl_rs::graphics::init();
600    /// {
601    ///     let mut texture = cgl_rs::graphics::Texture::dummy().unwrap();
602    ///     texture.destroy(); // optional
603    /// }
604    /// cgl_rs::graphics::shutdown();
605    /// window.destroy();
606    /// cgl_rs::shutdown();
607    pub fn destroy(&mut self) {
608        if !self.has_been_destroyed {
609            unsafe {
610                CGL_texture_destroy(self.handle);
611            }
612            self.has_been_destroyed = true;
613        }
614    }
615
616}
617
618impl Drop for Texture {
619    fn drop(&mut self) {
620        self.destroy();
621    }
622}
623
624
625impl Clone for Texture {
626    /// Clones the texture.
627    /// 
628    /// NOTE: The new instance will have the same handle, `has_been_destroyed` flag.
629    ///       This means that the new instance will not be able to receive events nor will the internal window handle be
630    ///       destroyed when the new instance is dropped. The internal window handle will be destroyed when the original
631    ///       instance is dropped.
632    /// 
633    /// 
634    /// # Returns
635    /// 
636    /// A new instance of `Texture` with the same handle as the original texture.
637    fn clone(&self) -> Self {
638        Texture {
639            handle: self.handle.clone(),
640            has_been_destroyed: true
641        }
642    }
643}