render: load libEGL and libGLESv2 at runtime
This commit is contained in:
parent
aa9ca29996
commit
0c82f02b26
15 changed files with 337 additions and 259 deletions
|
|
@ -97,16 +97,17 @@ fn write_egl_procs<W: Write>(f: &mut W) -> anyhow::Result<()> {
|
||||||
writeln!(f, "unsafe impl Send for ExtProc {{ }}")?;
|
writeln!(f, "unsafe impl Send for ExtProc {{ }}")?;
|
||||||
writeln!(f)?;
|
writeln!(f)?;
|
||||||
writeln!(f, "impl ExtProc {{")?;
|
writeln!(f, "impl ExtProc {{")?;
|
||||||
writeln!(f, " pub fn load() -> Self {{")?;
|
writeln!(f, " pub fn load() -> Option<Self> {{")?;
|
||||||
writeln!(f, " Self {{")?;
|
writeln!(f, " let egl = EGL.as_ref()?;")?;
|
||||||
|
writeln!(f, " Some(Self {{")?;
|
||||||
for (name, _, _) in map.iter().copied() {
|
for (name, _, _) in map.iter().copied() {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
" {}: unsafe {{ eglGetProcAddress(\"{}\\0\".as_ptr() as _) }},",
|
" {}: unsafe {{ (egl.eglGetProcAddress)(\"{}\\0\".as_ptr() as _) }},",
|
||||||
name, name
|
name, name
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
writeln!(f, " }}")?;
|
writeln!(f, " }})")?;
|
||||||
writeln!(f, " }}")?;
|
writeln!(f, " }}")?;
|
||||||
for (name, ret, args) in map.iter().copied() {
|
for (name, ret, args) in map.iter().copied() {
|
||||||
let mut args_names = String::new();
|
let mut args_names = String::new();
|
||||||
|
|
|
||||||
|
|
@ -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<Option<$container>> = 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 {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
gfx_api::{
|
gfx_api::{
|
||||||
|
|
@ -27,10 +74,8 @@ use {
|
||||||
gl::texture::image_target,
|
gl::texture::image_target,
|
||||||
renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture},
|
renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture},
|
||||||
sys::{
|
sys::{
|
||||||
glActiveTexture, glBindTexture, glDisable, glDisableVertexAttribArray,
|
GL_BLEND, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER,
|
||||||
glDrawArrays, glEnable, glEnableVertexAttribArray, glTexParameteri, glUniform1i,
|
GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
||||||
glUniform4f, glUseProgram, glVertexAttribPointer, GL_BLEND, GL_FALSE, GL_FLOAT,
|
|
||||||
GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
theme::Color,
|
theme::Color,
|
||||||
|
|
@ -69,6 +114,12 @@ pub(super) fn create_gfx_context(drm: &Drm) -> Result<Rc<dyn GfxContext>, GfxErr
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
enum RenderError {
|
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`")]
|
#[error("EGL library does not support `EGL_EXT_platform_base`")]
|
||||||
ExtPlatformBase,
|
ExtPlatformBase,
|
||||||
#[error("Could not compile a shader")]
|
#[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) {
|
fn fill_boxes3(ctx: &GlRenderContext, boxes: &[f32], color: &Color) {
|
||||||
|
let gles = ctx.ctx.dpy.gles;
|
||||||
unsafe {
|
unsafe {
|
||||||
glUseProgram(ctx.fill_prog.prog);
|
(gles.glUseProgram)(ctx.fill_prog.prog);
|
||||||
glUniform4f(ctx.fill_prog_color, color.r, color.g, color.b, color.a);
|
(gles.glUniform4f)(ctx.fill_prog_color, color.r, color.g, color.b, color.a);
|
||||||
glVertexAttribPointer(
|
(gles.glVertexAttribPointer)(
|
||||||
ctx.fill_prog_pos as _,
|
ctx.fill_prog_pos as _,
|
||||||
2,
|
2,
|
||||||
GL_FLOAT,
|
GL_FLOAT,
|
||||||
|
|
@ -232,9 +284,9 @@ fn fill_boxes3(ctx: &GlRenderContext, boxes: &[f32], color: &Color) {
|
||||||
0,
|
0,
|
||||||
boxes.as_ptr() as _,
|
boxes.as_ptr() as _,
|
||||||
);
|
);
|
||||||
glEnableVertexAttribArray(ctx.fill_prog_pos as _);
|
(gles.glEnableVertexAttribArray)(ctx.fill_prog_pos as _);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, (boxes.len() / 2) as _);
|
(gles.glDrawArrays)(GL_TRIANGLES, 0, (boxes.len() / 2) as _);
|
||||||
glDisableVertexAttribArray(ctx.fill_prog_pos as _);
|
(gles.glDisableVertexAttribArray)(ctx.fill_prog_pos as _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,13 +300,14 @@ fn render_texture(
|
||||||
src: &BufferPoints,
|
src: &BufferPoints,
|
||||||
) {
|
) {
|
||||||
assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx));
|
assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx));
|
||||||
|
let gles = ctx.ctx.dpy.gles;
|
||||||
unsafe {
|
unsafe {
|
||||||
glActiveTexture(GL_TEXTURE0);
|
(gles.glActiveTexture)(GL_TEXTURE0);
|
||||||
|
|
||||||
let target = image_target(texture.gl.external_only);
|
let target = image_target(texture.gl.external_only);
|
||||||
|
|
||||||
glBindTexture(target, texture.gl.tex);
|
(gles.glBindTexture)(target, texture.gl.tex);
|
||||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
(gles.glTexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
let progs = match texture.gl.external_only {
|
let progs = match texture.gl.external_only {
|
||||||
true => match &ctx.tex_external {
|
true => match &ctx.tex_external {
|
||||||
|
|
@ -268,18 +321,18 @@ fn render_texture(
|
||||||
};
|
};
|
||||||
let prog = match texture.gl.format.has_alpha {
|
let prog = match texture.gl.format.has_alpha {
|
||||||
true => {
|
true => {
|
||||||
glEnable(GL_BLEND);
|
(gles.glEnable)(GL_BLEND);
|
||||||
&progs.alpha
|
&progs.alpha
|
||||||
}
|
}
|
||||||
false => {
|
false => {
|
||||||
glDisable(GL_BLEND);
|
(gles.glDisable)(GL_BLEND);
|
||||||
&progs.solid
|
&progs.solid
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
glUseProgram(prog.prog.prog);
|
(gles.glUseProgram)(prog.prog.prog);
|
||||||
|
|
||||||
glUniform1i(prog.tex, 0);
|
(gles.glUniform1i)(prog.tex, 0);
|
||||||
|
|
||||||
let texcoord = [
|
let texcoord = [
|
||||||
src.top_right.x,
|
src.top_right.x,
|
||||||
|
|
@ -299,7 +352,7 @@ fn render_texture(
|
||||||
x1, y2, // bottom left
|
x1, y2, // bottom left
|
||||||
];
|
];
|
||||||
|
|
||||||
glVertexAttribPointer(
|
(gles.glVertexAttribPointer)(
|
||||||
prog.texcoord as _,
|
prog.texcoord as _,
|
||||||
2,
|
2,
|
||||||
GL_FLOAT,
|
GL_FLOAT,
|
||||||
|
|
@ -307,17 +360,17 @@ fn render_texture(
|
||||||
0,
|
0,
|
||||||
texcoord.as_ptr() as _,
|
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 _);
|
(gles.glEnableVertexAttribArray)(prog.texcoord as _);
|
||||||
glEnableVertexAttribArray(prog.pos as _);
|
(gles.glEnableVertexAttribArray)(prog.pos as _);
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
(gles.glDrawArrays)(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
glDisableVertexAttribArray(prog.texcoord as _);
|
(gles.glDisableVertexAttribArray)(prog.texcoord as _);
|
||||||
glDisableVertexAttribArray(prog.pos as _);
|
(gles.glDisableVertexAttribArray)(prog.pos as _);
|
||||||
|
|
||||||
glBindTexture(target, 0);
|
(gles.glBindTexture)(target, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
use {
|
use {
|
||||||
crate::gfx_apis::gl::{
|
crate::gfx_apis::gl::{
|
||||||
egl::sys::{
|
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_DEBUG_MSG_ERROR_KHR, EGL_DEBUG_MSG_INFO_KHR, EGL_DEBUG_MSG_WARN_KHR, EGL_NONE,
|
||||||
EGL_OPENGL_ES_API, EGL_TRUE,
|
EGL_OPENGL_ES_API, EGL_TRUE,
|
||||||
},
|
},
|
||||||
ext::{get_client_ext, ClientExt, EXT_PLATFORM_BASE, KHR_DEBUG, KHR_PLATFORM_GBM},
|
ext::{get_client_ext, ClientExt, EXT_PLATFORM_BASE, KHR_DEBUG, KHR_PLATFORM_GBM},
|
||||||
proc::ExtProc,
|
proc::ExtProc,
|
||||||
|
sys::EGL,
|
||||||
RenderError,
|
RenderError,
|
||||||
},
|
},
|
||||||
bstr::ByteSlice,
|
bstr::ByteSlice,
|
||||||
|
|
@ -27,11 +28,17 @@ pub mod display;
|
||||||
pub mod image;
|
pub mod image;
|
||||||
pub mod sys;
|
pub mod sys;
|
||||||
|
|
||||||
pub(crate) static PROCS: Lazy<ExtProc> = Lazy::new(ExtProc::load);
|
pub(crate) static PROCS: Lazy<Option<ExtProc>> = Lazy::new(ExtProc::load);
|
||||||
|
|
||||||
pub(crate) static EXTS: Lazy<ClientExt> = Lazy::new(get_client_ext);
|
pub(crate) static EXTS: Lazy<ClientExt> = Lazy::new(get_client_ext);
|
||||||
|
|
||||||
pub(in crate::gfx_apis::gl) fn init() -> Result<(), RenderError> {
|
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) {
|
if !EXTS.contains(EXT_PLATFORM_BASE) {
|
||||||
return Err(RenderError::ExtPlatformBase);
|
return Err(RenderError::ExtPlatformBase);
|
||||||
}
|
}
|
||||||
|
|
@ -51,10 +58,10 @@ pub(in crate::gfx_apis::gl) fn init() -> Result<(), RenderError> {
|
||||||
EGL_NONE as _,
|
EGL_NONE as _,
|
||||||
];
|
];
|
||||||
unsafe {
|
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);
|
return Err(RenderError::BindFailed);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,7 @@ use {
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
egl::{
|
egl::{
|
||||||
display::EglDisplay,
|
display::EglDisplay,
|
||||||
sys::{
|
sys::{EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE},
|
||||||
eglDestroyContext, eglMakeCurrent, EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE,
|
|
||||||
},
|
|
||||||
PROCS,
|
|
||||||
},
|
},
|
||||||
ext::{GlExt, EXT_CREATE_CONTEXT_ROBUSTNESS},
|
ext::{GlExt, EXT_CREATE_CONTEXT_ROBUSTNESS},
|
||||||
sys::{
|
sys::{
|
||||||
|
|
@ -32,7 +29,7 @@ pub struct EglContext {
|
||||||
impl Drop for EglContext {
|
impl Drop for EglContext {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
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");
|
log::warn!("`eglDestroyContext` failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -48,7 +45,7 @@ impl EglContext {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let status = self.with_current(|| unsafe {
|
let status = self.with_current(|| unsafe {
|
||||||
let status = match PROCS.glGetGraphicsResetStatusKHR() {
|
let status = match self.dpy.procs.glGetGraphicsResetStatusKHR() {
|
||||||
0 => return Ok(None),
|
0 => return Ok(None),
|
||||||
GL_GUILTY_CONTEXT_RESET_ARB => ResetStatus::Guilty,
|
GL_GUILTY_CONTEXT_RESET_ARB => ResetStatus::Guilty,
|
||||||
GL_INNOCENT_CONTEXT_RESET_ARB => ResetStatus::Innocent,
|
GL_INNOCENT_CONTEXT_RESET_ARB => ResetStatus::Innocent,
|
||||||
|
|
@ -78,7 +75,7 @@ impl EglContext {
|
||||||
&self,
|
&self,
|
||||||
f: F,
|
f: F,
|
||||||
) -> Result<T, RenderError> {
|
) -> Result<T, RenderError> {
|
||||||
if eglMakeCurrent(
|
if (self.dpy.egl.eglMakeCurrent)(
|
||||||
self.dpy.dpy,
|
self.dpy.dpy,
|
||||||
EGLSurface::none(),
|
EGLSurface::none(),
|
||||||
EGLSurface::none(),
|
EGLSurface::none(),
|
||||||
|
|
@ -90,7 +87,9 @@ impl EglContext {
|
||||||
let prev = CURRENT;
|
let prev = CURRENT;
|
||||||
CURRENT = self.ctx;
|
CURRENT = self.ctx;
|
||||||
let res = f();
|
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");
|
panic!("Could not restore EGLContext");
|
||||||
}
|
}
|
||||||
CURRENT = prev;
|
CURRENT = prev;
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ use {
|
||||||
context::EglContext,
|
context::EglContext,
|
||||||
image::EglImage,
|
image::EglImage,
|
||||||
sys::{
|
sys::{
|
||||||
eglCreateContext, eglTerminate, EGLClientBuffer, EGLConfig, EGLContext,
|
EGLClientBuffer, EGLConfig, EGLContext, EGLDisplay, EGLint,
|
||||||
EGLDisplay, EGLint, EGL_CONTEXT_CLIENT_VERSION, EGL_DMA_BUF_PLANE0_FD_EXT,
|
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_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_PLANE0_OFFSET_EXT, EGL_DMA_BUF_PLANE0_PITCH_EXT,
|
||||||
EGL_DMA_BUF_PLANE1_FD_EXT, EGL_DMA_BUF_PLANE1_MODIFIER_HI_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,
|
KHR_IMAGE_BASE, KHR_NO_CONFIG_CONTEXT, KHR_SURFACELESS_CONTEXT,
|
||||||
MESA_CONFIGLESS_CONTEXT,
|
MESA_CONFIGLESS_CONTEXT,
|
||||||
},
|
},
|
||||||
|
proc::ExtProc,
|
||||||
sys::{
|
sys::{
|
||||||
eglInitialize, EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
|
Egl, GlesV2, EGL, EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
|
||||||
EGL_LOSE_CONTEXT_ON_RESET_EXT, EGL_PLATFORM_GBM_KHR,
|
EGL_LOSE_CONTEXT_ON_RESET_EXT, EGL_PLATFORM_GBM_KHR, GLESV2,
|
||||||
},
|
},
|
||||||
RenderError,
|
RenderError,
|
||||||
},
|
},
|
||||||
|
|
@ -57,6 +58,9 @@ pub struct EglModifier {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EglDisplay {
|
pub struct EglDisplay {
|
||||||
|
pub egl: &'static Egl,
|
||||||
|
pub gles: &'static GlesV2,
|
||||||
|
pub procs: &'static ExtProc,
|
||||||
pub exts: DisplayExt,
|
pub exts: DisplayExt,
|
||||||
pub formats: AHashMap<u32, EglFormat>,
|
pub formats: AHashMap<u32, EglFormat>,
|
||||||
pub gbm: Rc<GbmDevice>,
|
pub gbm: Rc<GbmDevice>,
|
||||||
|
|
@ -66,11 +70,20 @@ pub struct EglDisplay {
|
||||||
impl EglDisplay {
|
impl EglDisplay {
|
||||||
pub(in crate::gfx_apis::gl) fn create(drm: &Drm) -> Result<Rc<Self>, RenderError> {
|
pub(in crate::gfx_apis::gl) fn create(drm: &Drm) -> Result<Rc<Self>, RenderError> {
|
||||||
unsafe {
|
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) {
|
let gbm = match GbmDevice::new(drm) {
|
||||||
Ok(gbm) => gbm,
|
Ok(gbm) => gbm,
|
||||||
Err(e) => return Err(RenderError::Gbm(e)),
|
Err(e) => return Err(RenderError::Gbm(e)),
|
||||||
};
|
};
|
||||||
let dpy = PROCS.eglGetPlatformDisplayEXT(
|
let dpy = procs.eglGetPlatformDisplayEXT(
|
||||||
EGL_PLATFORM_GBM_KHR as _,
|
EGL_PLATFORM_GBM_KHR as _,
|
||||||
gbm.raw() as _,
|
gbm.raw() as _,
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
|
|
@ -79,6 +92,9 @@ impl EglDisplay {
|
||||||
return Err(RenderError::GetDisplay);
|
return Err(RenderError::GetDisplay);
|
||||||
}
|
}
|
||||||
let mut dpy = EglDisplay {
|
let mut dpy = EglDisplay {
|
||||||
|
egl,
|
||||||
|
gles,
|
||||||
|
procs,
|
||||||
exts: DisplayExt::none(),
|
exts: DisplayExt::none(),
|
||||||
formats: AHashMap::new(),
|
formats: AHashMap::new(),
|
||||||
gbm: Rc::new(gbm),
|
gbm: Rc::new(gbm),
|
||||||
|
|
@ -86,7 +102,7 @@ impl EglDisplay {
|
||||||
};
|
};
|
||||||
let mut major = 0;
|
let mut major = 0;
|
||||||
let mut minor = 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);
|
return Err(RenderError::Initialize);
|
||||||
}
|
}
|
||||||
dpy.exts = get_display_ext(dpy.dpy);
|
dpy.exts = get_display_ext(dpy.dpy);
|
||||||
|
|
@ -105,7 +121,7 @@ impl EglDisplay {
|
||||||
if !dpy.exts.intersects(KHR_SURFACELESS_CONTEXT) {
|
if !dpy.exts.intersects(KHR_SURFACELESS_CONTEXT) {
|
||||||
return Err(RenderError::SurfacelessContext);
|
return Err(RenderError::SurfacelessContext);
|
||||||
}
|
}
|
||||||
dpy.formats = query_formats(dpy.dpy)?;
|
dpy.formats = query_formats(procs, dpy.dpy)?;
|
||||||
|
|
||||||
Ok(Rc::new(dpy))
|
Ok(Rc::new(dpy))
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +139,7 @@ impl EglDisplay {
|
||||||
}
|
}
|
||||||
attrib.push(EGL_NONE);
|
attrib.push(EGL_NONE);
|
||||||
let ctx = unsafe {
|
let ctx = unsafe {
|
||||||
eglCreateContext(
|
(self.egl.eglCreateContext)(
|
||||||
self.dpy,
|
self.dpy,
|
||||||
EGLConfig::none(),
|
EGLConfig::none(),
|
||||||
EGLContext::none(),
|
EGLContext::none(),
|
||||||
|
|
@ -139,7 +155,7 @@ impl EglDisplay {
|
||||||
ctx,
|
ctx,
|
||||||
formats: Default::default(),
|
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) {
|
if !ctx.ext.contains(GL_OES_EGL_IMAGE) {
|
||||||
return Err(RenderError::OesEglImage);
|
return Err(RenderError::OesEglImage);
|
||||||
}
|
}
|
||||||
|
|
@ -245,7 +261,7 @@ impl EglDisplay {
|
||||||
}
|
}
|
||||||
attribs.push(EGL_NONE);
|
attribs.push(EGL_NONE);
|
||||||
let img = unsafe {
|
let img = unsafe {
|
||||||
PROCS.eglCreateImageKHR(
|
self.procs.eglCreateImageKHR(
|
||||||
self.dpy,
|
self.dpy,
|
||||||
EGLContext::none(),
|
EGLContext::none(),
|
||||||
EGL_LINUX_DMA_BUF_EXT as _,
|
EGL_LINUX_DMA_BUF_EXT as _,
|
||||||
|
|
@ -268,22 +284,25 @@ impl EglDisplay {
|
||||||
impl Drop for EglDisplay {
|
impl Drop for EglDisplay {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if eglTerminate(self.dpy) != EGL_TRUE {
|
if (self.egl.eglTerminate)(self.dpy) != EGL_TRUE {
|
||||||
log::warn!("`eglTerminate` failed");
|
log::warn!("`eglTerminate` failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, EglFormat>, RenderError> {
|
unsafe fn query_formats(
|
||||||
|
procs: &ExtProc,
|
||||||
|
dpy: EGLDisplay,
|
||||||
|
) -> Result<AHashMap<u32, EglFormat>, RenderError> {
|
||||||
let mut vec = vec![];
|
let mut vec = vec![];
|
||||||
let mut num = 0;
|
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 {
|
if res != EGL_TRUE {
|
||||||
return Err(RenderError::QueryDmaBufFormats);
|
return Err(RenderError::QueryDmaBufFormats);
|
||||||
}
|
}
|
||||||
vec.reserve_exact(num as usize);
|
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 {
|
if res != EGL_TRUE {
|
||||||
return Err(RenderError::QueryDmaBufFormats);
|
return Err(RenderError::QueryDmaBufFormats);
|
||||||
}
|
}
|
||||||
|
|
@ -292,7 +311,7 @@ unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, EglFormat>, Ren
|
||||||
let formats = formats();
|
let formats = formats();
|
||||||
for fmt in vec {
|
for fmt in vec {
|
||||||
if let Some(format) = formats.get(&(fmt as u32)) {
|
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(
|
res.insert(
|
||||||
format.drm,
|
format.drm,
|
||||||
EglFormat {
|
EglFormat {
|
||||||
|
|
@ -307,6 +326,7 @@ unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, EglFormat>, Ren
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn query_modifiers(
|
unsafe fn query_modifiers(
|
||||||
|
procs: &ExtProc,
|
||||||
dpy: EGLDisplay,
|
dpy: EGLDisplay,
|
||||||
gl_format: EGLint,
|
gl_format: EGLint,
|
||||||
format: &'static Format,
|
format: &'static Format,
|
||||||
|
|
@ -314,7 +334,7 @@ unsafe fn query_modifiers(
|
||||||
let mut mods = vec![];
|
let mut mods = vec![];
|
||||||
let mut ext_only = vec![];
|
let mut ext_only = vec![];
|
||||||
let mut num = 0;
|
let mut num = 0;
|
||||||
let res = PROCS.eglQueryDmaBufModifiersEXT(
|
let res = procs.eglQueryDmaBufModifiersEXT(
|
||||||
dpy,
|
dpy,
|
||||||
gl_format,
|
gl_format,
|
||||||
num,
|
num,
|
||||||
|
|
@ -327,7 +347,7 @@ unsafe fn query_modifiers(
|
||||||
}
|
}
|
||||||
mods.reserve_exact(num as usize);
|
mods.reserve_exact(num as usize);
|
||||||
ext_only.reserve_exact(num as usize);
|
ext_only.reserve_exact(num as usize);
|
||||||
let res = PROCS.eglQueryDmaBufModifiersEXT(
|
let res = procs.eglQueryDmaBufModifiersEXT(
|
||||||
dpy,
|
dpy,
|
||||||
gl_format,
|
gl_format,
|
||||||
num,
|
num,
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ use {
|
||||||
gfx_apis::gl::egl::{
|
gfx_apis::gl::egl::{
|
||||||
display::EglDisplay,
|
display::EglDisplay,
|
||||||
sys::{EGLImageKHR, EGL_FALSE},
|
sys::{EGLImageKHR, EGL_FALSE},
|
||||||
PROCS,
|
|
||||||
},
|
},
|
||||||
video::dmabuf::DmaBuf,
|
video::dmabuf::DmaBuf,
|
||||||
},
|
},
|
||||||
|
|
@ -20,7 +19,7 @@ pub struct EglImage {
|
||||||
impl Drop for EglImage {
|
impl Drop for EglImage {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
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");
|
log::warn!("`eglDestroyImageKHR` failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_IMAGE_PRESERVED_KHR: EGLint = 0x30D2;
|
||||||
pub const EGL_LINUX_DMA_BUF_EXT: EGLint = 0x3270;
|
pub const EGL_LINUX_DMA_BUF_EXT: EGLint = 0x3270;
|
||||||
|
|
||||||
#[link(name = "EGL")]
|
dynload! {
|
||||||
extern "C" {
|
EGL: Egl from "libEGL.so" {
|
||||||
pub fn eglQueryString(dpy: EGLDisplay, name: EGLint) -> *const c::c_char;
|
eglQueryString: unsafe fn(dpy: EGLDisplay, name: EGLint) -> *const c::c_char,
|
||||||
pub fn eglGetProcAddress(procname: *const c::c_char) -> *mut u8;
|
eglGetProcAddress: unsafe fn(procname: *const c::c_char) -> *mut u8,
|
||||||
pub fn eglBindAPI(api: EGLenum) -> EGLBoolean;
|
eglBindAPI: unsafe fn(api: EGLenum) -> EGLBoolean,
|
||||||
pub fn eglTerminate(dpy: EGLDisplay) -> EGLBoolean;
|
eglTerminate: unsafe fn(dpy: EGLDisplay) -> EGLBoolean,
|
||||||
pub fn eglInitialize(dpy: EGLDisplay, major: *mut EGLint, minor: *mut EGLint) -> EGLBoolean;
|
eglInitialize: unsafe fn(dpy: EGLDisplay, major: *mut EGLint, minor: *mut EGLint) -> EGLBoolean,
|
||||||
pub fn eglCreateContext(
|
eglCreateContext: unsafe fn(
|
||||||
dpy: EGLDisplay,
|
dpy: EGLDisplay,
|
||||||
config: EGLConfig,
|
config: EGLConfig,
|
||||||
share_context: EGLContext,
|
share_context: EGLContext,
|
||||||
attrib_list: *const EGLint,
|
attrib_list: *const EGLint,
|
||||||
) -> EGLContext;
|
) -> EGLContext,
|
||||||
pub fn eglDestroyContext(dpy: EGLDisplay, ctx: EGLContext) -> EGLBoolean;
|
eglDestroyContext: unsafe fn(dpy: EGLDisplay, ctx: EGLContext) -> EGLBoolean,
|
||||||
pub fn eglMakeCurrent(
|
eglMakeCurrent: unsafe fn(
|
||||||
dpy: EGLDisplay,
|
dpy: EGLDisplay,
|
||||||
draw: EGLSurface,
|
draw: EGLSurface,
|
||||||
read: EGLSurface,
|
read: EGLSurface,
|
||||||
ctx: EGLContext,
|
ctx: EGLContext,
|
||||||
) -> EGLBoolean;
|
) -> EGLBoolean,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
egl::sys::{eglQueryString, EGLDisplay, EGL_EXTENSIONS},
|
egl::sys::{EGLDisplay, EGL_EXTENSIONS},
|
||||||
gl::sys::{glGetString, GL_EXTENSIONS},
|
gl::sys::GL_EXTENSIONS,
|
||||||
|
sys::{EGL, GLESV2},
|
||||||
|
RenderError,
|
||||||
},
|
},
|
||||||
utils::trim::AsciiTrim,
|
utils::trim::AsciiTrim,
|
||||||
},
|
},
|
||||||
|
|
@ -30,7 +32,7 @@ unsafe fn get_extensions(ext: *const c::c_char) -> Option<AHashSet<String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn get_dpy_extensions(dpy: EGLDisplay) -> Option<AHashSet<String>> {
|
unsafe fn get_dpy_extensions(dpy: EGLDisplay) -> Option<AHashSet<String>> {
|
||||||
let ext = eglQueryString(dpy, EGL_EXTENSIONS);
|
let ext = (EGL.as_ref()?.eglQueryString)(dpy, EGL_EXTENSIONS);
|
||||||
get_extensions(ext)
|
get_extensions(ext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,13 +109,16 @@ bitflags! {
|
||||||
GL_OES_EGL_IMAGE_EXTERNAL = 1 << 1,
|
GL_OES_EGL_IMAGE_EXTERNAL = 1 << 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_gl_ext() -> GlExt {
|
pub fn get_gl_ext() -> Result<GlExt, RenderError> {
|
||||||
let map = [
|
let map = [
|
||||||
("GL_OES_EGL_image", GL_OES_EGL_IMAGE),
|
("GL_OES_EGL_image", GL_OES_EGL_IMAGE),
|
||||||
("GL_OES_EGL_image_external", GL_OES_EGL_IMAGE_EXTERNAL),
|
("GL_OES_EGL_image_external", GL_OES_EGL_IMAGE_EXTERNAL),
|
||||||
];
|
];
|
||||||
match unsafe { get_extensions(glGetString(GL_EXTENSIONS) as _) } {
|
let Some(gles) = GLESV2.as_ref() else {
|
||||||
Some(exts) => get_typed_ext(&exts, GlExt::none(), &map),
|
return Err(RenderError::LoadGlesV2);
|
||||||
_ => GlExt::none(),
|
};
|
||||||
|
match unsafe { get_extensions((gles.glGetString)(GL_EXTENSIONS) as _) } {
|
||||||
|
Some(exts) => Ok(get_typed_ext(&exts, GlExt::none(), &map)),
|
||||||
|
_ => Ok(GlExt::none()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::gfx_apis::gl::{
|
crate::gfx_apis::gl::{
|
||||||
egl::context::EglContext,
|
egl::context::EglContext,
|
||||||
gl::{
|
gl::{render_buffer::GlRenderBuffer, sys::GLuint, texture::GlTexture},
|
||||||
render_buffer::GlRenderBuffer,
|
|
||||||
sys::{glDeleteFramebuffers, GLuint},
|
|
||||||
texture::GlTexture,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
std::rc::Rc,
|
std::rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
@ -23,7 +19,7 @@ impl Drop for GlFrameBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.ctx.with_current(|| {
|
let _ = self.ctx.with_current(|| {
|
||||||
unsafe {
|
unsafe {
|
||||||
glDeleteFramebuffers(1, &self.fbo);
|
(self.ctx.dpy.gles.glDeleteFramebuffers)(1, &self.fbo);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,7 @@ use {
|
||||||
egl::context::EglContext,
|
egl::context::EglContext,
|
||||||
gl::{
|
gl::{
|
||||||
shader::GlShader,
|
shader::GlShader,
|
||||||
sys::{
|
sys::{GLint, GLuint, GL_FALSE, GL_FRAGMENT_SHADER, GL_LINK_STATUS, GL_VERTEX_SHADER},
|
||||||
glAttachShader, glCreateProgram, glDeleteProgram, glDetachShader,
|
|
||||||
glGetAttribLocation, glGetProgramiv, glGetUniformLocation, glLinkProgram, GLint,
|
|
||||||
GLuint, GL_FALSE, GL_FRAGMENT_SHADER, GL_LINK_STATUS, GL_VERTEX_SHADER,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
RenderError,
|
RenderError,
|
||||||
},
|
},
|
||||||
|
|
@ -16,7 +12,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct GlProgram {
|
pub struct GlProgram {
|
||||||
pub _ctx: Rc<EglContext>,
|
pub ctx: Rc<EglContext>,
|
||||||
pub prog: GLuint,
|
pub prog: GLuint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -35,18 +31,19 @@ impl GlProgram {
|
||||||
vert: &GlShader,
|
vert: &GlShader,
|
||||||
frag: &GlShader,
|
frag: &GlShader,
|
||||||
) -> Result<Self, RenderError> {
|
) -> Result<Self, RenderError> {
|
||||||
|
let gles = vert.ctx.dpy.gles;
|
||||||
let res = GlProgram {
|
let res = GlProgram {
|
||||||
_ctx: vert.ctx.clone(),
|
ctx: vert.ctx.clone(),
|
||||||
prog: glCreateProgram(),
|
prog: (gles.glCreateProgram)(),
|
||||||
};
|
};
|
||||||
glAttachShader(res.prog, vert.shader);
|
(gles.glAttachShader)(res.prog, vert.shader);
|
||||||
glAttachShader(res.prog, frag.shader);
|
(gles.glAttachShader)(res.prog, frag.shader);
|
||||||
glLinkProgram(res.prog);
|
(gles.glLinkProgram)(res.prog);
|
||||||
glDetachShader(res.prog, vert.shader);
|
(gles.glDetachShader)(res.prog, vert.shader);
|
||||||
glDetachShader(res.prog, frag.shader);
|
(gles.glDetachShader)(res.prog, frag.shader);
|
||||||
|
|
||||||
let mut ok = 0;
|
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 {
|
if ok == GL_FALSE as GLint {
|
||||||
return Err(RenderError::ProgramLink);
|
return Err(RenderError::ProgramLink);
|
||||||
}
|
}
|
||||||
|
|
@ -55,19 +52,19 @@ impl GlProgram {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn get_uniform_location(&self, name: &Ustr) -> GLint {
|
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 {
|
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 {
|
impl Drop for GlProgram {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let _ = self._ctx.with_current(|| {
|
let _ = self.ctx.with_current(|| {
|
||||||
glDeleteProgram(self.prog);
|
(self.ctx.dpy.gles.glDeleteProgram)(self.prog);
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,10 @@
|
||||||
use {
|
use {
|
||||||
crate::gfx_apis::gl::{
|
crate::gfx_apis::gl::{
|
||||||
egl::{context::EglContext, image::EglImage, PROCS},
|
egl::{context::EglContext, image::EglImage},
|
||||||
gl::{
|
gl::{
|
||||||
frame_buffer::GlFrameBuffer,
|
frame_buffer::GlFrameBuffer,
|
||||||
sys::{
|
sys::{
|
||||||
glBindFramebuffer, glBindRenderbuffer, glCheckFramebufferStatus,
|
GLeglImageOES, GLuint, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER,
|
||||||
glDeleteRenderbuffers, glFramebufferRenderbuffer, glGenFramebuffers,
|
|
||||||
glGenRenderbuffers, GLeglImageOES, GLuint, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER,
|
|
||||||
GL_FRAMEBUFFER_COMPLETE, GL_RENDERBUFFER,
|
GL_FRAMEBUFFER_COMPLETE, GL_RENDERBUFFER,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -29,11 +27,14 @@ impl GlRenderBuffer {
|
||||||
if img.external_only {
|
if img.external_only {
|
||||||
return Err(RenderError::ExternalOnly);
|
return Err(RenderError::ExternalOnly);
|
||||||
}
|
}
|
||||||
|
let gles = ctx.dpy.gles;
|
||||||
let mut rbo = 0;
|
let mut rbo = 0;
|
||||||
glGenRenderbuffers(1, &mut rbo);
|
(gles.glGenRenderbuffers)(1, &mut rbo);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
(gles.glBindRenderbuffer)(GL_RENDERBUFFER, rbo);
|
||||||
PROCS.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, GLeglImageOES(img.img.0));
|
ctx.dpy
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
.procs
|
||||||
|
.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, GLeglImageOES(img.img.0));
|
||||||
|
(gles.glBindRenderbuffer)(GL_RENDERBUFFER, 0);
|
||||||
Ok(Rc::new(GlRenderBuffer {
|
Ok(Rc::new(GlRenderBuffer {
|
||||||
img: img.clone(),
|
img: img.clone(),
|
||||||
ctx: ctx.clone(),
|
ctx: ctx.clone(),
|
||||||
|
|
@ -44,17 +45,18 @@ impl GlRenderBuffer {
|
||||||
pub(in crate::gfx_apis::gl) unsafe fn create_framebuffer(
|
pub(in crate::gfx_apis::gl) unsafe fn create_framebuffer(
|
||||||
self: &Rc<Self>,
|
self: &Rc<Self>,
|
||||||
) -> Result<GlFrameBuffer, RenderError> {
|
) -> Result<GlFrameBuffer, RenderError> {
|
||||||
|
let gles = self.ctx.dpy.gles;
|
||||||
let mut fbo = 0;
|
let mut fbo = 0;
|
||||||
glGenFramebuffers(1, &mut fbo);
|
(gles.glGenFramebuffers)(1, &mut fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, fbo);
|
||||||
glFramebufferRenderbuffer(
|
(gles.glFramebufferRenderbuffer)(
|
||||||
GL_FRAMEBUFFER,
|
GL_FRAMEBUFFER,
|
||||||
GL_COLOR_ATTACHMENT0,
|
GL_COLOR_ATTACHMENT0,
|
||||||
GL_RENDERBUFFER,
|
GL_RENDERBUFFER,
|
||||||
self.rbo,
|
self.rbo,
|
||||||
);
|
);
|
||||||
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
let status = (gles.glCheckFramebufferStatus)(GL_FRAMEBUFFER);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, 0);
|
||||||
let fb = GlFrameBuffer {
|
let fb = GlFrameBuffer {
|
||||||
rb: self.clone(),
|
rb: self.clone(),
|
||||||
_tex: None,
|
_tex: None,
|
||||||
|
|
@ -74,7 +76,7 @@ impl Drop for GlRenderBuffer {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.ctx.with_current(|| {
|
let _ = self.ctx.with_current(|| {
|
||||||
unsafe {
|
unsafe {
|
||||||
glDeleteRenderbuffers(1, &self.rbo);
|
(self.ctx.dpy.gles.glDeleteRenderbuffers)(1, &self.rbo);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::gfx_apis::gl::{
|
crate::gfx_apis::gl::{
|
||||||
egl::context::EglContext,
|
egl::context::EglContext,
|
||||||
gl::sys::{
|
gl::sys::{GLenum, GLuint, GL_COMPILE_STATUS, GL_FALSE},
|
||||||
glCompileShader, glCreateShader, glDeleteShader, glGetShaderiv, glShaderSource, GLenum,
|
|
||||||
GLuint, GL_COMPILE_STATUS, GL_FALSE,
|
|
||||||
},
|
|
||||||
sys::GLint,
|
sys::GLint,
|
||||||
RenderError,
|
RenderError,
|
||||||
},
|
},
|
||||||
|
|
@ -22,17 +19,18 @@ impl GlShader {
|
||||||
ty: GLenum,
|
ty: GLenum,
|
||||||
src: &str,
|
src: &str,
|
||||||
) -> Result<Self, RenderError> {
|
) -> Result<Self, RenderError> {
|
||||||
let shader = glCreateShader(ty);
|
let gles = ctx.dpy.gles;
|
||||||
|
let shader = (gles.glCreateShader)(ty);
|
||||||
let res = GlShader {
|
let res = GlShader {
|
||||||
ctx: ctx.clone(),
|
ctx: ctx.clone(),
|
||||||
shader,
|
shader,
|
||||||
};
|
};
|
||||||
let len = src.len() as _;
|
let len = src.len() as _;
|
||||||
glShaderSource(shader, 1, &(src.as_ptr() as _), &len);
|
(gles.glShaderSource)(shader, 1, &(src.as_ptr() as _), &len);
|
||||||
glCompileShader(shader);
|
(gles.glCompileShader)(shader);
|
||||||
|
|
||||||
let mut ok = 0;
|
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 {
|
if ok == GL_FALSE as GLint {
|
||||||
return Err(RenderError::ShaderCompileFailed);
|
return Err(RenderError::ShaderCompileFailed);
|
||||||
}
|
}
|
||||||
|
|
@ -43,7 +41,7 @@ impl GlShader {
|
||||||
impl Drop for GlShader {
|
impl Drop for GlShader {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.ctx.with_current(|| unsafe {
|
let _ = self.ctx.with_current(|| unsafe {
|
||||||
glDeleteShader(self.shader);
|
(self.ctx.dpy.gles.glDeleteShader)(self.shader);
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,107 +45,105 @@ pub const GL_BLEND: GLenum = 0x0BE2;
|
||||||
pub const GL_ONE: GLenum = 1;
|
pub const GL_ONE: GLenum = 1;
|
||||||
pub const GL_ONE_MINUS_SRC_ALPHA: GLenum = 0x0303;
|
pub const GL_ONE_MINUS_SRC_ALPHA: GLenum = 0x0303;
|
||||||
|
|
||||||
#[link(name = "GLESv2")]
|
dynload! {
|
||||||
extern "C" {
|
GLESV2: GlesV2 from "libGLESv2.so" {
|
||||||
pub fn glGetString(name: GLenum) -> *const u8;
|
glGetString: unsafe fn(name: GLenum) -> *const u8,
|
||||||
pub fn glGenRenderbuffers(n: GLsizei, renderbuffers: *mut GLuint);
|
glGenRenderbuffers: unsafe fn(n: GLsizei, renderbuffers: *mut GLuint),
|
||||||
pub fn glDeleteRenderbuffers(n: GLsizei, renderbuffers: *const GLuint);
|
glDeleteRenderbuffers: unsafe fn(n: GLsizei, renderbuffers: *const GLuint),
|
||||||
pub fn glBindRenderbuffer(target: GLenum, renderbuffer: GLuint);
|
glBindRenderbuffer: unsafe fn(target: GLenum, renderbuffer: GLuint),
|
||||||
pub fn glGenFramebuffers(n: GLsizei, framebuffers: *mut GLuint);
|
glGenFramebuffers: unsafe fn(n: GLsizei, framebuffers: *mut GLuint),
|
||||||
pub fn glDeleteFramebuffers(n: GLsizei, framebuffers: *const GLuint);
|
glDeleteFramebuffers: unsafe fn(n: GLsizei, framebuffers: *const GLuint),
|
||||||
pub fn glBindFramebuffer(target: GLenum, framebuffer: GLuint);
|
glBindFramebuffer: unsafe fn(target: GLenum, framebuffer: GLuint),
|
||||||
pub fn glFramebufferRenderbuffer(
|
glFramebufferRenderbuffer: unsafe fn(
|
||||||
target: GLenum,
|
target: GLenum,
|
||||||
attachment: GLenum,
|
attachment: GLenum,
|
||||||
renderbuffertarget: GLenum,
|
renderbuffertarget: GLenum,
|
||||||
renderbuffer: GLuint,
|
renderbuffer: GLuint,
|
||||||
);
|
),
|
||||||
#[allow(dead_code)]
|
glFramebufferTexture2D: unsafe fn(
|
||||||
pub fn glFramebufferTexture2D(
|
target: GLenum,
|
||||||
target: GLenum,
|
attachment: GLenum,
|
||||||
attachment: GLenum,
|
textarget: GLenum,
|
||||||
textarget: GLenum,
|
texture: GLenum,
|
||||||
texture: GLenum,
|
level: GLint,
|
||||||
level: GLint,
|
),
|
||||||
);
|
glCheckFramebufferStatus: unsafe fn(target: GLenum) -> GLenum,
|
||||||
pub fn glCheckFramebufferStatus(target: GLenum) -> GLenum;
|
glClear: unsafe fn(mask: GLbitfield),
|
||||||
pub fn glClear(mask: GLbitfield);
|
glBlendFunc: unsafe fn(sfactor: GLenum, dfactor: GLenum),
|
||||||
pub fn glBlendFunc(sfactor: GLenum, dfactor: GLenum);
|
glClearColor: unsafe fn(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat),
|
||||||
pub fn glClearColor(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat);
|
glFlush: unsafe fn(),
|
||||||
#[allow(dead_code)]
|
|
||||||
pub fn glFlush();
|
|
||||||
|
|
||||||
pub fn glReadnPixels(
|
glReadnPixels: unsafe fn(
|
||||||
x: GLint,
|
x: GLint,
|
||||||
y: GLint,
|
y: GLint,
|
||||||
width: GLsizei,
|
width: GLsizei,
|
||||||
height: GLsizei,
|
height: GLsizei,
|
||||||
format: GLenum,
|
format: GLenum,
|
||||||
ty: GLenum,
|
ty: GLenum,
|
||||||
buf_size: GLsizei,
|
buf_size: GLsizei,
|
||||||
data: *mut c::c_void,
|
data: *mut c::c_void,
|
||||||
);
|
),
|
||||||
|
|
||||||
pub fn glGenTextures(n: GLsizei, textures: *mut GLuint);
|
glGenTextures: unsafe fn(n: GLsizei, textures: *mut GLuint),
|
||||||
pub fn glDeleteTextures(n: GLsizei, textures: *const GLuint);
|
glDeleteTextures: unsafe fn(n: GLsizei, textures: *const GLuint),
|
||||||
pub fn glBindTexture(target: GLenum, texture: GLuint);
|
glBindTexture: unsafe fn(target: GLenum, texture: GLuint),
|
||||||
pub fn glTexParameteri(target: GLenum, pname: GLenum, param: GLint);
|
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(
|
glTexImage2D: unsafe fn(
|
||||||
target: GLenum,
|
target: GLenum,
|
||||||
level: GLint,
|
level: GLint,
|
||||||
internalformat: GLint,
|
internalformat: GLint,
|
||||||
width: GLsizei,
|
width: GLsizei,
|
||||||
height: GLsizei,
|
height: GLsizei,
|
||||||
border: GLint,
|
border: GLint,
|
||||||
format: GLenum,
|
format: GLenum,
|
||||||
ty: GLenum,
|
ty: GLenum,
|
||||||
pixels: *const c::c_void,
|
pixels: *const c::c_void,
|
||||||
);
|
),
|
||||||
|
|
||||||
pub fn glEnable(cap: GLenum);
|
glEnable: unsafe fn(cap: GLenum),
|
||||||
pub fn glDisable(cap: GLenum);
|
glDisable: unsafe fn(cap: GLenum),
|
||||||
pub fn glViewport(x: GLint, y: GLint, width: GLsizei, height: GLsizei);
|
glViewport: unsafe fn(x: GLint, y: GLint, width: GLsizei, height: GLsizei),
|
||||||
|
|
||||||
pub fn glCreateShader(ty: GLenum) -> GLuint;
|
glCreateShader: unsafe fn(ty: GLenum) -> GLuint,
|
||||||
pub fn glDeleteShader(shader: GLuint);
|
glDeleteShader: unsafe fn(shader: GLuint),
|
||||||
pub fn glShaderSource(
|
glShaderSource: unsafe fn(
|
||||||
shader: GLuint,
|
shader: GLuint,
|
||||||
count: GLsizei,
|
count: GLsizei,
|
||||||
string: *const *const GLchar,
|
string: *const *const GLchar,
|
||||||
length: *const GLint,
|
length: *const GLint,
|
||||||
);
|
),
|
||||||
pub fn glCompileShader(shader: GLuint);
|
glCompileShader: unsafe fn(shader: GLuint),
|
||||||
pub fn glGetShaderiv(shader: GLuint, pname: GLenum, params: *mut GLint);
|
glGetShaderiv: unsafe fn(shader: GLuint, pname: GLenum, params: *mut GLint),
|
||||||
|
|
||||||
pub fn glCreateProgram() -> GLuint;
|
glCreateProgram: unsafe fn() -> GLuint,
|
||||||
pub fn glDeleteProgram(prog: GLuint);
|
glDeleteProgram: unsafe fn(prog: GLuint),
|
||||||
pub fn glAttachShader(prog: GLuint, shader: GLuint);
|
glAttachShader: unsafe fn(prog: GLuint, shader: GLuint),
|
||||||
pub fn glDetachShader(prog: GLuint, shader: GLuint);
|
glDetachShader: unsafe fn(prog: GLuint, shader: GLuint),
|
||||||
pub fn glLinkProgram(prog: GLuint);
|
glLinkProgram: unsafe fn(prog: GLuint),
|
||||||
pub fn glGetProgramiv(program: GLuint, pname: GLenum, params: *mut GLint);
|
glGetProgramiv: unsafe fn(program: GLuint, pname: GLenum, params: *mut GLint),
|
||||||
pub fn glUseProgram(program: GLuint);
|
glUseProgram: unsafe fn(program: GLuint),
|
||||||
|
|
||||||
pub fn glGetUniformLocation(prog: GLuint, name: *const GLchar) -> GLint;
|
glGetUniformLocation: unsafe fn(prog: GLuint, name: *const GLchar) -> GLint,
|
||||||
pub fn glGetAttribLocation(prog: GLuint, name: *const GLchar) -> GLint;
|
glGetAttribLocation: unsafe fn(prog: GLuint, name: *const GLchar) -> GLint,
|
||||||
pub fn glUniform1i(location: GLint, v0: GLint);
|
glUniform1i: unsafe fn(location: GLint, v0: GLint),
|
||||||
#[allow(dead_code)]
|
glUniform1f: unsafe fn(location: GLint, v0: GLfloat),
|
||||||
pub fn glUniform1f(location: GLint, v0: GLfloat);
|
glUniform4f: unsafe fn(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat, v3: GLfloat),
|
||||||
pub fn glUniform4f(location: GLint, v0: GLfloat, v1: GLfloat, v2: GLfloat, v3: GLfloat);
|
glVertexAttribPointer: unsafe fn(
|
||||||
pub fn glVertexAttribPointer(
|
index: GLuint,
|
||||||
index: GLuint,
|
size: GLint,
|
||||||
size: GLint,
|
ty: GLenum,
|
||||||
ty: GLenum,
|
normalized: GLboolean,
|
||||||
normalized: GLboolean,
|
stride: GLsizei,
|
||||||
stride: GLsizei,
|
pointer: *const u8,
|
||||||
pointer: *const u8,
|
),
|
||||||
);
|
|
||||||
|
|
||||||
pub fn glActiveTexture(texture: GLuint);
|
glActiveTexture: unsafe fn(texture: GLuint),
|
||||||
|
|
||||||
pub fn glEnableVertexAttribArray(idx: GLuint);
|
glEnableVertexAttribArray: unsafe fn(idx: GLuint),
|
||||||
pub fn glDisableVertexAttribArray(idx: GLuint);
|
glDisableVertexAttribArray: unsafe fn(idx: GLuint),
|
||||||
pub fn glDrawArrays(mode: GLenum, first: GLint, count: GLsizei);
|
glDrawArrays: unsafe fn(mode: GLenum, first: GLint, count: GLsizei),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,10 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
format::Format,
|
format::Format,
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
egl::{context::EglContext, image::EglImage, PROCS},
|
egl::{context::EglContext, image::EglImage},
|
||||||
ext::GL_OES_EGL_IMAGE_EXTERNAL,
|
ext::GL_OES_EGL_IMAGE_EXTERNAL,
|
||||||
gl::sys::{
|
gl::sys::{
|
||||||
glBindTexture, glDeleteTextures, glGenTextures, glPixelStorei, glTexImage2D,
|
GLint, GLuint, GL_CLAMP_TO_EDGE, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
||||||
glTexParameteri, GLint, GLuint, GL_CLAMP_TO_EDGE, GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
|
||||||
GL_TEXTURE_WRAP_T, GL_UNPACK_ROW_LENGTH_EXT,
|
GL_TEXTURE_WRAP_T, GL_UNPACK_ROW_LENGTH_EXT,
|
||||||
},
|
},
|
||||||
sys::{GLeglImageOES, GLenum, GL_TEXTURE_EXTERNAL_OES},
|
sys::{GLeglImageOES, GLenum, GL_TEXTURE_EXTERNAL_OES},
|
||||||
|
|
@ -41,15 +40,18 @@ impl GlTexture {
|
||||||
if !ctx.ext.contains(GL_OES_EGL_IMAGE_EXTERNAL) {
|
if !ctx.ext.contains(GL_OES_EGL_IMAGE_EXTERNAL) {
|
||||||
return Err(RenderError::ExternalUnsupported);
|
return Err(RenderError::ExternalUnsupported);
|
||||||
}
|
}
|
||||||
|
let gles = ctx.dpy.gles;
|
||||||
let target = image_target(img.external_only);
|
let target = image_target(img.external_only);
|
||||||
let tex = ctx.with_current(|| unsafe {
|
let tex = ctx.with_current(|| unsafe {
|
||||||
let mut tex = 0;
|
let mut tex = 0;
|
||||||
glGenTextures(1, &mut tex);
|
(gles.glGenTextures)(1, &mut tex);
|
||||||
glBindTexture(target, tex);
|
(gles.glBindTexture)(target, tex);
|
||||||
glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
(gles.glTexParameteri)(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
(gles.glTexParameteri)(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
PROCS.glEGLImageTargetTexture2DOES(target, GLeglImageOES(img.img.0));
|
ctx.dpy
|
||||||
glBindTexture(target, 0);
|
.procs
|
||||||
|
.glEGLImageTargetTexture2DOES(target, GLeglImageOES(img.img.0));
|
||||||
|
(gles.glBindTexture)(target, 0);
|
||||||
Ok(tex)
|
Ok(tex)
|
||||||
})?;
|
})?;
|
||||||
Ok(GlTexture {
|
Ok(GlTexture {
|
||||||
|
|
@ -74,14 +76,15 @@ impl GlTexture {
|
||||||
if (stride * height) as usize > data.len() {
|
if (stride * height) as usize > data.len() {
|
||||||
return Err(RenderError::SmallImageBuffer);
|
return Err(RenderError::SmallImageBuffer);
|
||||||
}
|
}
|
||||||
|
let gles = ctx.dpy.gles;
|
||||||
let tex = ctx.with_current(|| unsafe {
|
let tex = ctx.with_current(|| unsafe {
|
||||||
let mut tex = 0;
|
let mut tex = 0;
|
||||||
glGenTextures(1, &mut tex);
|
(gles.glGenTextures)(1, &mut tex);
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
(gles.glBindTexture)(GL_TEXTURE_2D, tex);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
(gles.glTexParameteri)(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint);
|
(gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, stride / format.bpp as GLint);
|
||||||
glTexImage2D(
|
(gles.glTexImage2D)(
|
||||||
GL_TEXTURE_2D,
|
GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
format.gl_format,
|
format.gl_format,
|
||||||
|
|
@ -92,8 +95,8 @@ impl GlTexture {
|
||||||
format.gl_type as _,
|
format.gl_type as _,
|
||||||
data.as_ptr() as _,
|
data.as_ptr() as _,
|
||||||
);
|
);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
|
(gles.glPixelStorei)(GL_UNPACK_ROW_LENGTH_EXT, 0);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
(gles.glBindTexture)(GL_TEXTURE_2D, 0);
|
||||||
Ok(tex)
|
Ok(tex)
|
||||||
})?;
|
})?;
|
||||||
Ok(GlTexture {
|
Ok(GlTexture {
|
||||||
|
|
@ -111,7 +114,7 @@ impl GlTexture {
|
||||||
impl Drop for GlTexture {
|
impl Drop for GlTexture {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.ctx.with_current(|| unsafe {
|
let _ = self.ctx.with_current(|| unsafe {
|
||||||
glDeleteTextures(1, &self.tex);
|
(self.ctx.dpy.gles.glDeleteTextures)(1, &self.tex);
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,11 @@ use {
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
gl::{
|
gl::{
|
||||||
frame_buffer::GlFrameBuffer,
|
frame_buffer::GlFrameBuffer,
|
||||||
sys::{
|
sys::{GL_COLOR_BUFFER_BIT, GL_FRAMEBUFFER},
|
||||||
glBindFramebuffer, glClear, glClearColor, glViewport, GL_COLOR_BUFFER_BIT,
|
|
||||||
GL_FRAMEBUFFER,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
renderer::context::GlRenderContext,
|
renderer::context::GlRenderContext,
|
||||||
run_ops,
|
run_ops,
|
||||||
sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
|
sys::{GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
|
||||||
},
|
},
|
||||||
theme::Color,
|
theme::Color,
|
||||||
},
|
},
|
||||||
|
|
@ -46,12 +43,13 @@ impl Framebuffer {
|
||||||
format: &Format,
|
format: &Format,
|
||||||
shm: &[Cell<u8>],
|
shm: &[Cell<u8>],
|
||||||
) {
|
) {
|
||||||
|
let gles = self.ctx.ctx.dpy.gles;
|
||||||
let y = self.gl.height - y - height;
|
let y = self.gl.height - y - height;
|
||||||
let _ = self.ctx.ctx.with_current(|| {
|
let _ = self.ctx.ctx.with_current(|| {
|
||||||
unsafe {
|
unsafe {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
|
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo);
|
||||||
glViewport(0, 0, self.gl.width, self.gl.height);
|
(gles.glViewport)(0, 0, self.gl.width, self.gl.height);
|
||||||
glReadnPixels(
|
(gles.glReadnPixels)(
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
width,
|
width,
|
||||||
|
|
@ -67,19 +65,20 @@ impl Framebuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) {
|
pub fn render(&self, ops: Vec<GfxApiOpt>, clear: Option<&Color>) {
|
||||||
|
let gles = self.ctx.ctx.dpy.gles;
|
||||||
let _ = self.ctx.ctx.with_current(|| {
|
let _ = self.ctx.ctx.with_current(|| {
|
||||||
unsafe {
|
unsafe {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
|
(gles.glBindFramebuffer)(GL_FRAMEBUFFER, self.gl.fbo);
|
||||||
glViewport(0, 0, self.gl.width, self.gl.height);
|
(gles.glViewport)(0, 0, self.gl.width, self.gl.height);
|
||||||
if let Some(c) = clear {
|
if let Some(c) = clear {
|
||||||
glClearColor(c.r, c.g, c.b, c.a);
|
(gles.glClearColor)(c.r, c.g, c.b, c.a);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
(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);
|
run_ops(self, &ops);
|
||||||
unsafe {
|
unsafe {
|
||||||
glFlush();
|
(gles.glFlush)();
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue