#![allow(dead_code)] use smithay::backend::renderer::gles::{ ffi::{self, Gles2, FRAGMENT_SHADER, VERTEX_SHADER}, GlesError, }; use std::mem::transmute; use stereokit::Shader; use tracing::error; struct FfiAssetHeader { asset_type: i32, asset_state: i32, id: u64, index: u64, refs: i32, debug: *mut u8, } struct FfiSkgShader { meta: *mut u8, vertex: u32, pixel: u32, program: u32, compute: u32, } struct FfiShader { header: FfiAssetHeader, shader: FfiSkgShader, } unsafe fn compile_shader( gl: &ffi::Gles2, variant: ffi::types::GLuint, src: &str, ) -> Result { let shader = gl.CreateShader(variant); if shader == 0 { return Err(GlesError::CreateShaderObject); } gl.ShaderSource( shader, 1, &src.as_ptr() as *const *const u8 as *const *const ffi::types::GLchar, &(src.len() as i32) as *const _, ); gl.CompileShader(shader); let mut status = ffi::FALSE as i32; gl.GetShaderiv(shader, ffi::COMPILE_STATUS, &mut status as *mut _); if status == ffi::FALSE as i32 { let mut max_len = 0; gl.GetShaderiv(shader, ffi::INFO_LOG_LENGTH, &mut max_len as *mut _); let mut error = Vec::with_capacity(max_len as usize); let mut len = 0; gl.GetShaderInfoLog( shader, max_len as _, &mut len as *mut _, error.as_mut_ptr() as *mut _, ); error.set_len(len as usize); error!( "[GL] {}", std::str::from_utf8(&error).unwrap_or("") ); gl.DeleteShader(shader); return Err(GlesError::ShaderCompileError); } Ok(shader) } unsafe fn link_program( gl: &ffi::Gles2, vert: ffi::types::GLuint, frag: ffi::types::GLuint, ) -> Result { let program = gl.CreateProgram(); gl.AttachShader(program, vert); gl.AttachShader(program, frag); gl.LinkProgram(program); // gl.DetachShader(program, vert); // gl.DetachShader(program, frag); // gl.DeleteShader(vert); // gl.DeleteShader(frag); let mut status = ffi::FALSE as i32; gl.GetProgramiv(program, ffi::LINK_STATUS, &mut status as *mut _); if status == ffi::FALSE as i32 { let mut max_len = 0; gl.GetProgramiv(program, ffi::INFO_LOG_LENGTH, &mut max_len as *mut _); let mut error = Vec::with_capacity(max_len as usize); let mut len = 0; gl.GetProgramInfoLog( program, max_len as _, &mut len as *mut _, error.as_mut_ptr() as *mut _, ); error.set_len(len as usize); error!( "[GL] {}", std::str::from_utf8(&error).unwrap_or("") ); gl.DeleteProgram(program); return Err(GlesError::ProgramLinkError); } Ok(program) } pub unsafe fn shader_inject( c: &Gles2, sk_shader: &mut Shader, vert_str: &str, frag_str: &str, ) -> Result<(), GlesError> { let gl_vert = compile_shader(c, VERTEX_SHADER, vert_str)?; let gl_frag = compile_shader(c, FRAGMENT_SHADER, frag_str)?; let gl_prog = link_program(c, gl_vert, gl_frag)?; let shader: *mut FfiShader = transmute(sk_shader.0.as_mut()); if let Some(shader) = shader.as_mut() { shader.shader.vertex = gl_vert; shader.shader.pixel = gl_frag; shader.shader.program = gl_prog; } Ok(()) }