1
0
Fork 0
forked from wry/wry

autocommit 2022-01-28 19:46:23 CET

This commit is contained in:
Julian Orth 2022-01-28 19:46:23 +01:00
parent a5573b8a3a
commit b11a36729c
45 changed files with 1646 additions and 2171 deletions

View file

@ -0,0 +1,55 @@
use crate::rect::Rect;
use crate::render::egl::context::EglContext;
use crate::render::gl::render_buffer::GlRenderBuffer;
use crate::render::gl::sys::{glDeleteFramebuffers, GLuint};
use crate::render::gl::texture::GlTexture;
use crate::render::sys::{glDisable, glEnable, glScissor, GL_SCISSOR_TEST};
use crate::utils::ptr_ext::PtrExt;
use std::ptr;
use std::rc::Rc;
pub struct GlFrameBuffer {
pub _rb: Option<Rc<GlRenderBuffer>>,
pub _tex: Option<Rc<GlTexture>>,
pub ctx: Rc<EglContext>,
pub width: i32,
pub height: i32,
pub fbo: GLuint,
}
impl Drop for GlFrameBuffer {
fn drop(&mut self) {
let _ = self.ctx.with_current(|| {
unsafe {
glDeleteFramebuffers(1, &self.fbo);
}
Ok(())
});
}
}
pub unsafe fn with_scissor<T, F: FnOnce() -> T>(scissor: &Rect, f: F) -> T {
#[thread_local]
static mut SCISSOR: *const Rect = ptr::null();
let prev = SCISSOR;
if prev.is_null() {
glEnable(GL_SCISSOR_TEST);
}
glScissor(
scissor.x1(),
scissor.y1(),
scissor.width(),
scissor.height(),
);
SCISSOR = scissor;
let res = f();
if prev.is_null() {
glDisable(GL_SCISSOR_TEST);
} else {
let prev = prev.deref();
glScissor(prev.x1(), prev.y1(), prev.width(), prev.height());
}
SCISSOR = prev;
res
}

6
src/render/gl/mod.rs Normal file
View file

@ -0,0 +1,6 @@
pub mod frame_buffer;
pub mod program;
pub mod render_buffer;
pub mod shader;
pub mod sys;
pub mod texture;

66
src/render/gl/program.rs Normal file
View file

@ -0,0 +1,66 @@
use crate::render::egl::context::EglContext;
use crate::render::gl::shader::GlShader;
use crate::render::gl::sys::{
glAttachShader, glCreateProgram, glDeleteProgram, glDetachShader, glGetAttribLocation,
glGetProgramiv, glGetUniformLocation, glLinkProgram, GLint, GLuint, GL_FALSE, GL_LINK_STATUS,
};
use crate::render::gl::sys::{GL_FRAGMENT_SHADER, GL_VERTEX_SHADER};
use crate::render::RenderError;
use std::rc::Rc;
use uapi::Ustr;
pub struct GlProgram {
pub _ctx: Rc<EglContext>,
pub prog: GLuint,
}
impl GlProgram {
pub unsafe fn from_shaders(
ctx: &Rc<EglContext>,
vert: &str,
frag: &str,
) -> Result<Self, RenderError> {
let vert = GlShader::compile(ctx, GL_VERTEX_SHADER, vert)?;
let frag = GlShader::compile(ctx, GL_FRAGMENT_SHADER, frag)?;
Self::link(&vert, &frag)
}
pub unsafe fn link(vert: &GlShader, frag: &GlShader) -> Result<Self, RenderError> {
let res = GlProgram {
_ctx: vert.ctx.clone(),
prog: glCreateProgram(),
};
glAttachShader(res.prog, vert.shader);
glAttachShader(res.prog, frag.shader);
glLinkProgram(res.prog);
glDetachShader(res.prog, vert.shader);
glDetachShader(res.prog, frag.shader);
let mut ok = 0;
glGetProgramiv(res.prog, GL_LINK_STATUS, &mut ok);
if ok == GL_FALSE as _ {
return Err(RenderError::ProgramLink);
}
Ok(res)
}
pub unsafe fn get_uniform_location(&self, name: &Ustr) -> GLint {
glGetUniformLocation(self.prog, name.as_ptr() as _)
}
pub unsafe fn get_attrib_location(&self, name: &Ustr) -> GLint {
glGetAttribLocation(self.prog, name.as_ptr() as _)
}
}
impl Drop for GlProgram {
fn drop(&mut self) {
unsafe {
let _ = self._ctx.with_current(|| {
glDeleteProgram(self.prog);
Ok(())
});
}
}
}

View file

@ -0,0 +1,72 @@
use crate::render::egl::context::EglContext;
use crate::render::egl::image::EglImage;
use crate::render::egl::PROCS;
use crate::render::gl::frame_buffer::GlFrameBuffer;
use crate::render::gl::sys::{
glBindFramebuffer, glBindRenderbuffer, glCheckFramebufferStatus, glDeleteRenderbuffers,
glFramebufferRenderbuffer, glGenFramebuffers, glGenRenderbuffers, GLeglImageOES, GLuint,
GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER, GL_FRAMEBUFFER_COMPLETE, GL_RENDERBUFFER,
};
use crate::render::RenderError;
use std::rc::Rc;
pub struct GlRenderBuffer {
pub img: Rc<EglImage>,
pub ctx: Rc<EglContext>,
rbo: GLuint,
}
impl GlRenderBuffer {
pub unsafe fn from_image(
img: &Rc<EglImage>,
ctx: &Rc<EglContext>,
) -> Result<Rc<GlRenderBuffer>, RenderError> {
let mut rbo = 0;
glGenRenderbuffers(1, &mut rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
PROCS.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, GLeglImageOES(img.img.0));
glBindRenderbuffer(GL_RENDERBUFFER, 0);
Ok(Rc::new(GlRenderBuffer {
img: img.clone(),
ctx: ctx.clone(),
rbo,
}))
}
pub unsafe fn create_framebuffer(self: &Rc<Self>) -> Result<GlFrameBuffer, RenderError> {
let mut fbo = 0;
glGenFramebuffers(1, &mut fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
self.rbo,
);
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
let fb = GlFrameBuffer {
_rb: Some(self.clone()),
_tex: None,
ctx: self.ctx.clone(),
fbo,
width: self.img.width,
height: self.img.height,
};
if status != GL_FRAMEBUFFER_COMPLETE {
return Err(RenderError::CreateFramebuffer);
}
Ok(fb)
}
}
impl Drop for GlRenderBuffer {
fn drop(&mut self) {
let _ = self.ctx.with_current(|| {
unsafe {
glDeleteRenderbuffers(1, &self.rbo);
}
Ok(())
});
}
}

45
src/render/gl/shader.rs Normal file
View file

@ -0,0 +1,45 @@
use crate::render::egl::context::EglContext;
use crate::render::gl::sys::{
glCompileShader, glCreateShader, glDeleteShader, glGetShaderiv, glShaderSource, GLenum, GLuint,
GL_COMPILE_STATUS, GL_FALSE,
};
use crate::render::RenderError;
use std::rc::Rc;
pub struct GlShader {
pub ctx: Rc<EglContext>,
pub shader: GLuint,
}
impl GlShader {
pub unsafe fn compile(
ctx: &Rc<EglContext>,
ty: GLenum,
src: &str,
) -> Result<Self, RenderError> {
let shader = glCreateShader(ty);
let res = GlShader {
ctx: ctx.clone(),
shader,
};
let len = src.len() as _;
glShaderSource(shader, 1, &(src.as_ptr() as _), &len);
glCompileShader(shader);
let mut ok = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, &mut ok);
if ok == GL_FALSE as _ {
return Err(RenderError::ShaderCompileFailed);
}
Ok(res)
}
}
impl Drop for GlShader {
fn drop(&mut self) {
let _ = self.ctx.with_current(|| unsafe {
glDeleteShader(self.shader);
Ok(())
});
}
}

131
src/render/gl/sys.rs Normal file
View file

