1use std::{error::Error, fmt::Formatter, rc::Rc};
14
15use ffgl_core::*;
16use glium::{
17 backend::Context,
18 framebuffer::{RenderBuffer, SimpleFrameBuffer},
19 BlitTarget, CapabilitiesSource, Frame, Surface, Texture2d,
20};
21use std::fmt::Debug;
22
23mod gl_backend;
24pub mod texture;
25pub mod validate_gl;
26
27pub struct FFGLGlium {
29 pub ctx: Rc<Context>,
30 backend: Rc<gl_backend::RawGlBackend>,
31}
32
33impl Debug for FFGLGlium {
34 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35 f.debug_struct("FFGLGliumHandler").finish()
36 }
37}
38
39impl FFGLGlium {
40 pub fn new(inst_data: &FFGLData) -> Self {
41 let backend = Rc::new(gl_backend::RawGlBackend::new(inst_data.get_dimensions()));
42
43 tracing::debug!("BACKEND: {backend:?}");
44
45 let ctx = unsafe {
46 glium::backend::Context::new(
47 backend.clone(),
48 false,
49 glium::debug::DebugCallbackBehavior::Ignore,
50 )
51 .unwrap()
52 };
53
54 let valid_versions = &ctx.get_capabilities().supported_glsl_versions;
55
56 tracing::debug!("VALID VERSIONS: {valid_versions:?}");
57
58 tracing::debug!("OPENGL_VERSION {}", ctx.get_opengl_version_string());
59
60 Self { ctx, backend }
61 }
62
63 pub fn draw(
64 &self,
65 output_res: (u32, u32),
66 render_res: (u32, u32),
67 frame_data: GLInput<'_>,
68 render_frame: &mut impl FnMut(
69 &mut SimpleFrameBuffer,
70 Vec<Texture2d>,
71 ) -> Result<(), Box<dyn Error>>,
72 ) {
73 unsafe { self.ctx.rebuild(self.backend.clone()).unwrap() };
74
75 let frame = Frame::new(self.ctx.clone(), (render_res.0, render_res.1));
76 let rb = RenderBuffer::new(
77 &self.ctx,
78 glium::texture::UncompressedFloatFormat::U8U8U8U8,
79 render_res.0,
80 render_res.1,
81 )
82 .unwrap();
83
84 let fb = &mut SimpleFrameBuffer::new(&self.ctx, &rb).unwrap();
85
86 let textures: Vec<_> = frame_data
87 .textures
88 .iter()
89 .map(|texture_info| unsafe {
90 Texture2d::from_id(
91 &self.ctx,
92 glium::texture::UncompressedFloatFormat::U8U8U8U8,
93 texture_info.Handle,
94 false,
95 glium::texture::MipmapsOption::NoMipmap,
96 glium::texture::Dimensions::Texture2d {
97 width: texture_info.Width,
98 height: texture_info.Height,
99 },
100 )
101 })
102 .collect();
103
104 if let Err(err) = render_frame(fb, textures) {
105 tracing::error!("Render ERROR: {err:?}");
106 }
107
108 fb.fill(&frame, glium::uniforms::MagnifySamplerFilter::Nearest);
112
113 unsafe {
115 gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, frame_data.host);
116 blit_fb(render_res, output_res);
117 }
118
119 frame.finish().unwrap();
120
121 }
127}
128
129unsafe fn blit_fb((read_w, read_h): (u32, u32), (write_w, write_h): (u32, u32)) {
130 let src_rect = BlitTarget {
131 left: 0,
132 bottom: 0,
133 width: read_w as i32,
134 height: read_h as i32,
135 };
136
137 let target_rect = BlitTarget {
138 left: 0 as u32,
139 bottom: 0 as u32,
140 width: write_w as i32,
141 height: write_h as i32,
142 };
143
144 gl::BlitFramebuffer(
145 src_rect.left as gl::types::GLint,
146 src_rect.bottom as gl::types::GLint,
147 (src_rect.left as i32 + src_rect.width) as gl::types::GLint,
148 (src_rect.bottom as i32 + src_rect.height) as gl::types::GLint,
149 (target_rect.left) as gl::types::GLint,
150 (target_rect.bottom) as gl::types::GLint,
151 (target_rect.left as i32 + target_rect.width) as gl::types::GLint,
152 (target_rect.bottom as i32 + target_rect.height) as gl::types::GLint,
153 gl::COLOR_BUFFER_BIT,
154 gl::NEAREST,
155 );
156}