Skip to main content

beamterm_core/gl/
context.rs

1use glow::HasContext;
2
3/// Manages simple GL state to reduce redundant state changes
4#[derive(Debug)]
5pub struct GlState {
6    // Viewport dimensions
7    viewport: [i32; 4], // [x, y, width, height]
8
9    // Clear color
10    clear_color: [f32; 4],
11
12    // Blend function state
13    blend_func: (u32, u32), // (src_factor, dst_factor)
14
15    // Active texture unit
16    active_texture_unit: u32,
17
18    // Enabled vertex attribute arrays
19    enabled_vertex_attribs: Vec<bool>,
20}
21
22impl GlState {
23    /// Create a new GLState object with GL defaults
24    pub fn new(gl: &glow::Context) -> Self {
25        // Get max vertex attributes
26        let max_vertex_attribs = unsafe { gl.get_parameter_i32(glow::MAX_VERTEX_ATTRIBS) as usize };
27
28        Self {
29            viewport: [0, 0, 0, 0],
30            clear_color: [0.0, 0.0, 0.0, 0.0],
31            blend_func: (glow::ONE, glow::ZERO), // Default blend function
32            active_texture_unit: glow::TEXTURE0,
33            enabled_vertex_attribs: vec![false; max_vertex_attribs],
34        }
35    }
36
37    /// Set viewport dimensions
38    pub fn viewport(
39        &mut self,
40        gl: &glow::Context,
41        x: i32,
42        y: i32,
43        width: i32,
44        height: i32,
45    ) -> &mut Self {
46        let new_viewport = [x, y, width, height];
47        if self.viewport != new_viewport {
48            unsafe { gl.viewport(x, y, width, height) };
49            self.viewport = new_viewport;
50        }
51        self
52    }
53
54    /// Set clear color
55    pub fn clear_color(&mut self, gl: &glow::Context, r: f32, g: f32, b: f32, a: f32) -> &mut Self {
56        let new_color = [r, g, b, a];
57        if self.clear_color != new_color {
58            unsafe { gl.clear_color(r, g, b, a) };
59            self.clear_color = new_color;
60        }
61        self
62    }
63
64    /// Set active texture unit
65    pub fn active_texture(&mut self, gl: &glow::Context, texture_unit: u32) -> &mut Self {
66        if self.active_texture_unit != texture_unit {
67            unsafe { gl.active_texture(texture_unit) };
68            self.active_texture_unit = texture_unit;
69        }
70        self
71    }
72
73    /// Enable or disable a vertex attribute array
74    pub fn vertex_attrib_array(
75        &mut self,
76        gl: &glow::Context,
77        index: u32,
78        enable: bool,
79    ) -> &mut Self {
80        let idx = index as usize;
81        if idx < self.enabled_vertex_attribs.len() && self.enabled_vertex_attribs[idx] != enable {
82            if enable {
83                unsafe { gl.enable_vertex_attrib_array(index) };
84            } else {
85                unsafe { gl.disable_vertex_attrib_array(index) };
86            }
87            self.enabled_vertex_attribs[idx] = enable;
88        }
89        self
90    }
91
92    /// Reset all tracked state to GL defaults
93    pub fn reset(&mut self, gl: &glow::Context) {
94        // Reset blend function
95        if self.blend_func != (glow::ONE, glow::ZERO) {
96            unsafe { gl.blend_func(glow::ONE, glow::ZERO) };
97            self.blend_func = (glow::ONE, glow::ZERO);
98        }
99
100        // Reset texture unit
101        if self.active_texture_unit != glow::TEXTURE0 {
102            unsafe { gl.active_texture(glow::TEXTURE0) };
103            self.active_texture_unit = glow::TEXTURE0;
104        }
105
106        // Reset vertex attributes
107        for (idx, enabled) in self.enabled_vertex_attribs.iter_mut().enumerate() {
108            if *enabled {
109                unsafe { gl.disable_vertex_attrib_array(idx as u32) };
110                *enabled = false;
111            }
112        }
113
114        // Note: We don't reset viewport or clear_color as these are typically
115        // set based on canvas dimensions or application needs
116    }
117}