1use num_enum::{IntoPrimitive, TryFromPrimitive};
2use std::cell::RefCell;
3use std::convert::TryInto;
4use std::fmt::Debug;
5use std::ops::Deref;
6use std::ops::DerefMut;
7use web_sys::{AngleInstancedArrays, WebGlRenderingContext as Context};
8
9use super::data_buffer::{ArrayBuffer, Item, ItemsBuffer};
10use super::gl::Gl;
11use super::program::Program;
12use super::texture::Texture;
13use super::texture::TextureFilter;
14use crate::depth_buffer::DepthBuffer;
15use crate::{ElementsBuffer, FrameBuffer};
16
17#[repr(u32)]
18#[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Eq)]
19pub enum BlendFunction {
20 Zero = Context::ZERO,
21 One = Context::ONE,
22 SrcColor = Context::SRC_COLOR,
23 OneMinusSrcColor = Context::ONE_MINUS_SRC_COLOR,
24 DstColor = Context::DST_COLOR,
25 OneMinusDstColor = Context::ONE_MINUS_DST_COLOR,
26 SrcAlpha = Context::SRC_ALPHA,
27 OneMinusSrcAlpha = Context::ONE_MINUS_SRC_ALPHA,
28 DstAlpha = Context::DST_ALPHA,
29 OneMinusDstAlpha = Context::ONE_MINUS_DST_ALPHA,
30 SrcAlphaSaturate = Context::SRC_ALPHA_SATURATE,
31}
32
33#[repr(u32)]
34#[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Eq)]
35pub enum CullFace {
36 Front = Context::FRONT,
37 Back = Context::BACK,
38 FrontAndBack = Context::FRONT_AND_BACK,
39}
40
41impl Default for CullFace {
42 fn default() -> Self {
43 CullFace::Back
44 }
45}
46
47#[repr(u32)]
48#[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Eq)]
49pub enum BlendEquation {
50 Add = Context::FUNC_ADD,
51 Sub = Context::FUNC_SUBTRACT,
52 RSub = Context::FUNC_REVERSE_SUBTRACT,
53}
54
55impl Default for BlendEquation {
56 fn default() -> Self {
57 BlendEquation::Add
58 }
59}
60
61#[repr(u32)]
62#[derive(Clone, Copy, Debug, TryFromPrimitive, IntoPrimitive, PartialEq, Eq)]
63pub enum DepthFunction {
64 Never = Context::NEVER,
65 Less = Context::LESS,
66 Equal = Context::EQUAL,
67 LEqual = Context::LEQUAL,
68 Greater = Context::GREATER,
69 NotEqual = Context::NOTEQUAL,
70 GEqual = Context::GEQUAL,
71 Always = Context::ALWAYS,
72}
73
74impl Default for DepthFunction {
75 fn default() -> Self {
76 DepthFunction::Less
77 }
78}
79
80#[derive(Clone, Copy, PartialEq, Eq, Debug)]
81pub struct ColorMask(bool, bool, bool, bool);
82
83impl Default for ColorMask {
84 fn default() -> Self {
85 Self(true, true, true, true)
86 }
87}
88
89#[derive(Clone, Debug, Default)]
90pub struct SettingsCache {
91 blend: BlendSetting,
92 depth: DepthTestSetting,
93 array_buffer: ArrayBufferSetting,
94 element_buffer: ElementBufferSetting,
95 active_texture: ActiveTextureSetting,
96 textures: [Option<Texture>; 16],
97 enabled_attributes: EnabledAttributesSetting,
98 instanced_attributes: InstancedAttributesSetting,
99 program: ProgramSetting,
100 clear_color: ClearColorSetting,
101 clear_depth: ClearDepthSetting,
102 viewport: ViewportSetting,
103 depth_buffer: DepthBufferSetting,
104 frame_buffer: FrameBufferSetting,
105 blend_equation: BlendEquationSetting,
106 blend_function: BlendFunctionSetting,
107 depth_function: DepthFunction,
108 cull_face: CullFace,
109 color_mask: ColorMask,
110}
111
112pub trait Settings
113where
114 Self: PartialEq,
115 Self: Debug,
116 Self: Clone,
117{
118 fn apply<R, F: FnOnce() -> R>(&self, gl: &Gl, cache: &RefCell<SettingsCache>, callback: F)
119 -> R;
120
121 fn depth_test(self, value: bool) -> ComposedSetting<Self, DepthTestSetting> {
122 ComposedSetting(self, DepthTestSetting(value))
123 }
124
125 fn blend(self, value: bool) -> ComposedSetting<Self, BlendSetting> {
126 ComposedSetting(self, BlendSetting(value))
127 }
128
129 fn blend_equation(
130 self,
131 color: BlendEquation,
132 alpha: BlendEquation,
133 ) -> ComposedSetting<Self, BlendEquationSetting> {
134 ComposedSetting(self, BlendEquationSetting { color, alpha })
135 }
136
137 fn blend_function(
138 self,
139 src_rgb: BlendFunction,
140 dst_rgb: BlendFunction,
141 src_alpha: BlendFunction,
142 dst_alpha: BlendFunction,
143 ) -> ComposedSetting<Self, BlendFunctionSetting> {
144 ComposedSetting(
145 self,
146 BlendFunctionSetting {
147 src_rgb,
148 dst_rgb,
149 src_alpha,
150 dst_alpha,
151 },
152 )
153 }
154
155 fn depth_function(self, function: DepthFunction) -> ComposedSetting<Self, DepthFunction> {
156 ComposedSetting(self, function)
157 }
158
159 fn active_texture(self, index: u32) -> ComposedSetting<Self, ActiveTextureSetting> {
160 ComposedSetting(self, ActiveTextureSetting(index))
161 }
162
163 fn texture(self, index: u32, texture: Texture) -> ComposedSetting<Self, TextureSetting> {
164 ComposedSetting(
165 self,
166 TextureSetting {
167 index,
168 texture: Some(texture),
169 },
170 )
171 }
172
173 fn texture_list<T: IntoIterator<Item = Texture>>(
174 self,
175 textures: T,
176 ) -> ComposedSetting<Self, TextureListSetting> {
177 let mut setting: [Option<Texture>; 16] = Default::default();
178 for (i, texture) in textures.into_iter().enumerate() {
179 setting[i] = Some(texture);
180 }
181 ComposedSetting(self, TextureListSetting { textures: setting })
182 }
183
184 fn texture_filter(
185 self,
186 texture: Texture,
187 filter: TextureFilter,
188 ) -> ComposedSetting<Self, TextureFilterSetting> {
189 ComposedSetting(self, TextureFilterSetting { texture, filter })
190 }
191
192 fn array_buffer(self, array_buffer: ArrayBuffer) -> ComposedSetting<Self, ArrayBufferSetting> {
193 ComposedSetting(self, ArrayBufferSetting(Some(array_buffer)))
194 }
195
196 fn items_buffer<T: Item>(
197 self,
198 array_buffer: ItemsBuffer<T>,
199 ) -> ComposedSetting<Self, ArrayBufferSetting> {
200 ComposedSetting(self, ArrayBufferSetting(Some(array_buffer.buffer)))
201 }
202
203 fn element_buffer(
204 self,
205 element_buffer: ElementsBuffer,
206 ) -> ComposedSetting<Self, ElementBufferSetting> {
207 ComposedSetting(self, ElementBufferSetting(Some(element_buffer)))
208 }
209
210 fn enabled_attributes(
211 self,
212 attributes: &[u32],
213 ) -> ComposedSetting<Self, EnabledAttributesSetting> {
214 ComposedSetting(
215 self,
216 EnabledAttributesSetting {
217 items: attributes.into(),
218 },
219 )
220 }
221
222 fn program(self, program: Program) -> ComposedSetting<Self, ProgramSetting> {
223 ComposedSetting(
224 self,
225 ProgramSetting {
226 program: Some(program),
227 },
228 )
229 }
230
231 fn clear_color(
232 self,
233 r: f32,
234 g: f32,
235 b: f32,
236 alpha: f32,
237 ) -> ComposedSetting<Self, ClearColorSetting> {
238 ComposedSetting(
239 self,
240 ClearColorSetting {
241 color: [r, g, b, alpha],
242 },
243 )
244 }
245
246 fn clear_depth(self, value: f32) -> ComposedSetting<Self, ClearDepthSetting> {
247 ComposedSetting(self, ClearDepthSetting { value })
248 }
249
250 fn viewport(
251 self,
252 x: i32,
253 y: i32,
254 width: i32,
255 height: i32,
256 ) -> ComposedSetting<Self, ViewportSetting> {
257 ComposedSetting(
258 self,
259 ViewportSetting {
260 x,
261 y,
262 width,
263 height,
264 },
265 )
266 }
267
268 fn depth_buffer(self, buffer: DepthBuffer) -> ComposedSetting<Self, DepthBufferSetting> {
269 ComposedSetting(
270 self,
271 DepthBufferSetting {
272 buffer: Some(buffer),
273 },
274 )
275 }
276
277 fn frame_buffer(self, buffer: FrameBuffer) -> ComposedSetting<Self, FrameBufferSetting> {
278 ComposedSetting(
279 self,
280 FrameBufferSetting {
281 buffer: Some(buffer),
282 },
283 )
284 }
285
286 fn cull_face(self, cull_face: CullFace) -> ComposedSetting<Self, CullFace> {
287 ComposedSetting(self, cull_face)
288 }
289
290 fn color_mask(self, r: bool, g: bool, b: bool, a: bool) -> ComposedSetting<Self, ColorMask> {
291 ComposedSetting(self, ColorMask(r, g, b, a))
292 }
293}
294
295pub trait CachedSettings {
296 fn set(gl: &Gl, value: &Self);
297 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self;
298 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self);
299}
300
301impl<T> Settings for T
302where
303 T: PartialEq,
304 T: Debug,
305 T: Clone,
306 T: CachedSettings,
307{
308 fn apply<R, F: FnOnce() -> R>(
309 &self,
310 gl: &Gl,
311 cache: &RefCell<SettingsCache>,
312 callback: F,
313 ) -> R {
314 let old_value = Self::read_cached(&cache.borrow());
315 return if self == &old_value {
316 callback()
317 } else {
318 Self::write_cached(&mut cache.borrow_mut(), self);
319 Self::set(gl, self);
320 let result = callback();
321 Self::set(gl, &old_value);
322 Self::write_cached(&mut cache.borrow_mut(), &old_value);
323 result
324 };
325 }
326}
327
328#[derive(Default, PartialEq, Debug, Clone)]
329pub struct EmptySetting {}
330
331impl Settings for EmptySetting {
332 fn apply<R, F: FnOnce() -> R>(&self, _: &Gl, _: &RefCell<SettingsCache>, callback: F) -> R {
333 callback()
334 }
335}
336
337#[derive(Default, PartialEq, Debug, Clone)]
338pub struct ComposedSetting<S1: Settings, S2: Settings>(S1, S2);
339
340impl<S1: Settings, S2: Settings> Settings for ComposedSetting<S1, S2> {
341 fn apply<R, F: FnOnce() -> R>(
342 &self,
343 gl: &Gl,
344 cache: &RefCell<SettingsCache>,
345 callback: F,
346 ) -> R {
347 self.0
348 .apply(gl, cache, || self.1.apply(gl, cache, || callback()))
349 }
350}
351#[derive(Default, PartialEq, Debug, Clone, Copy)]
352pub struct ClearColorSetting {
353 color: [f32; 4],
354}
355
356impl CachedSettings for ClearColorSetting {
357 fn set(gl: &Gl, value: &Self) {
358 gl.context().clear_color(
359 value.color[0],
360 value.color[1],
361 value.color[2],
362 value.color[3],
363 );
364 }
365
366 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
367 cache.clear_color
368 }
369
370 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
371 cache.clear_color = *value;
372 }
373}
374
375#[derive(Default, PartialEq, Debug, Clone, Copy)]
376pub struct ClearDepthSetting {
377 value: f32,
378}
379
380impl CachedSettings for ClearDepthSetting {
381 fn set(gl: &Gl, value: &Self) {
382 gl.context().clear_depth(value.value);
383 }
384
385 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
386 cache.clear_depth
387 }
388
389 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
390 cache.clear_depth = *value;
391 }
392}
393
394#[derive(Default, PartialEq, Debug, Clone, Copy)]
395pub struct ViewportSetting {
396 pub x: i32,
397 pub y: i32,
398 pub width: i32,
399 pub height: i32,
400}
401
402impl CachedSettings for ViewportSetting {
403 fn set(gl: &Gl, value: &Self) {
404 gl.context()
405 .viewport(value.x, value.y, value.width, value.height);
406 }
407
408 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
409 cache.viewport
410 }
411
412 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
413 cache.viewport = *value;
414 }
415}
416
417#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
418pub struct ActiveTextureSetting(u32);
419
420impl CachedSettings for ActiveTextureSetting {
421 fn set(gl: &Gl, value: &Self) {
422 gl.context().active_texture(value.0 + Context::TEXTURE0);
423 }
424 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
425 cache.active_texture
426 }
427 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
428 cache.active_texture = *value;
429 }
430}
431
432#[derive(Clone, Debug, Default, PartialEq, Eq)]
433pub struct ArrayBufferSetting(Option<ArrayBuffer>);
434
435impl CachedSettings for ArrayBufferSetting {
436 fn set(gl: &Gl, value: &Self) {
437 gl.context().bind_buffer(
438 Context::ARRAY_BUFFER,
439 value.0.as_ref().map(|v| v.handle()).as_ref(),
440 );
441 }
442 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
443 cache.array_buffer.clone()
444 }
445 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
446 cache.array_buffer = value.clone();
447 }
448}
449
450#[derive(Clone, Debug, Default, PartialEq, Eq)]
451pub struct ElementBufferSetting(Option<ElementsBuffer>);
452
453impl CachedSettings for ElementBufferSetting {
454 fn set(gl: &Gl, value: &Self) {
455 gl.context().bind_buffer(
456 Context::ELEMENT_ARRAY_BUFFER,
457 value.0.as_ref().map(|v| v.handle()).as_ref(),
458 );
459 }
460 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
461 cache.element_buffer.clone()
462 }
463 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
464 cache.element_buffer = value.clone();
465 }
466}
467
468#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
469pub struct BlendSetting(bool);
470
471impl CachedSettings for BlendSetting {
472 fn set(gl: &Gl, value: &Self) {
473 if value.0 {
474 gl.context().enable(Context::BLEND)
475 } else {
476 gl.context().disable(Context::BLEND)
477 }
478 }
479 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
480 cache.blend
481 }
482 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
483 cache.blend = *value;
484 }
485}
486
487#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
488pub struct DepthTestSetting(bool);
489
490impl CachedSettings for DepthTestSetting {
491 fn set(gl: &Gl, value: &Self) {
492 if value.0 {
493 gl.context().enable(Context::DEPTH_TEST)
494 } else {
495 gl.context().disable(Context::DEPTH_TEST)
496 }
497 }
498 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
499 cache.depth
500 }
501 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
502 cache.depth = *value;
503 }
504}
505
506#[derive(Clone, Debug, Default, PartialEq, Eq)]
507pub struct TextureSetting {
508 index: u32,
509 texture: Option<Texture>,
510}
511
512impl TextureSetting {
513 pub(self) fn set_texture(gl: &Gl, index: u32, texture: Option<&Texture>) {
514 gl.apply(Gl::settings().active_texture(index), || {
515 gl.context()
516 .bind_texture(Context::TEXTURE_2D, texture.map(|texture| texture.handle()));
517 })
518 }
519}
520
521impl Settings for TextureSetting {
522 fn apply<R, F: FnOnce() -> R>(
523 &self,
524 gl: &Gl,
525 cache: &RefCell<SettingsCache>,
526 callback: F,
527 ) -> R {
528 let previous = cache.borrow().textures[self.index as usize].clone();
529 cache.borrow_mut().textures[self.index as usize] = self.texture.clone();
530 Self::set_texture(gl, self.index, self.texture.as_ref());
531 let result = callback();
532 Self::set_texture(gl, self.index, previous.as_ref());
533 cache.borrow_mut().textures[self.index as usize] = previous;
534 return result;
535 }
536}
537
538#[derive(Clone, Debug, Default, PartialEq, Eq)]
539pub struct TextureListSetting {
540 textures: [Option<Texture>; 16],
541}
542
543impl TextureListSetting {
544 pub(self) fn set_textures(
545 gl: &Gl,
546 current: &[Option<Texture>; 16],
547 target: &[Option<Texture>; 16],
548 ) {
549 for i in 0..16 {
550 if current[i] != target[i] {
551 TextureSetting::set_texture(gl, i.try_into().unwrap(), target[i].as_ref());
552 }
553 }
554 }
555}
556
557impl Settings for TextureListSetting {
558 fn apply<R, F: FnOnce() -> R>(
559 &self,
560 gl: &Gl,
561 cache: &RefCell<SettingsCache>,
562 callback: F,
563 ) -> R {
564 let previous = cache.borrow().textures.clone();
565
566 cache.borrow_mut().textures = self.textures.clone();
567 TextureListSetting::set_textures(gl, &previous, &self.textures);
568
569 let result = callback();
570
571 TextureListSetting::set_textures(gl, &self.textures, &previous);
572 cache.borrow_mut().textures = previous;
573
574 return result;
575 }
576}
577
578#[derive(Clone, Debug, PartialEq, Eq)]
579pub struct TextureFilterSetting {
580 texture: Texture,
581 filter: TextureFilter,
582}
583
584impl Settings for TextureFilterSetting {
585 fn apply<R, F: FnOnce() -> R>(&self, _: &Gl, _: &RefCell<SettingsCache>, callback: F) -> R {
586 let previous = self.texture.filter();
587 let current = self.filter;
588 self.texture.set_filter(current);
589 let result = callback();
590 self.texture.set_filter(previous);
591 return result;
592 }
593}
594
595fn array_diff<'a, T: PartialEq>(v1: &'a Vec<T>, v2: &'a Vec<T>) -> impl Iterator<Item = &'a T> {
596 v1.iter().filter(move |i| !v2.contains(i))
597}
598
599#[derive(Clone, Debug, Default, PartialEq, Eq)]
600pub struct EnabledAttributesSetting {
601 items: Vec<u32>,
602}
603
604impl Settings for EnabledAttributesSetting {
605 fn apply<R, F: FnOnce() -> R>(
606 &self,
607 gl: &Gl,
608 cache: &RefCell<SettingsCache>,
609 callback: F,
610 ) -> R {
611 let context: &Context = gl.context();
612 let previous = { cache.borrow().enabled_attributes.clone() };
614
615 {
617 cache.borrow_mut().enabled_attributes = self.clone();
618 }
619
620 array_diff(&previous.items, &self.items).for_each(|i| {
622 context.disable_vertex_attrib_array(*i);
623 });
624
625 array_diff(&self.items, &previous.items).for_each(|i| {
627 context.enable_vertex_attrib_array(*i);
628 });
629
630 let result = callback();
632
633 array_diff(&previous.items, &self.items).for_each(|i| {
635 context.enable_vertex_attrib_array(*i);
636 });
637
638 array_diff(&self.items, &previous.items).for_each(|i| {
639 context.disable_vertex_attrib_array(*i);
640 });
641
642 {
643 cache.borrow_mut().enabled_attributes = previous;
644 }
645
646 return result;
647 }
648}
649
650#[derive(Clone, Debug, Default, PartialEq, Eq)]
651pub struct InstancedAttributesSetting {
652 items: Vec<u32>,
653}
654
655impl Settings for InstancedAttributesSetting {
656 fn apply<R, F: FnOnce() -> R>(
657 &self,
658 gl: &Gl,
659 cache: &RefCell<SettingsCache>,
660 callback: F,
661 ) -> R {
662 let context: &AngleInstancedArrays = gl.instanced_arrays();
663 let previous = { cache.borrow().instanced_attributes.clone() };
665
666 {
668 cache.borrow_mut().instanced_attributes = self.clone();
669 }
670
671 array_diff(&previous.items, &self.items).for_each(|i| {
673 context.vertex_attrib_divisor_angle(*i, 0);
674 });
675
676 array_diff(&self.items, &previous.items).for_each(|i| {
678 context.vertex_attrib_divisor_angle(*i, 1);
679 });
680
681 let result = callback();
683
684 array_diff(&previous.items, &self.items).for_each(|i| {
686 context.vertex_attrib_divisor_angle(*i, 1);
687 });
688
689 array_diff(&self.items, &previous.items).for_each(|i| {
690 context.vertex_attrib_divisor_angle(*i, 0);
691 });
692
693 {
694 cache.borrow_mut().instanced_attributes = previous;
695 }
696
697 return result;
698 }
699}
700
701#[derive(Clone, Debug, Default, PartialEq, Eq)]
702pub struct ProgramSetting {
703 program: Option<Program>,
704}
705
706impl CachedSettings for ProgramSetting {
707 fn set(gl: &Gl, value: &Self) {
708 gl.context().use_program(
709 value
710 .program
711 .as_ref()
712 .map(|program| program.handle())
713 .as_ref(),
714 );
715 }
716
717 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
718 cache.program.clone()
719 }
720
721 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
722 cache.program = value.clone();
723 }
724}
725
726#[derive(Clone, Debug, Default, PartialEq, Eq)]
727pub struct DepthBufferSetting {
728 buffer: Option<DepthBuffer>,
729}
730
731impl CachedSettings for DepthBufferSetting {
732 fn set(gl: &Gl, value: &Self) {
733 gl.context().bind_renderbuffer(
734 Context::RENDERBUFFER,
735 value.buffer.as_ref().map(|v| v.handle()),
736 );
737 }
738
739 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
740 cache.depth_buffer.clone()
741 }
742
743 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
744 cache.depth_buffer = value.clone();
745 }
746}
747
748#[derive(Clone, Debug, Default, PartialEq, Eq)]
749pub struct FrameBufferSetting {
750 buffer: Option<FrameBuffer>,
751}
752
753impl CachedSettings for FrameBufferSetting {
754 fn set(gl: &Gl, value: &Self) {
755 gl.context().bind_framebuffer(
756 Context::FRAMEBUFFER,
757 value.buffer.as_ref().map(|v| v.handle()),
758 );
759 }
760
761 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
762 cache.frame_buffer.clone()
763 }
764
765 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
766 cache.frame_buffer = value.clone();
767 }
768}
769
770#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
771pub struct BlendEquationSetting {
772 color: BlendEquation,
773 alpha: BlendEquation,
774}
775
776impl CachedSettings for BlendEquationSetting {
777 fn set(gl: &Gl, value: &Self) {
778 gl.context()
779 .blend_equation_separate(value.color.into(), value.alpha.into());
780 }
781
782 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
783 cache.blend_equation
784 }
785
786 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
787 cache.blend_equation = *value;
788 }
789}
790
791#[derive(Clone, Copy, Debug, PartialEq, Eq)]
792pub struct BlendFunctionSetting {
793 src_rgb: BlendFunction,
794 dst_rgb: BlendFunction,
795 src_alpha: BlendFunction,
796 dst_alpha: BlendFunction,
797}
798
799impl Default for BlendFunctionSetting {
800 fn default() -> Self {
801 BlendFunctionSetting {
802 src_rgb: BlendFunction::One,
803 dst_rgb: BlendFunction::Zero,
804 src_alpha: BlendFunction::One,
805 dst_alpha: BlendFunction::Zero,
806 }
807 }
808}
809
810impl CachedSettings for BlendFunctionSetting {
811 fn set(gl: &Gl, value: &Self) {
812 gl.context().blend_func_separate(
813 value.src_rgb.into(),
814 value.dst_rgb.into(),
815 value.src_alpha.into(),
816 value.dst_alpha.into(),
817 );
818 }
819
820 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
821 cache.blend_function
822 }
823
824 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
825 cache.blend_function = *value;
826 }
827}
828
829impl CachedSettings for DepthFunction {
830 fn set(gl: &Gl, value: &Self) {
831 gl.context().depth_func((*value).into());
832 }
833
834 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
835 cache.depth_function
836 }
837
838 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
839 cache.depth_function = *value;
840 }
841}
842
843impl CachedSettings for CullFace {
844 fn set(gl: &Gl, value: &Self) {
845 gl.context().cull_face((*value).into());
846 }
847
848 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
849 cache.cull_face
850 }
851
852 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
853 cache.cull_face = *value;
854 }
855}
856
857impl CachedSettings for ColorMask {
858 fn set(gl: &Gl, value: &Self) {
859 gl.context().color_mask(value.0, value.1, value.2, value.3);
860 }
861
862 fn read_cached(cache: &impl Deref<Target = SettingsCache>) -> Self {
863 cache.color_mask
864 }
865
866 fn write_cached(cache: &mut impl DerefMut<Target = SettingsCache>, value: &Self) {
867 cache.color_mask = *value;
868 }
869}