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,104 @@
use crate::drm::dma::DmaBuf;
use crate::drm::drm::Drm;
use crate::format::{Format, XRGB8888};
use crate::render::egl::context::EglContext;
use crate::render::egl::find_drm_device;
use crate::render::gl::program::GlProgram;
use crate::render::gl::render_buffer::GlRenderBuffer;
use crate::render::gl::sys::GLint;
use crate::render::gl::texture::GlTexture;
use crate::render::renderer::framebuffer::Framebuffer;
use crate::render::renderer::RENDERDOC;
use crate::render::{RenderError, Texture};
use renderdoc::{RenderDoc, V100};
use std::cell::{Cell, RefCell};
use std::rc::Rc;
use uapi::ustr;
pub struct RenderContext {
pub(super) ctx: Rc<EglContext>,
pub(super) renderdoc: Option<RefCell<RenderDoc<V100>>>,
pub(super) tex_prog: GlProgram,
pub(super) tex_prog_pos: GLint,
pub(super) tex_prog_texcoord: GLint,
pub(super) tex_prog_tex: GLint,
pub(super) fill_prog: GlProgram,
pub(super) fill_prog_pos: GLint,
pub(super) fill_prog_color: GLint,
}
impl RenderContext {
pub fn from_drm_device(drm: &Drm) -> Result<Self, RenderError> {
let egl_dev = match find_drm_device(&drm)? {
Some(d) => d,
None => return Err(RenderError::UnknownDrmDevice),
};
let dpy = egl_dev.create_display()?;
if !dpy.formats.contains_key(&XRGB8888.drm) {
return Err(RenderError::XRGB888);
}
let ctx = dpy.create_context()?;
ctx.with_current(|| unsafe { Self::new(&ctx) })
}
unsafe fn new(ctx: &Rc<EglContext>) -> Result<Self, RenderError> {
let tex_prog = GlProgram::from_shaders(
ctx,
include_str!("../shaders/tex.vert.glsl"),
include_str!("../shaders/tex.frag.glsl"),
)?;
let fill_prog = GlProgram::from_shaders(
ctx,
include_str!("../shaders/fill.vert.glsl"),
include_str!("../shaders/fill.frag.glsl"),
)?;
Ok(Self {
ctx: ctx.clone(),
tex_prog_pos: tex_prog.get_attrib_location(ustr!("pos")),
tex_prog_texcoord: tex_prog.get_attrib_location(ustr!("texcoord")),
tex_prog_tex: tex_prog.get_uniform_location(ustr!("tex")),
tex_prog,
fill_prog_pos: fill_prog.get_attrib_location(ustr!("pos")),
fill_prog_color: fill_prog.get_uniform_location(ustr!("color")),
fill_prog,
renderdoc: if RENDERDOC {
Some(RefCell::new(RenderDoc::new().unwrap()))
} else {
None
},
})
}
pub fn dmabuf_fb(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Framebuffer>, RenderError> {
self.ctx.with_current(|| unsafe {
let img = self.ctx.dpy.import_dmabuf(buf)?;
let rb = GlRenderBuffer::from_image(&img, &self.ctx)?;
let fb = rb.create_framebuffer()?;
Ok(Rc::new(Framebuffer {
ctx: self.clone(),
gl: fb,
}))
})
}
pub fn shmem_texture(
self: &Rc<Self>,
data: &[Cell<u8>],
format: &'static Format,
width: i32,
height: i32,
stride: i32,
) -> Result<Rc<Texture>, RenderError> {
let gl = GlTexture::import_texture(&self.ctx, data, format, width, height, stride)?;
Ok(Rc::new(Texture {
ctx: self.clone(),
gl,
}))
}
}

View file

@ -0,0 +1,40 @@
use crate::render::gl::frame_buffer::GlFrameBuffer;
use crate::render::gl::sys::{
glBindFramebuffer, glClear, glClearColor, glViewport, GL_COLOR_BUFFER_BIT, GL_FRAMEBUFFER,
};
use crate::render::renderer::context::RenderContext;
use crate::render::renderer::renderer::Renderer;
use crate::tree::Node;
use std::ptr;
use std::rc::Rc;
pub struct Framebuffer {
pub(super) ctx: Rc<RenderContext>,
pub(super) gl: GlFrameBuffer,
}
impl Framebuffer {
pub fn render(&self, node: &dyn Node) {
let _ = self.ctx.ctx.with_current(|| {
if let Some(rd) = &self.ctx.renderdoc {
rd.borrow_mut()
.start_frame_capture(ptr::null(), ptr::null());
}
unsafe {
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
glViewport(0, 0, self.gl.width, self.gl.height);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
}
let mut renderer = Renderer {
renderer: &self.ctx,
image: &self.gl,
};
node.render(&mut renderer, 0, 0);
if let Some(rd) = &self.ctx.renderdoc {
rd.borrow_mut().end_frame_capture(ptr::null(), ptr::null());
}
Ok(())
});
}
}

View file

@ -0,0 +1,11 @@
pub use context::*;
pub use framebuffer::*;
pub use renderer::*;
pub use texture::*;
mod context;
mod framebuffer;
mod renderer;
mod texture;
pub const RENDERDOC: bool = true;

View file

@ -0,0 +1,280 @@
use crate::ifs::wl_buffer::WlBuffer;
use crate::ifs::wl_surface::xdg_surface::xdg_toplevel::XdgToplevel;
use crate::ifs::wl_surface::WlSurface;
use crate::rect::Rect;
use crate::render::gl::frame_buffer::{with_scissor, GlFrameBuffer};
use crate::render::gl::sys::{
glActiveTexture, glBindTexture, glDisableVertexAttribArray, glDrawArrays,
glEnableVertexAttribArray, glTexParameteri, glUniform1i, glUniform4f, glUseProgram,
glVertexAttribPointer, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP,
};
use crate::render::renderer::context::RenderContext;
use crate::tree::{
ContainerFocus, ContainerNode, ContainerSplit, FloatNode, OutputNode, WorkspaceNode,
CONTAINER_BORDER, CONTAINER_TITLE_HEIGHT,
};
use std::ops::Deref;
use std::rc::Rc;
use std::slice;
const NON_COLOR: (f32, f32, f32) = (0.2, 0.2, 0.2);
const CHILD_COLOR: (f32, f32, f32) = (0.8, 0.8, 0.8);
const YES_COLOR: (f32, f32, f32) = (0.0, 0.0, 1.0);
fn focus_color(focus: ContainerFocus) -> (f32, f32, f32) {
match focus {
ContainerFocus::None => NON_COLOR,
ContainerFocus::Child => CHILD_COLOR,
ContainerFocus::Yes => YES_COLOR,
}
}
pub struct Renderer<'a> {
pub(super) renderer: &'a RenderContext,
pub(super) image: &'a GlFrameBuffer,
}
impl Renderer<'_> {
pub fn render_output(&mut self, output: &OutputNode, x: i32, y: i32) {
if let Some(ws) = output.workspace.get() {
self.render_workspace(&ws, x, y);
}
}
pub fn render_workspace(&mut self, workspace: &WorkspaceNode, x: i32, y: i32) {
if let Some(node) = workspace.container.get() {
self.render_container(&node, x, y)
}
}
fn x_to_f(&self, x: i32) -> f32 {
2.0 * (x as f32 / self.image.width as f32) - 1.0
}
fn y_to_f(&self, y: i32) -> f32 {
2.0 * (y as f32 / self.image.height as f32) - 1.0
}
fn fill_boxes(&self, boxes: &[Rect], r: f32, g: f32, b: f32, a: f32) {
let mut pos = Vec::with_capacity(boxes.len() * 12);
for bx in boxes {
let x1 = self.x_to_f(bx.x1());
let y1 = self.y_to_f(bx.y1());
let x2 = self.x_to_f(bx.x2());
let y2 = self.y_to_f(bx.y2());
pos.extend_from_slice(&[
// triangle 1
x2, y1, // top right
x1, y1, // top left
x1, y2, // bottom left
// triangle 2
x2, y1, // top right
x1, y2, // bottom left
x2, y2, // bottom right
]);
}
unsafe {
glUseProgram(self.renderer.fill_prog.prog);
glUniform4f(self.renderer.fill_prog_color, r, g, b, a);
glVertexAttribPointer(
self.renderer.fill_prog_pos as _,
2,
GL_FLOAT,
GL_FALSE,
0,
pos.as_ptr() as _,
);
glEnableVertexAttribArray(self.renderer.fill_prog_pos as _);
glDrawArrays(GL_TRIANGLES, 0, (boxes.len() * 6) as _);
glDisableVertexAttribArray(self.renderer.fill_prog_pos as _);
}
}
pub fn render_container(&mut self, container: &ContainerNode, x: i32, y: i32) {
let cwidth = container.width.get();
let cheight = container.height.get();
let num_children = container.num_children();
let title_rect =
Rect::new_sized(x, y, container.width.get(), CONTAINER_TITLE_HEIGHT).unwrap();
if let Some(child) = container.mono_child.get() {
let space_per_child = cwidth / num_children as i32;
let mut rem = cwidth % num_children as i32;
let mut pos = x;
let (r, g, b) = focus_color(ContainerFocus::None);
self.fill_boxes(slice::from_ref(&title_rect), r, g, b, 1.0);
for child in container.children.iter() {
let focus = child.focus.get();
let (r, g, b) = focus_color(focus);
let mut width = space_per_child;
if rem > 0 {
rem -= 1;
width += 1;
}
if focus != ContainerFocus::None {
let rect = Rect::new_sized(pos, y, width, CONTAINER_TITLE_HEIGHT).unwrap();
self.fill_boxes(slice::from_ref(&rect), r, g, b, 1.0);
}
pos += width as i32;
}
unsafe {
with_scissor(&container.mono_body.get(), || {
let content = container.mono_content.get();
child.node.render(self, x + content.x1(), y + content.y1());
});
}
} else {
let split = container.split.get();
let mut rects = Vec::with_capacity(num_children);
rects.push(title_rect);
for (i, child) in container.children.iter().enumerate() {
let body = child.body.get();
if i + 1 < num_children {
let rect = if split == ContainerSplit::Horizontal {
Rect::new_sized(
x + body.x2(),
y + body.y1() - CONTAINER_TITLE_HEIGHT,
CONTAINER_BORDER,
container.height.get(),
)
.unwrap()
} else {
Rect::new_sized(
x + body.x1(),
y + body.y2(),
container.width.get(),
CONTAINER_BORDER,
)
.unwrap()
};
rects.push(rect);
}
}
let (r, g, b) = focus_color(ContainerFocus::None);
self.fill_boxes(&rects, r, g, b, 1.0);
for child in container.children.iter() {
let body = child.body.get();
if body.x1() >= cwidth || body.y1() >= cheight {
break;
}
unsafe {
with_scissor(&body, || {
let content = child.content.get();
child.node.render(self, x + content.x1(), y + content.y1());
});
}
}
}
}
pub fn render_toplevel(&mut self, tl: &XdgToplevel, mut x: i32, mut y: i32) {
let surface = &tl.xdg.surface;
if let Some(geo) = tl.xdg.geometry() {
let (xt, yt) = geo.translate(x, y);
x = xt;
y = yt;
}
self.render_surface(surface, x, y);
}
pub fn render_surface(&mut self, surface: &WlSurface, x: i32, y: i32) {
let children = surface.children.borrow();
let buffer = match surface.buffer.get() {
Some(b) => b,
_ => {
log::warn!("surface has no buffer attached");
return;
}
};
if let Some(children) = children.deref() {
macro_rules! render {
($children:expr) => {
for child in $children.rev_iter() {
if child.pending.get() {
continue;
}
let pos = child.sub_surface.position.get();
self.render_surface(&child.sub_surface.surface, x + pos.x1(), y + pos.y1());
}
};
}
render!(&children.above);
self.render_buffer(&buffer, x, y);
render!(&children.below);
} else {
self.render_buffer(&buffer, x, y);
}
let mut fr = surface.frame_requests.borrow_mut();
for cb in fr.drain(..) {
surface.client.dispatch_frame_requests.push(cb);
}
}
pub fn render_buffer(&mut self, buffer: &WlBuffer, x: i32, y: i32) {
let texture = match buffer.texture.get() {
Some(t) => t,
_ => return,
};
assert!(Rc::ptr_eq(&self.renderer.ctx, &texture.ctx.ctx));
unsafe {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.gl.tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glUseProgram(self.renderer.tex_prog.prog);
glUniform1i(self.renderer.tex_prog_tex, 0);
let texcoord: [f32; 8] = [1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0];
let f_width = self.image.width as f32;
let f_height = self.image.height as f32;
let x1 = 2.0 * (x as f32 / f_width) - 1.0;
let y1 = 2.0 * (y as f32 / f_height) - 1.0;
let x2 = 2.0 * ((x + texture.gl.width) as f32 / f_width) - 1.0;
let y2 = 2.0 * ((y + texture.gl.height) as f32 / f_height) - 1.0;
let pos: [f32; 8] = [
x2, y1, // top right
x1, y1, // top left
x2, y2, // bottom right
x1, y2, // bottom left
];
glVertexAttribPointer(
self.renderer.tex_prog_texcoord as _,
2,
GL_FLOAT,
GL_FALSE,
0,
texcoord.as_ptr() as _,
);
glVertexAttribPointer(
self.renderer.tex_prog_pos as _,
2,
GL_FLOAT,
GL_FALSE,
0,
pos.as_ptr() as _,
);
glEnableVertexAttribArray(self.renderer.tex_prog_texcoord as _);
glEnableVertexAttribArray(self.renderer.tex_prog_pos as _);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisableVertexAttribArray(self.renderer.tex_prog_texcoord as _);
glDisableVertexAttribArray(self.renderer.tex_prog_pos as _);
glBindTexture(GL_TEXTURE_2D, 0);
}
}
pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) {
if let Some(child) = floating.child.get() {
child.render(self, x, y)
}
}
}

View file

@ -0,0 +1,8 @@
use crate::render::gl::texture::GlTexture;
use crate::render::renderer::context::RenderContext;
use std::rc::Rc;
pub struct Texture {
pub(super) ctx: Rc<RenderContext>,
pub(super) gl: GlTexture,
}