@ -0,0 +1,131 @@
pub use uapi::c;
pub type GLbitfield = c::c_uint;
pub type GLboolean = c::c_uchar;
pub type GLchar = c::c_char;
pub type GLenum = c::c_uint;
pub type GLfloat = f32;
pub type GLint = c::c_int;
pub type GLsizei = c::c_int;
pub type GLubyte = u8;
pub type GLuint = c::c_uint;
egl_transparent!(GLeglImageOES);
pub const GL_BGRA_EXT: GLint = 0x80E1;
pub const GL_CLAMP_TO_EDGE: GLint = 0x812F;
pub const GL_COLOR_ATTACHMENT0: GLenum = 0x8CE0;
pub const GL_COLOR_BUFFER_BIT: GLbitfield = 0x00004000;
pub const GL_COMPILE_STATUS: GLenum = 0x8B81;
pub const GL_EXTENSIONS: GLenum = 0x1F03;
pub const GL_FALSE: GLboolean = 0;
pub const GL_FLOAT: GLenum = 0x1406;
pub const GL_FRAGMENT_SHADER: GLenum = 0x8B30;
pub const GL_FRAMEBUFFER_COMPLETE: GLenum = 0x8CD5;
pub const GL_FRAMEBUFFER: GLenum = 0x8D40;
pub const GL_LINEAR: GLint = 0x2601;
pub const GL_LINK_STATUS: GLenum = 0x8B82;
pub const GL_RENDERBUFFER: GLenum = 0x8D41;
pub const GL_SCISSOR_TEST: GLenum = 0x0C11;
pub const GL_TEXTURE0: GLenum = 0x84C0;
pub const GL_TEXTURE_2D: GLenum = 0x0DE1;
pub const GL_TEXTURE_MAG_FILTER: GLenum = 0x2800;
pub const GL_TEXTURE_MIN_FILTER: GLenum = 0x2801;
pub const GL_TEXTURE_WRAP_S: GLenum = 0x2802;
pub const GL_TEXTURE_WRAP_T: GLenum = 0x2803;
pub const GL_TRIANGLE_STRIP: GLenum = 0x0005;
pub const GL_TRIANGLES: GLenum = 0x0004;
pub const GL_UNPACK_ROW_LENGTH_EXT: GLenum = 0x0CF2;
pub const GL_UNSIGNED_BYTE: GLint = 0x1401;
pub const GL_VERTEX_SHADER: GLenum = 0x8B31;
#[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,
);
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 glClearColor(red: GLfloat, green: GLfloat, blue: GLfloat, alpha: GLfloat);
pub fn glFlush();
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);
pub fn glPixelStorei(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,
);
pub fn glScissor(x: GLint, y: GLint, width: GLsizei, height: GLsizei);
pub fn glEnable(cap: GLenum);
pub fn glDisable(cap: GLenum);
pub fn glViewport(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);
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);
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);
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,
);
pub fn glActiveTexture(texture: GLuint);
pub fn glEnableVertexAttribArray(idx: GLuint);
pub fn glDisableVertexAttribArray(idx: GLuint);
pub fn glDrawArrays(mode: GLenum, first: GLint, count: GLsizei);
}

138
src/render/gl/texture.rs Normal file
View file

@ -0,0 +1,138 @@
use crate::format::Format;
use crate::render::egl::context::EglContext;
use crate::render::gl::frame_buffer::GlFrameBuffer;
use crate::render::gl::sys::{
glBindFramebuffer, glBindTexture, glCheckFramebufferStatus, glDeleteTextures,
glFramebufferTexture2D, glGenFramebuffers, glGenTextures, glPixelStorei, glTexImage2D,
glTexParameteri, GLint, GLuint, GL_CLAMP_TO_EDGE, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER,
GL_FRAMEBUFFER_COMPLETE, GL_LINEAR, GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_UNPACK_ROW_LENGTH_EXT,
};
use crate::render::RenderError;
use std::cell::Cell;
use std::ptr;
use std::rc::Rc;
pub struct GlTexture {
pub(super) ctx: Rc<EglContext>,
pub tex: GLuint,
pub width: i32,
pub height: i32,
}
impl GlTexture {
pub fn new(
ctx: &Rc<EglContext>,
format: &'static Format,
width: i32,
height: i32,
) -> Result<Rc<GlTexture>, RenderError> {
let tex = ctx.with_current(|| unsafe {
let mut tex = 0;
glGenTextures(1, &mut tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(
GL_TEXTURE_2D,
0,
format.gl_format,
width,
height,
0,
format.gl_format as _,
format.gl_type as _,
ptr::null(),
);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
Ok(tex)
})?;
Ok(Rc::new(GlTexture {
ctx: ctx.clone(),
tex,
width,
height,
}))
}
pub unsafe fn to_framebuffer(self: &Rc<Self>) -> Result<Rc<GlFrameBuffer>, RenderError> {
self.ctx.with_current(|| unsafe {
let mut fbo = 0;
glGenFramebuffers(1, &mut fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
self.tex,
0,
);
let fb = GlFrameBuffer {
_rb: None,
_tex: Some(self.clone()),
ctx: self.ctx.clone(),
fbo,
width: self.width,
height: self.height,
};
let status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
if status != GL_FRAMEBUFFER_COMPLETE {
return Err(RenderError::CreateFramebuffer);
}
Ok(Rc::new(fb))
})
}
pub fn import_texture(
ctx: &Rc<EglContext>,
data: &[Cell<u8>],
format: &'static Format,
width: i32,
height: i32,
stride: i32,
) -> Result<GlTexture, RenderError> {
if (stride * height) as usize > data.len() {
return Err(RenderError::SmallImageBuffer);
}
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(
GL_TEXTURE_2D,
0,
format.gl_format,
width,
height,
0,
format.gl_format as _,
format.gl_type as _,
data.as_ptr() as _,
);
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
Ok(tex)
})?;
Ok(GlTexture {
ctx: ctx.clone(),
tex,
width,
height,
})
}
}
impl Drop for GlTexture {
fn drop(&mut self) {
unsafe {
self.ctx.with_current(|| {
glDeleteTextures(1, &self.tex);
Ok(())
});
}
}
}