diff --git a/README.md b/README.md index 9cf6c1bf..87a1eb33 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ The following features have been implemented and should work: - Hardware cursors - Pointer constraints - Selecting the primary device in multi-GPU systems +- An OpenGL backend +- A Vulkan backend ### Missing Features @@ -56,7 +58,6 @@ automatically. It is however unavoidable that Jay depends on a number of native libraries: * **libinput.so**: For input event processing. -* **libEGL.so**, **libGLESv2.so**: For OpenGL rendering. * **libgbm.so**: For graphics buffer allocation. * **libxkbcommon.so**: For keymap handling. * **libudev.so**: For device enumeration and hotplug support. @@ -76,6 +77,8 @@ At runtime, Jay depends on the following services being available on the system: Jay as an X client.) * **Logind**: For the metal backend. (Only required if you want to run Jay from a TTY.) +* **libEGL.so**, **libGLESv2.so**: For the OpenGL backend. +* **libvulkan.so**: For the Vulkan backend. ## Building and Installing diff --git a/build/egl.rs b/build/egl.rs index bfba180d..148f421f 100644 --- a/build/egl.rs +++ b/build/egl.rs @@ -97,16 +97,17 @@ fn write_egl_procs(f: &mut W) -> anyhow::Result<()> { writeln!(f, "unsafe impl Send for ExtProc {{ }}")?; writeln!(f)?; writeln!(f, "impl ExtProc {{")?; - writeln!(f, " pub fn load() -> Self {{")?; - writeln!(f, " Self {{")?; + writeln!(f, " pub fn load() -> Option {{")?; + writeln!(f, " let egl = EGL.as_ref()?;")?; + writeln!(f, " Some(Self {{")?; for (name, _, _) in map.iter().copied() { writeln!( f, - " {}: unsafe {{ eglGetProcAddress(\"{}\\0\".as_ptr() as _) }},", + " {}: unsafe {{ (egl.eglGetProcAddress)(\"{}\\0\".as_ptr() as _) }},", name, name )?; } - writeln!(f, " }}")?; + writeln!(f, " }})")?; writeln!(f, " }}")?; for (name, ret, args) in map.iter().copied() { let mut args_names = String::new(); diff --git a/src/gfx_apis/gl.rs b/src/gfx_apis/gl.rs index f080d1a0..908f12d9 100644 --- a/src/gfx_apis/gl.rs +++ b/src/gfx_apis/gl.rs @@ -18,6 +18,53 @@ macro_rules! egl_transparent { }; } +macro_rules! dynload { + ( + $item:ident: $container:ident from $name:literal { + $( + $fun:ident: $ty:ty, + )* + } + ) => { + #[allow(non_snake_case)] + #[derive(Debug)] + pub struct $container { + _lib: libloading::Library, + $( + pub $fun: $ty, + )* + } + + pub static $item: once_cell::sync::Lazy> = once_cell::sync::Lazy::new(|| unsafe { + use crate::utils::errorfmt::ErrorFmt; + let lib = match libloading::Library::new($name) { + Ok(l) => l, + Err(e) => { + log::error!("Could not load lib{}: {}", $name, ErrorFmt(e)); + return None; + } + }; + $( + #[allow(non_snake_case)] + let $fun: $ty = + match lib.get(stringify!($fun).as_bytes()) { + Ok(s) => *s, + Err(e) => { + log::error!("Could not load {} from {}: {}", stringify!($fun), $name, ErrorFmt(e)); + return None; + } + }; + )* + Some($container { + _lib: lib, + $( + $fun, + )* + }) + }); + }; +} + use { crate::{ gfx_api::{ @@ -27,10 +74,8 @@ use { gl::texture::image_target, renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture}, sys::{ - glActiveTexture, glBindTexture, glDisable, glDisableVertexAttribArray, - glDrawArrays, glEnable, glEnableVertexAttribArray, glTexParameteri, glUniform1i, - glUniform4f, glUseProgram, glVertexAttribPointer, GL_BLEND, GL_FALSE, GL_FLOAT, - GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP, + GL_BLEND, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER, + GL_TRIANGLES, GL_TRIANGLE_STRIP, }, }, theme::Color, @@ -69,6 +114,12 @@ pub(super) fn create_gfx_context(drm: &Drm) -> Result, GfxErr #[derive(Debug, Error)] enum RenderError { + #[error("Could not load libEGL")] + LoadEgl, + #[error("Could not load libGLESv2")] + LoadGlesV2, + #[error("Could not load extension functions from libEGL")] + LoadEglProcs, #[error("EGL library does not support `EGL_EXT_platform_base`")] ExtPlatformBase, #[error("Could not compile a shader")] @@ -221,10 +272,11 @@ fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) { } fn fill_boxes3(ctx: &GlRenderContext, boxes: &[f32], color: &Color) { + let gles = ctx.ctx.dpy.gles; unsafe { - glUseProgram(ctx.fill_prog.prog); - glUniform4f(ctx.fill_prog_color, color.r, color.g, color.b, color.a); - glVertexAttribPointer( + (gles.glUseProgram)(ctx.fill_prog.prog); + (gles.glUniform4f)(ctx.fill_prog_color, color.r, color.g, color.b, color.a); + (gles.glVertexAttribPointer)( ctx.fill_prog_pos as _, 2, GL_FLOAT, @@ -232,9 +284,9 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[f32], color: &Color) { 0, boxes.as_ptr() as _, ); - glEnableVertexAttribArray(ctx.fill_prog_pos as _); - glDrawArrays(GL_TRIANGLES, 0, (boxes.len() / 2) as _); - glDisableVertexAttribArray(ctx.fill_prog_pos as _); + (gles.glEnableVertexAttribArray)(ctx.fill_prog_pos as _); + (gles.glDrawArrays)(GL_TRIANGLES, 0, (boxes.len() / 2) as _); + (gles.glDisableVertexAttribArray)(ctx.fill_prog_pos as _); } } @@ -248,13 +300,14 @@ fn render_texture( src: &BufferPoints, ) { assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx)); + let gles = ctx.ctx.dpy.gles; unsafe { - glActiveTexture(GL_TEXTURE0); + (gles.glActiveTexture)(GL_TEXTURE0); let target = image_target(texture.gl.external_only); - glBindTexture(target, texture.gl.tex); - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + (gles.glBindTexture)(target, texture.gl.tex); + (gles.glTexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); let progs = match texture.gl.external_only { true => match &ctx.tex_external { @@ -268,18 +321,18 @@ fn render_texture( }; let prog = match texture.gl.format.has_alpha { true => { - glEnable(GL_BLEND); + (gles.glEnable)(GL_BLEND); &progs.alpha } false => { - glDisable(GL_BLEND); + (gles.glDisable)(GL_BLEND); &progs.solid } }; - glUseProgram(prog.prog.prog); + (gles.glUseProgram)(prog.prog.prog); - glUniform1i(prog.tex, 0); + (gles.glUniform1i)(prog.tex, 0); let texcoord = [ src.top_right.x, @@ -299,7 +352,7 @@ fn render_texture( x1, y2, // bottom left ]; - glVertexAttribPointer( + (gles.glVertexAttribPointer)( prog.texcoord as _, 2, GL_FLOAT, @@ -307,17 +360,17 @@ fn render_texture( 0, texcoord.as_ptr() as _, ); - glVertexAttribPointer(prog.pos as _, 2, GL_FLOAT, GL_FALSE, 0, pos.as_ptr() as _); + (gles.glVertexAttribPointer)(prog.pos as _, 2, GL_FLOAT, GL_FALSE, 0, pos.as_ptr() as _); - glEnableVertexAttribArray(prog.texcoord as _); - glEnableVertexAttribArray(prog.pos as _); + (gles.glEnableVertexAttribArray)(prog.texcoord as _); + (gles.glEnableVertexAttribArray)(prog.pos as _); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + (gles.glDrawArrays)(GL_TRIANGLE_STRIP, 0, 4); - glDisableVertexAttribArray(prog.texcoord as _); - glDisableVertexAttribArray(prog.pos as _); + (gles.glDisableVertexAttribArray)(prog.texcoord as _); + (gles.glDisableVertexAttribArray)(prog.pos as _); - glBindTexture(target, 0); + (gles.glBindTexture)(target, 0); } } diff --git a/src/gfx_apis/gl/egl.rs b/src/gfx_apis/gl/egl.rs index 1eb65803..a6237cb4 100644 --- a/src/gfx_apis/gl/egl.rs +++ b/src/gfx_apis/gl/egl.rs @@ -1,12 +1,13 @@ use { crate::gfx_apis::gl::{ egl::sys::{ - eglBindAPI, EGLAttrib, EGLLabelKHR, EGLenum, EGLint, EGL_DEBUG_MSG_CRITICAL_KHR, + EGLAttrib, EGLLabelKHR, EGLenum, EGLint, EGL_DEBUG_MSG_CRITICAL_KHR, EGL_DEBUG_MSG_ERROR_KHR, EGL_DEBUG_MSG_INFO_KHR, EGL_DEBUG_MSG_WARN_KHR, EGL_NONE, EGL_OPENGL_ES_API, EGL_TRUE, }, ext::{get_client_ext, ClientExt, EXT_PLATFORM_BASE, KHR_DEBUG, KHR_PLATFORM_GBM}, proc::ExtProc, + sys::EGL, RenderError, }, bstr::ByteSlice, @@ -27,11 +28,17 @@ pub mod display; pub mod image; pub mod sys; -pub(crate) static PROCS: Lazy = Lazy::new(ExtProc::load); +pub(crate) static PROCS: Lazy> = Lazy::new(ExtProc::load); pub(crate) static EXTS: Lazy = Lazy::new(get_client_ext); pub(in crate::gfx_apis::gl) fn init() -> Result<(), RenderError> { + let Some(egl) = EGL.as_ref() else { + return Err(RenderError::LoadEgl); + }; + let Some(procs) = PROCS.as_ref() else { + return Err(RenderError::LoadEglProcs); + }; if !EXTS.contains(EXT_PLATFORM_BASE) { return Err(RenderError::ExtPlatformBase); } @@ -51,10 +58,10 @@ pub(in crate::gfx_apis::gl) fn init() -> Result<(), RenderError> { EGL_NONE as _, ]; unsafe { - PROCS.eglDebugMessageControlKHR(egl_log, attrib.as_ptr()); + procs.eglDebugMessageControlKHR(egl_log, attrib.as_ptr()); } } - if unsafe { eglBindAPI(EGL_OPENGL_ES_API) } != EGL_TRUE { + if unsafe { (egl.eglBindAPI)(EGL_OPENGL_ES_API) } != EGL_TRUE { return Err(RenderError::BindFailed); } Ok(()) diff --git a/src/gfx_apis/gl/egl/context.rs b/src/gfx_apis/gl/egl/context.rs index a7ca813b..094308a2 100644 --- a/src/gfx_apis/gl/egl/context.rs +++ b/src/gfx_apis/gl/egl/context.rs @@ -4,10 +4,7 @@ use { gfx_apis::gl::{ egl::{ display::EglDisplay, - sys::{ - eglDestroyContext, eglMakeCurrent, EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE, - }, - PROCS, + sys::{EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE}, }, ext::{GlExt, EXT_CREATE_CONTEXT_ROBUSTNESS}, sys::{ @@ -32,7 +29,7 @@ pub struct EglContext { impl Drop for EglContext { fn drop(&mut self) { unsafe { - if eglDestroyContext(self.dpy.dpy, self.ctx) != EGL_TRUE { + if (self.dpy.egl.eglDestroyContext)(self.dpy.dpy, self.ctx) != EGL_TRUE { log::warn!("`eglDestroyContext` failed"); } } @@ -48,7 +45,7 @@ impl EglContext { return None; } let status = self.with_current(|| unsafe { - let status = match PROCS.glGetGraphicsResetStatusKHR() { + let status = match self.dpy.procs.glGetGraphicsResetStatusKHR() { 0 => return Ok(None), GL_GUILTY_CONTEXT_RESET_ARB => ResetStatus::Guilty, GL_INNOCENT_CONTEXT_RESET_ARB => ResetStatus::Innocent, @@ -78,7 +75,7 @@ impl EglContext { &self, f: F, ) -> Result { - if eglMakeCurrent( + if (self.dpy.egl.eglMakeCurrent)( self.dpy.dpy, EGLSurface::none(), EGLSurface::none(), @@ -90,7 +87,9 @@ impl EglContext { let prev = CURRENT; CURRENT = self.ctx; let res = f(); - if eglMakeCurrent(self.dpy.dpy, EGLSurface::none(), EGLSurface::none(), prev) == EGL_FALSE { + if (self.dpy.egl.eglMakeCurrent)(self.dpy.dpy, EGLSurface::none(), EGLSurface::none(), prev) + == EGL_FALSE + { panic!("Could not restore EGLContext"); } CURRENT = prev; diff --git a/src/gfx_apis/gl/egl/display.rs b/src/gfx_apis/gl/egl/display.rs index 795bbacb..7237dc32 100644 --- a/src/gfx_apis/gl/egl/display.rs +++ b/src/gfx_apis/gl/egl/display.rs @@ -7,8 +7,8 @@ use { context::EglContext, image::EglImage, sys::{ - eglCreateContext, eglTerminate, EGLClientBuffer, EGLConfig, EGLContext, - EGLDisplay, EGLint, EGL_CONTEXT_CLIENT_VERSION, EGL_DMA_BUF_PLANE0_FD_EXT, + EGLClientBuffer, EGLConfig, EGLContext, EGLDisplay, EGLint, + EGL_CONTEXT_CLIENT_VERSION, EGL_DMA_BUF_PLANE0_FD_EXT, EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE0_PITCH_EXT, EGL_DMA_BUF_PLANE1_FD_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT, @@ -29,9 +29,10 @@ use { KHR_IMAGE_BASE, KHR_NO_CONFIG_CONTEXT, KHR_SURFACELESS_CONTEXT, MESA_CONFIGLESS_CONTEXT, }, + proc::ExtProc, sys::{ - eglInitialize, EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, - EGL_LOSE_CONTEXT_ON_RESET_EXT, EGL_PLATFORM_GBM_KHR, + Egl, GlesV2, EGL, EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, + EGL_LOSE_CONTEXT_ON_RESET_EXT, EGL_PLATFORM_GBM_KHR, GLESV2, }, RenderError, }, @@ -57,6 +58,9 @@ pub struct EglModifier { #[derive(Debug)] pub struct EglDisplay { + pub egl: &'static Egl, + pub gles: &'static GlesV2, + pub procs: &'static ExtProc, pub exts: DisplayExt, pub formats: AHashMap, pub gbm: Rc, @@ -66,11 +70,20 @@ pub struct EglDisplay { impl EglDisplay { pub(in crate::gfx_apis::gl) fn create(drm: &Drm) -> Result, RenderError> { unsafe { + let Some(egl) = EGL.as_ref() else { + return Err(RenderError::LoadEgl); + }; + let Some(gles) = GLESV2.as_ref() else { + return Err(RenderError::LoadGlesV2); + }; + let Some(procs) = PROCS.as_ref() else { + return Err(RenderError::LoadEglProcs); + }; let gbm = match GbmDevice::new(drm) { Ok(gbm) => gbm, Err(e) => return Err(RenderError::Gbm(e)), }; - let dpy = PROCS.eglGetPlatformDisplayEXT( + let dpy = procs.eglGetPlatformDisplayEXT( EGL_PLATFORM_GBM_KHR as _, gbm.raw() as _, ptr::null(), @@ -79,6 +92,9 @@ impl EglDisplay { return Err(RenderError::GetDisplay); } let mut dpy = EglDisplay { + egl, + gles, + procs, exts: DisplayExt::none(), formats: AHashMap::new(), gbm: Rc::new(gbm), @@ -86,7 +102,7 @@ impl EglDisplay { }; let mut major = 0; let mut minor = 0; - if eglInitialize(dpy.dpy, &mut major, &mut minor) != EGL_TRUE { + if (egl.eglInitialize)(dpy.dpy, &mut major, &mut minor) != EGL_TRUE { return Err(RenderError::Initialize); } dpy.exts = get_display_ext(dpy.dpy); @@ -105,7 +121,7 @@ impl EglDisplay { if !dpy.exts.intersects(KHR_SURFACELESS_CONTEXT) { return Err(RenderError::SurfacelessContext); } - dpy.formats = query_formats(dpy.dpy)?; + dpy.formats = query_formats(procs, dpy.dpy)?; Ok(Rc::new(dpy)) } @@ -123,7 +139,7 @@ impl EglDisplay { } attrib.push(EGL_NONE); let ctx = unsafe { - eglCreateContext( + (self.egl.eglCreateContext)( self.dpy, EGLConfig::none(), EGLContext::none(), @@ -139,7 +155,7 @@ impl EglDisplay { ctx, formats: Default::default(), }; - ctx.ext = ctx.with_current(|| Ok(get_gl_ext()))?; + ctx.ext = ctx.with_current(get_gl_ext)?; if !ctx.ext.contains(GL_OES_EGL_IMAGE) { return Err(RenderError::OesEglImage); } @@ -245,7 +261,7 @@ impl EglDisplay { } attribs.push(EGL_NONE); let img = unsafe { - PROCS.eglCreateImageKHR( + self.procs.eglCreateImageKHR( self.dpy, EGLContext::none(), EGL_LINUX_DMA_BUF_EXT as _, @@ -268,22 +284,25 @@ impl EglDisplay { impl Drop for EglDisplay { fn drop(&mut self) { unsafe { - if eglTerminate(self.dpy) != EGL_TRUE { + if (self.egl.eglTerminate)(self.dpy) != EGL_TRUE { log::warn!("`eglTerminate` failed"); } } } } -unsafe fn query_formats(dpy: EGLDisplay) -> Result, RenderError> { +unsafe fn query_formats( + procs: &ExtProc, + dpy: EGLDisplay, +) -> Result, RenderError> { let mut vec = vec![]; let mut num = 0; - let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, ptr::null_mut(), &mut num); + let res = procs.eglQueryDmaBufFormatsEXT(dpy, num, ptr::null_mut(), &mut num); if res != EGL_TRUE { return Err(RenderError::QueryDmaBufFormats); } vec.reserve_exact(num as usize); - let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, vec.as_mut_ptr(), &mut num); + let res = procs.eglQueryDmaBufFormatsEXT(dpy, num, vec.as_mut_ptr(), &mut num); if res != EGL_TRUE { return Err(RenderError::QueryDmaBufFormats); } @@ -292,7 +311,7 @@ unsafe fn query_formats(dpy: EGLDisplay) -> Result, Ren let formats = formats(); for fmt in vec { if let Some(format) = formats.get(&(fmt as u32)) { - let (modifiers, external_only) = query_modifiers(dpy, fmt, format)?; + let (modifiers, external_only) = query_modifiers(procs, dpy, fmt, format)?; res.insert( format.drm, EglFormat { @@ -307,6 +326,7 @@ unsafe fn query_formats(dpy: EGLDisplay) -> Result, Ren } unsafe fn query_modifiers( + procs: &ExtProc, dpy: EGLDisplay, gl_format: EGLint, format: &'static Format, @@ -314,7 +334,7 @@ unsafe fn query_modifiers( let mut mods = vec![]; let mut ext_only = vec![]; let mut num = 0; - let res = PROCS.eglQueryDmaBufModifiersEXT( + let res = procs.eglQueryDmaBufModifiersEXT( dpy, gl_format, num, @@ -327,7 +347,7 @@ unsafe fn query_modifiers( } mods.reserve_exact(num as usize); ext_only.reserve_exact(num as usize); - let res = PROCS.eglQueryDmaBufModifiersEXT( + let res = procs.eglQueryDmaBufModifiersEXT( dpy, gl_format, num, diff --git a/src/gfx_apis/gl/egl/image.rs b/src/gfx_apis/gl/egl/image.rs index 31cad564..c85d65cb 100644 --- a/src/gfx_apis/gl/egl/image.rs +++ b/src/gfx_apis/gl/egl/image.rs @@ -3,7 +3,6 @@ use { gfx_apis::gl::egl::{ display::EglDisplay, sys::{EGLImageKHR, EGL_FALSE}, - PROCS, }, video::dmabuf::DmaBuf, }, @@ -20,7 +19,7 @@ pub struct EglImage { impl Drop for EglImage { fn drop(&mut self) { unsafe { - if PROCS.eglDestroyImageKHR(self.dpy.dpy, self.img) == EGL_FALSE { + if self.dpy.procs.eglDestroyImageKHR(self.dpy.dpy, self.img) == EGL_FALSE { log::warn!("`eglDestroyImageKHR` failed"); } } diff --git a/src/gfx_apis/gl/egl/sys.rs b/src/gfx_apis/gl/egl/sys.rs index 8282eb48..044d4de5 100644 --- a/src/gfx_apis/gl/egl/sys.rs +++ b/src/gfx_apis/gl/egl/sys.rs @@ -84,24 +84,25 @@ pub const EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT: EGLint = 0x344A; pub const EGL_IMAGE_PRESERVED_KHR: EGLint = 0x30D2; pub const EGL_LINUX_DMA_BUF_EXT: EGLint = 0x3270; -#[link(name = "EGL")] -extern "C" { - pub fn eglQueryString(dpy: EGLDisplay, name: EGLint) -> *const c::c_char; - pub fn eglGetProcAddress(procname: *const c::c_char) -> *mut u8; - pub fn eglBindAPI(api: EGLenum) -> EGLBoolean; - pub fn eglTerminate(dpy: EGLDisplay) -> EGLBoolean; - pub fn eglInitialize(dpy: EGLDisplay, major: *mut EGLint, minor: *mut EGLint) -> EGLBoolean; - pub fn eglCreateContext( - dpy: EGLDisplay, - config: EGLConfig, - share_context: EGLContext, - attrib_list: *const EGLint, - ) -> EGLContext; - pub fn eglDestroyContext(dpy: EGLDisplay, ctx: EGLContext) -> EGLBoolean; - pub fn eglMakeCurrent( - dpy: EGLDisplay, - draw: EGLSurface, - read: EGLSurface, - ctx: EGLContext, - ) -> EGLBoolean; +dynload! { + EGL: Egl from "libEGL.so" { + eglQueryString: unsafe fn(dpy: EGLDisplay, name: EGLint) -> *const c::c_char, + eglGetProcAddress: unsafe fn(procname: *const c::c_char) -> *mut u8, + eglBindAPI: unsafe fn(api: EGLenum) -> EGLBoolean, + eglTerminate: unsafe fn(dpy: EGLDisplay) -> EGLBoolean, + eglInitialize: unsafe fn(dpy: EGLDisplay, major: *mut EGLint, minor: *mut EGLint) -> EGLBoolean, + eglCreateContext: unsafe fn( + dpy: EGLDisplay, + config: EGLConfig, + share_context: EGLContext, + attrib_list: *const EGLint, + ) -> EGLContext, + eglDestroyContext: unsafe fn(dpy: EGLDisplay, ctx: EGLContext) -> EGLBoolean, + eglMakeCurrent: unsafe fn( + dpy: EGLDisplay, + draw: EGLSurface, + read: EGLSurface, + ctx: EGLContext, + ) -> EGLBoolean, + } } diff --git a/src/gfx_apis/gl/ext.rs b/src/gfx_apis/gl/ext.rs index 500aaf40..fdc23ea1 100644 --- a/src/gfx_apis/gl/ext.rs +++ b/src/gfx_apis/gl/ext.rs @@ -1,8 +1,10 @@ use { crate::{ gfx_apis::gl::{ - egl::sys::{eglQueryString, EGLDisplay, EGL_EXTENSIONS}, - gl::sys::{glGetString, GL_EXTENSIONS}, + egl::sys::{EGLDisplay, EGL_EXTENSIONS}, + gl::sys::GL_EXTENSIONS, + sys::{EGL, GLESV2}, + RenderError, }, utils::trim::AsciiTrim, }, @@ -30,7 +32,7 @@ unsafe fn get_extensions(ext: *const c::c_char) -> Option> { } unsafe fn get_dpy_extensions(dpy: EGLDisplay) -> Option> { - let ext = eglQueryString(dpy, EGL_EXTENSIONS); + let ext = (EGL.as_ref()?.eglQueryString)(dpy, EGL_EXTENSIONS); get_extensions(ext) } @@ -107,13 +109,16 @@ bitflags! { GL_OES_EGL_IMAGE_EXTERNAL = 1 << 1, } -pub fn get_gl_ext() -> GlExt { +pub fn get_gl_ext() -> Result { let map = [ ("GL_OES_EGL_image", GL_OES_EGL_IMAGE), ("GL_OES_EGL_image_external", GL_OES_EGL_IMAGE_EXTERNAL), ]; - match unsafe { get_extensions(glGetString(GL_EXTENSIONS) as _) } { - Some(exts) => get_typed_ext(&exts, GlExt::none(), &map), - _ => GlExt::none(), + let Some(gles) = GLESV2.as_ref() else { + return Err(RenderError::LoadGlesV2); + }; + match unsafe { get_extensions((gles.glGetString)(GL_EXTENSIONS) as _) } { + Some(exts) => Ok(get_typed_ext(&exts, GlExt::none(), &map)), + _ => Ok(GlExt::none()), } } diff --git a/src/gfx_apis/gl/gl/frame_buffer.rs b/src/gfx_apis/gl/gl/frame_buffer.rs index d9ef828e..737eba68 100644 --- a/src/gfx_apis/gl/gl/frame_buffer.rs +++ b/src/gfx_apis/gl/gl/frame_buffer.rs @@ -1,11 +1,7 @@ use { crate::gfx_apis::gl::{ egl::context::EglContext, - gl::{ - render_buffer::GlRenderBuffer, - sys::{glDeleteFramebuffers, GLuint}, - texture::GlTexture, - }, + gl::{render_buffer::GlRenderBuffer, sys::GLuint, texture::GlTexture}, }, std::rc::Rc, }; @@ -23,7 +19,7 @@ impl Drop for GlFrameBuffer { fn drop(&mut self) { let _ = self.ctx.with_current(|| { unsafe { - glDeleteFramebuffers(1, &self.fbo); + (self.ctx.dpy.gles.glDeleteFramebuffers)(1, &self.fbo); } Ok(()) }); diff --git a/src/gfx_apis/gl/gl/program.rs b/src/gfx_apis/gl/gl/program.rs index a2c523f8..3ab59e3d 100644 --- a/src/gfx_apis/gl/gl/program.rs +++ b/src/gfx_apis/gl/gl/program.rs @@ -3,11 +3,7 @@ use { egl::context::EglContext, gl::{ shader::GlShader, - sys::{ - glAttachShader, glCreateProgram, glDeleteProgram, glDetachShader, - glGetAttribLocation, glGetProgramiv, glGetUniformLocation, glLinkProgram, GLint, - GLuint, GL_FALSE, GL_FRAGMENT_SHADER, GL_LINK_STATUS, GL_VERTEX_SHADER, - }, + sys::{GLint, GLuint, GL_FALSE, GL_FRAGMENT_SHADER, GL_LINK_STATUS, GL_VERTEX_SHADER}, }, RenderError, }, @@ -16,7 +12,7 @@ use { }; pub struct GlProgram { - pub _ctx: Rc, + pub ctx: Rc, pub prog: GLuint, } @@ -35,18 +31,19 @@ impl GlProgram { vert: &GlShader, frag: &GlShader, ) -> Result { + let gles = vert.ctx.dpy.gles; let res = GlProgram { - _ctx: vert.ctx.clone(), - prog: glCreateProgram(), + ctx: vert.ctx.clone(), + prog: (gles.glCreateProgram)(), }; - glAttachShader(res.prog, vert.shader); - glAttachShader(res.prog, frag.shader); - glLinkProgram(res.prog); - glDetachShader(res.prog, vert.shader); - glDetachShader(res.prog, frag.shader); + (gles.glAttachShader)(res.prog, vert.shader); + (gles.glAttachShader)(res.prog, frag.shader); + (gles.glLinkProgram)(res.prog); + (gles.glDetachShader)(res.prog, vert.shader); + (gles.glDetachShader)(res.prog, frag.shader); let mut ok = 0; - glGetProgramiv(res.prog, GL_LINK_STATUS, &mut ok); + (gles.glGetProgramiv)(res.prog, GL_LINK_STATUS, &mut ok); if ok == GL_FALSE as GLint { return Err(RenderError::ProgramLink); } @@ -55,19 +52,19 @@ impl GlProgram { } pub unsafe fn get_uniform_location(&self, name: &Ustr) -> GLint { - glGetUniformLocation(self.prog, name.as_ptr() as _) + (self.ctx.dpy.gles.glGetUniformLocation)(self.prog, name.as_ptr() as _) } pub unsafe fn get_attrib_location(&self, name: &Ustr) -> GLint { - glGetAttribLocation(self.prog, name.as_ptr() as _) + (self.ctx.dpy.gles.glGetAttribLocation)(self.prog, name.as_ptr() as _) } } impl Drop for GlProgram { fn drop(&mut self) { unsafe { - let _ = self._ctx.with_current(|| { - glDeleteProgram(self.prog); + let _ = self.ctx.with_current(|| { + (self.ctx.dpy.gles.glDeleteProgram)(self.prog); Ok(()) }); } diff --git a/src/gfx_apis/gl/gl/render_buffer.rs b/src/gfx_apis/gl/gl/render_buffer.rs index 32dad288..ed170326 100644 --- a/src/gfx_apis/gl/gl/render_buffer.rs +++ b/src/gfx_apis/gl/gl/render_buffer.rs @@ -1,12 +1,10 @@ use { crate::gfx_apis::gl::{ - egl::{context::EglContext, image::EglImage, PROCS}, + egl::{context::EglContext, image::EglImage}, gl::{ frame_buffer::GlFrameBuffer, sys::{ - glBindFramebuffer, glBindRenderbuffer, glCheckFramebufferStatus, - glDeleteRenderbuffers, glFramebufferRenderbuffer, glGenFramebuffers, - glGenRenderbuffers, GLeglImageOES, GLuint, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER, + GLeglImageOES, GLuint, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, GL_RENDERBUFFER, }, }, @@ -29,11 +27,14 @@ impl GlRenderBuffer { if img.external_only { return Err(RenderError::ExternalOnly); } + let gles = ctx.dpy.gles; let mut rbo = 0; - glGenRenderbuffers(1, &mut rbo); - glBindRenderbuffer(GL_RENDERBUFFER, rbo); - PROCS.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, GLeglImageOES(img.img.0)); - glBindRenderbuffer(GL_RENDERBUFFER, 0); + (gles.glGenRenderbuffers)(1, &mut rbo); + (gles.glBindRenderbuffer)(GL_RENDERBUFFER, rbo); + ctx.dpy + .procs + .glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, GLeglImageOES(img.img.0)); + (gles.glBindRenderbuffer)(GL_RENDERBUFFER, 0); Ok(Rc::new(GlRenderBuffer { img: img.clone(), ctx: ctx.clone(), @@ -44,17 +45,18 @@ impl GlRenderBuffer { pub(in crate::gfx_apis::gl) unsafe fn create_framebuffer( self: &Rc, ) -> Result { + let gles = self.ctx.dpy.gles; let mut fbo = 0; - glGenFramebuffers(1, &mut fbo); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferRenderbuffer( + (gles.glGenFramebuffers)(1, &mut fbo); + (gles.glBindFramebuffer)(GL_FRAMEBUFFER, fbo); + (gles.glFramebufferRenderbuffer)( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.rbo, ); - let status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + let status = (gles.glCheckFramebufferStatus)(GL_FRAMEBUFFER); + (gles.glBindFramebuffer)(GL_FRAMEBUFFER, 0); let fb = GlFrameBuffer { rb: self.clone(), _tex: None, @@ -74,7 +76,7 @@ impl Drop for GlRenderBuffer { fn drop(&mut self) { let _ = self.ctx.with_current(|| { unsafe { - glDeleteRenderbuffers(1, &self.rbo); + (self.ctx.dpy.gles.glDeleteRenderbuffers)(1, &self.rbo); } Ok(()) }); diff --git a/src/gfx_apis/gl/gl/shader.rs b/src/gfx_apis/gl/gl/shader.rs index 40386ea1..9a13de48 100644 --- a/src/gfx_apis/gl/gl/shader.rs +++ b/src/gfx_apis/gl/gl/shader.rs @@ -1,10 +1,7 @@ use { crate::gfx_apis::gl::{ egl::context::EglContext, - gl::sys::{ - glCompileShader, glCreateShader, glDeleteShader, glGetShaderiv, glShaderSource, GLenum, - GLuint, GL_COMPILE_STATUS, GL_FALSE, - }, + gl::sys::{GLenum, GLuint, GL_COMPILE_STATUS, GL_FALSE}, sys::GLint, RenderError, }, @@ -22,17 +19,18 @@ impl GlShader { ty: GLenum, src: &str, ) -> Result { - let shader = glCreateShader(ty); + let gles = ctx.dpy.gles; + let shader = (gles.glCreateShader)(ty); let res = GlShader { ctx: ctx.clone(), shader, }; let len = src.len() as _; - glShaderSource(shader, 1, &(src.as_ptr() as _), &len); - glCompileShader(shader); + (gles.glShaderSource)(shader, 1, &(src.as_ptr() as _), &len); + (gles.glCompileShader)(shader); let mut ok = 0; - glGetShaderiv(shader, GL_COMPILE_STATUS, &mut ok); + (gles.glGetShaderiv)(shader, GL_COMPILE_STATUS, &mut ok); if ok == GL_FALSE as GLint { return Err(RenderError::ShaderCompileFailed); } @@ -43,7 +41,7 @@ impl GlShader { impl Drop for GlShader { fn drop(&mut self) { let _ = self.ctx.with_current(|| unsafe { - glDeleteShader(self.shader); + (self.ctx.dpy.gles.glDeleteShader)(self.shader); Ok(()) }); } diff --git a/src/gfx_apis/gl/gl/sys.rs b/src/gfx_apis/gl/gl/sys.rs index 54bf0754..f1fcbb40 100644 --- a/src/gfx_apis/gl/gl/sys.rs +++ b/src/gfx_apis/gl/gl/sys.rs @@ -45,107 +45,105 @@ pub const GL_BLEND: GLenum = 0x0BE2; pub const GL_ONE: GLenum = 1; pub const GL_ONE_MINUS_SRC_ALPHA: GLenum = 0x0303; -#[link(name = "GLESv2")] -extern "C" { - pub fn glGetString(name: GLenum) -> *const u8; - pub fn glGenRenderbuffers(n: GLsizei, renderbuffers: *mut GLuint); - pub fn glDeleteRenderbuffers(n: GLsizei, renderbuffers: *const GLuint); - pub fn glBindRenderbuffer(target: GLenum, renderbuffer: GLuint); - pub fn glGenFramebuffers(n: GLsizei, framebuffers: *mut GLuint); - pub fn glDeleteFramebuffers(n: GLsizei, framebuffers: *const GLuint); - pub fn glBindFramebuffer(target: GLenum, framebuffer: GLuint); - pub fn glFramebufferRenderbuffer( - target: GLenum, - attachment: GLenum, - renderbuffertarget: GLenum, - renderbuffer: GLuint, - ); - #[allow(dead_code)] - pub fn glFramebufferTexture2D( - target: GLenum, - attachment: GLenum, - textarget: GLenum, - texture: GLenum, - level: GLint, - ); - pub fn glCheckFramebufferStatus(target: GLenum) -> GLenum; - pub fn glClear(mask: GLbitfield); - pub fn glBlendFunc(sfactor: GLenum, dfactor: GLenum); - pub fn glClearColor(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat); - #[allow(dead_code)] - pub fn glFlush(); +dynload! { + GLESV2: GlesV2 from "libGLESv2.so" { + glGetString: unsafe fn(name: GLenum) -> *const u8, + glGenRenderbuffers: unsafe fn(n: GLsizei, renderbuffers: *mut GLuint), + glDeleteRenderbuffers: unsafe fn(n: GLsizei, renderbuffers: *const GLuint), + glBindRenderbuffer: unsafe fn(target: GLenum, renderbuffer: GLuint), + glGenFramebuffers: unsafe fn(n: GLsizei, framebuffers: *mut GLuint), + glDeleteFramebuffers: unsafe fn(n: GLsizei, framebuffers: *const GLuint), + glBindFramebuffer: unsafe fn(target: GLenum, framebuffer: GLuint), + glFramebufferRenderbuffer: unsafe fn( + target: GLenum, + attachment: GLenum, + renderbuffertarget: GLenum, + renderbuffer: GLuint, + ), + glFramebufferTexture2D: unsafe fn( + target: GLenum, + attachment: GLenum, + textarget: GLenum, + texture: GLenum, + level: GLint, + ), + glCheckFramebufferStatus: unsafe fn(target: GLenum) -> GLenum, + glClear: unsafe fn(mask: GLbitfield), + glBlendFunc: unsafe fn(sfactor: GLenum, dfactor: GLenum), + glClearColor: unsafe fn(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat), + glFlush: unsafe fn(), - pub fn glReadnPixels( - x: GLint, - y: GLint, - width: GLsizei, - height: GLsizei, - format: GLenum, - ty: GLenum, - buf_size: GLsizei, - data: *mut c::c_void, - ); + glReadnPixels: unsafe fn( + x: GLint, + y: GLint, + width: GLsizei, + height: GLsizei, + format: GLenum, + ty: GLenum, + buf_size: GLsizei, + data: *mut c::c_void, + ), - pub fn glGenTextures(n: GLsizei, textures: *mut GLuint); - pub fn glDeleteTextures(n: GLsizei, textures: *const GLuint); - pub fn glBindTexture(target: GLenum, texture: GLuint); - pub fn glTexParameteri(target: GLenum, pname: GLenum, param: GLint); + glGenTextures: unsafe fn(n: GLsizei, textures: *mut GLuint), + glDeleteTextures: unsafe fn(n: GLsizei, textures: *const GLuint), + glBindTexture: unsafe fn(target: GLenum, texture: GLuint), + glTexParameteri: unsafe fn(target: GLenum, pname: GLenum, param: GLint), - pub fn glPixelStorei(pname: GLenum, param: GLint); + glPixelStorei: unsafe fn(pname: GLenum, param: GLint), - pub fn glTexImage2D( - target: GLenum, - level: GLint, - internalformat: GLint, - width: GLsizei, - height: GLsizei, - border: GLint, - format: GLenum, - ty: GLenum, - pixels: *const c::c_void, - ); + glTexImage2D: unsafe fn( + target: GLenum, + level: GLint, + internalformat: GLint, + width: GLsizei, + height: GLsizei, + border: GLint, + format: GLenum, + ty: GLenum, + pixels: *const c::c_void, + ), - pub fn glEnable(cap: GLenum); - pub fn glDisable(cap: GLenum); - pub fn glViewport(x: GLint, y: GLint, width: GLsizei, height: GLsizei); + glEnable: unsafe fn(cap: GLenum), + glDisable: unsafe fn(cap: GLenum), + glViewport: unsafe fn(x: GLint, y: GLint, width: GLsizei, height: GLsizei), - pub fn glCreateShader(ty: GLenum) -> GLuint; - pub fn glDeleteShader(shader: GLuint); - pub fn glShaderSource( - shader: GLuint, - count: GLsizei, - string: *const *const GLchar, - length: *const GLint, - ); - pub fn glCompileShader(shader: GLuint); - pub fn glGetShaderiv(shader: GLuint, pname: GLenum, params: *mut GLint); + glCreateShader: unsafe fn(ty: GLenum) -> GLuint, + glDeleteShader: unsafe fn(shader: GLuint), + glShaderSource: unsafe fn( + shader: GLuint, + count: GLsizei, + string: *const *const GLchar, + length: *const GLint, + ), + glCompileShader: unsafe fn(shader: GLuint), + glGetShaderiv: unsafe fn(shader: GLuint, pname: GLenum, params: *mut GLint), - pub fn glCreateProgram() -> GLuint; - pub fn glDeleteProgram(prog: GLuint); - pub fn glAttachShader(prog: GLuint, shader: GLuint); - pub fn glDetachShader(prog: GLuint, shader: GLuint); - pub fn glLinkProgram(prog: GLuint); - pub fn glGetProgramiv(program: GLuint, pname: GLenum, params: *mut GLint); - pub fn glUseProgram(program: GLuint); + glCreateProgram: unsafe fn() -> GLuint, + glDeleteProgram: unsafe fn(prog: GLuint), + glAttachShader: unsafe fn(prog: GLuint, shader: GLuint), + glDetachShader: unsafe fn(prog: GLuint, shader: GLuint), + glLinkProgram: unsafe fn(prog: GLuint), + glGetProgramiv: unsafe fn(program: GLuint, pname: GLenum, params: *mut GLint), + glUseProgram: unsafe fn(program: GLuint), - pub fn glGetUniformLocation(prog: GLuint, name: *const GLchar) -> GLint; - pub fn glGetAttribLocation(prog: GLuint, name: *const GLchar) -> GLint; - pub fn glUniform1i(location: GLint, v0: GLint); - #[allow(dead_code)] - pub fn glUniform1f(location: GLint, v0: GLfloat); - pub fn glUniform4f(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat, v3: GLfloat); - pub fn glVertexAttribPointer( - index: GLuint, - size: GLint, - ty: GLenum, - normalized: GLboolean, - stride: GLsizei, - pointer: *const u8, - ); + glGetUniformLocation: unsafe fn(prog: GLuint, name: *const GLchar) -> GLint, + glGetAttribLocation: unsafe fn(prog: GLuint, name: *const GLchar) -> GLint, + glUniform1i: unsafe fn(location: GLint, v0: GLint), + glUniform1f: unsafe fn(location: GLint, v0: GLfloat), + glUniform4f: unsafe fn(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat, v3: GLfloat), + glVertexAttribPointer: unsafe fn( + index: GLuint, + size: GLint, + ty: GLenum, + normalized: GLboolean, + stride: GLsizei, + pointer: *const u8, + ), - pub fn glActiveTexture(texture: GLuint); + glActiveTexture: unsafe fn(texture: GLuint), - pub fn glEnableVertexAttribArray(idx: GLuint); - pub fn glDisableVertexAttribArray(idx: GLuint); - pub fn glDrawArrays(mode: GLenum, first: GLint, count: GLsizei); + glEnableVertexAttribArray: unsafe fn(idx: GLuint), + glDisableVertexAttribArray: unsafe fn(idx: GLuint), + glDrawArrays: unsafe fn(mode: GLenum, first: GLint, count: GLsizei), + } } diff --git a/src/gfx_apis/gl/gl/texture.rs b/src/gfx_apis/gl/gl/texture.rs index 9397578d..fa006579 100644 --- a/src/gfx_apis/gl/gl/texture.rs +++ b/src/gfx_apis/gl/gl/texture.rs @@ -2,11 +2,10 @@ use { crate::{ format::Format, gfx_apis::gl::{ - egl::{context::EglContext, image::EglImage, PROCS}, + egl::{context::EglContext, image::EglImage}, ext::GL_OES_EGL_IMAGE_EXTERNAL, gl::sys::{ - glBindTexture, glDeleteTextures, glGenTextures, glPixelStorei, glTexImage2D, - glTexParameteri, GLint, GLuint, GL_CLAMP_TO_EDGE, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, + GLint, GLuint, GL_CLAMP_TO_EDGE, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_UNPACK_ROW_LENGTH_EXT, }, sys::{GLeglImageOES, GLenum, GL_TEXTURE_EXTERNAL_OES}, @@ -41,15 +40,18 @@ impl GlTexture { if !ctx.ext.contains(GL_OES_EGL_IMAGE_EXTERNAL) { return Err(RenderError::ExternalUnsupported); } + let gles = ctx.dpy.gles; let target = image_target(img.external_only); let tex = ctx.with_current(|| unsafe { let mut tex = 0; - glGenTextures(1, &mut tex); - glBindTexture(target, tex); - glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - PROCS.glEGLImageTargetTexture2DOES(target, GLeglImageOES(img.img.0)); - glBindTexture(target, 0); + (gles.glGenTextures)(1, &mut tex); + (gles.glBindTexture)(target, tex); + (gles.glTexParameteri)(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + (gles.glTexParameteri)(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + ctx.dpy + .procs + .glEGLImageTargetTexture2DOES(target, GLeglImageOES(img.img.0)); + (gles.glBindTexture)(target, 0); Ok(tex) })?; Ok(GlTexture { @@ -74,14 +76,15 @@ impl GlTexture { if (stride * height) as usize > data.len() { return Err(RenderError::SmallImageBuffer); } + let gles = ctx.dpy.gles; let tex = ctx.with_current(|| unsafe { let mut tex = 0; - glGenTextures(1, &mut tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint); - glTexImage2D( + (gles.glGenTextures)(1, &mut tex); + (gles.glBindTexture)(GL_TEXTURE_2D, tex); + (gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + (gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + (gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint); + (gles.glTexImage2D)( GL_TEXTURE_2D, 0, format.gl_format, @@ -92,8 +95,8 @@ impl GlTexture { format.gl_type as _, data.as_ptr() as _, ); - glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); - glBindTexture(GL_TEXTURE_2D, 0); + (gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, 0); + (gles.glBindTexture)(GL_TEXTURE_2D, 0); Ok(tex) })?; Ok(GlTexture { @@ -111,7 +114,7 @@ impl GlTexture { impl Drop for GlTexture { fn drop(&mut self) { let _ = self.ctx.with_current(|| unsafe { - glDeleteTextures(1, &self.tex); + (self.ctx.dpy.gles.glDeleteTextures)(1, &self.tex); Ok(()) }); } diff --git a/src/gfx_apis/gl/renderer/framebuffer.rs b/src/gfx_apis/gl/renderer/framebuffer.rs index e1cd262c..3be56f86 100644 --- a/src/gfx_apis/gl/renderer/framebuffer.rs +++ b/src/gfx_apis/gl/renderer/framebuffer.rs @@ -5,14 +5,11 @@ use { gfx_apis::gl::{ gl::{ frame_buffer::GlFrameBuffer, - sys::{ - glBindFramebuffer, glClear, glClearColor, glViewport, GL_COLOR_BUFFER_BIT, - GL_FRAMEBUFFER, - }, + sys::{GL_COLOR_BUFFER_BIT, GL_FRAMEBUFFER}, }, renderer::context::GlRenderContext, run_ops, - sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, + sys::{GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, }, theme::Color, }, @@ -46,12 +43,13 @@ impl Framebuffer { format: &Format, shm: &[Cell], ) { + let gles = self.ctx.ctx.dpy.gles; let y = self.gl.height - y - height; let _ = self.ctx.ctx.with_current(|| { unsafe { - glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); - glViewport(0, 0, self.gl.width, self.gl.height); - glReadnPixels( + (gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo); + (gles.glViewport)(0, 0, self.gl.width, self.gl.height); + (gles.glReadnPixels)( x, y, width, @@ -67,19 +65,20 @@ impl Framebuffer { } pub fn render(&self, ops: Vec, clear: Option<&Color>) { + let gles = self.ctx.ctx.dpy.gles; let _ = self.ctx.ctx.with_current(|| { unsafe { - glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); - glViewport(0, 0, self.gl.width, self.gl.height); + (gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo); + (gles.glViewport)(0, 0, self.gl.width, self.gl.height); if let Some(c) = clear { - glClearColor(c.r, c.g, c.b, c.a); - glClear(GL_COLOR_BUFFER_BIT); + (gles.glClearColor)(c.r, c.g, c.b, c.a); + (gles.glClear)(GL_COLOR_BUFFER_BIT); } - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + (gles.glBlendFunc)(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } run_ops(self, &ops); unsafe { - glFlush(); + (gles.glFlush)(); } Ok(()) });