renderer: add renderer_base
This commit is contained in:
parent
f84b4619ba
commit
163adbd893
5 changed files with 306 additions and 252 deletions
|
|
@ -281,7 +281,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
|
||||||
img.extents.move_(x.round_down(), y.round_down())
|
img.extents.move_(x.round_down(), y.round_down())
|
||||||
};
|
};
|
||||||
if extents.intersects(&renderer.physical_extents()) {
|
if extents.intersects(&renderer.physical_extents()) {
|
||||||
renderer.render_texture(
|
renderer.base.render_texture(
|
||||||
&img.tex,
|
&img.tex,
|
||||||
extents.x1(),
|
extents.x1(),
|
||||||
extents.y1(),
|
extents.y1(),
|
||||||
|
|
@ -300,7 +300,9 @@ impl Cursor for StaticCursor {
|
||||||
|
|
||||||
fn render_hardware_cursor(&self, renderer: &mut Renderer) {
|
fn render_hardware_cursor(&self, renderer: &mut Renderer) {
|
||||||
if let Some(img) = self.image.scales.get(&renderer.scale()) {
|
if let Some(img) = self.image.scales.get(&renderer.scale()) {
|
||||||
renderer.render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale());
|
renderer
|
||||||
|
.base
|
||||||
|
.render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -328,7 +330,9 @@ impl Cursor for AnimatedCursor {
|
||||||
fn render_hardware_cursor(&self, renderer: &mut Renderer) {
|
fn render_hardware_cursor(&self, renderer: &mut Renderer) {
|
||||||
let img = &self.images[self.idx.get()];
|
let img = &self.images[self.idx.get()];
|
||||||
if let Some(img) = img.scales.get(&renderer.scale()) {
|
if let Some(img) = img.scales.get(&renderer.scale()) {
|
||||||
renderer.render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale());
|
renderer
|
||||||
|
.base
|
||||||
|
.render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,4 +4,5 @@ mod context;
|
||||||
mod framebuffer;
|
mod framebuffer;
|
||||||
mod image;
|
mod image;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
|
mod renderer_base;
|
||||||
mod texture;
|
mod texture;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use {
|
||||||
GL_FRAMEBUFFER,
|
GL_FRAMEBUFFER,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
renderer::{context::RenderContext, renderer::Renderer},
|
renderer::{context::RenderContext, renderer::Renderer, renderer_base::RendererBase},
|
||||||
sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
|
sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
|
||||||
RenderResult, Texture,
|
RenderResult, Texture,
|
||||||
},
|
},
|
||||||
|
|
@ -39,11 +39,15 @@ impl Debug for Framebuffer {
|
||||||
|
|
||||||
impl Framebuffer {
|
impl Framebuffer {
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
|
self.clear_with(0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_with(&self, r: f32, g: f32, b: f32, a: f32) {
|
||||||
let _ = self.ctx.ctx.with_current(|| {
|
let _ = self.ctx.ctx.with_current(|| {
|
||||||
unsafe {
|
unsafe {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo);
|
||||||
glViewport(0, 0, self.gl.width, self.gl.height);
|
glViewport(0, 0, self.gl.width, self.gl.height);
|
||||||
glClearColor(0.0, 0.0, 0.0, 0.0);
|
glClearColor(r, g, b, a);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
@ -59,17 +63,21 @@ impl Framebuffer {
|
||||||
}
|
}
|
||||||
let scale = Fixed::from_int(1);
|
let scale = Fixed::from_int(1);
|
||||||
let mut renderer = Renderer {
|
let mut renderer = Renderer {
|
||||||
ctx: &self.ctx,
|
base: RendererBase {
|
||||||
fb: &self.gl,
|
ctx: &self.ctx,
|
||||||
|
fb: &self.gl,
|
||||||
|
scaled: false,
|
||||||
|
scale,
|
||||||
|
scalef: 1.0,
|
||||||
|
},
|
||||||
state,
|
state,
|
||||||
on_output: false,
|
on_output: false,
|
||||||
result: &mut RenderResult::default(),
|
result: &mut RenderResult::default(),
|
||||||
scaled: false,
|
|
||||||
scale,
|
|
||||||
scalef: 1.0,
|
|
||||||
logical_extents: Rect::new_sized(0, 0, self.gl.width, self.gl.height).unwrap(),
|
logical_extents: Rect::new_sized(0, 0, self.gl.width, self.gl.height).unwrap(),
|
||||||
};
|
};
|
||||||
renderer.render_texture(texture, x, y, XRGB8888, None, None, scale);
|
renderer
|
||||||
|
.base
|
||||||
|
.render_texture(texture, x, y, XRGB8888, None, None, scale);
|
||||||
unsafe {
|
unsafe {
|
||||||
glFlush();
|
glFlush();
|
||||||
}
|
}
|
||||||
|
|
@ -126,14 +134,16 @@ impl Framebuffer {
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
}
|
}
|
||||||
let mut renderer = Renderer {
|
let mut renderer = Renderer {
|
||||||
ctx: &self.ctx,
|
base: RendererBase {
|
||||||
fb: &self.gl,
|
ctx: &self.ctx,
|
||||||
|
fb: &self.gl,
|
||||||
|
scaled: scale != 1,
|
||||||
|
scale,
|
||||||
|
scalef: scale.to_f64(),
|
||||||
|
},
|
||||||
state,
|
state,
|
||||||
on_output,
|
on_output,
|
||||||
result,
|
result,
|
||||||
scaled: scale != 1,
|
|
||||||
scale,
|
|
||||||
scalef: scale.to_f64(),
|
|
||||||
logical_extents: node.node_absolute_position().at_point(0, 0),
|
logical_extents: node.node_absolute_position().at_point(0, 0),
|
||||||
};
|
};
|
||||||
node.node_render(&mut renderer, 0, 0);
|
node.node_render(&mut renderer, 0, 0);
|
||||||
|
|
@ -180,14 +190,16 @@ impl Framebuffer {
|
||||||
}
|
}
|
||||||
let mut res = RenderResult::default();
|
let mut res = RenderResult::default();
|
||||||
let mut renderer = Renderer {
|
let mut renderer = Renderer {
|
||||||
ctx: &self.ctx,
|
base: RendererBase {
|
||||||
fb: &self.gl,
|
ctx: &self.ctx,
|
||||||
|
fb: &self.gl,
|
||||||
|
scaled: scale != 1,
|
||||||
|
scale,
|
||||||
|
scalef: scale.to_f64(),
|
||||||
|
},
|
||||||
state,
|
state,
|
||||||
on_output: false,
|
on_output: false,
|
||||||
result: &mut res,
|
result: &mut res,
|
||||||
scaled: scale != 1,
|
|
||||||
scale,
|
|
||||||
scalef: scale.to_f64(),
|
|
||||||
logical_extents: Rect::new_empty(0, 0),
|
logical_extents: Rect::new_empty(0, 0),
|
||||||
};
|
};
|
||||||
cursor.render_hardware_cursor(&mut renderer);
|
cursor.render_hardware_cursor(&mut renderer);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
fixed::Fixed,
|
fixed::Fixed,
|
||||||
format::{Format, ARGB8888},
|
format::ARGB8888,
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_buffer::WlBuffer,
|
wl_buffer::WlBuffer,
|
||||||
wl_callback::WlCallback,
|
wl_callback::WlCallback,
|
||||||
|
|
@ -11,28 +11,13 @@ use {
|
||||||
wp_presentation_feedback::WpPresentationFeedback,
|
wp_presentation_feedback::WpPresentationFeedback,
|
||||||
},
|
},
|
||||||
rect::Rect,
|
rect::Rect,
|
||||||
render::{
|
render::{gl::frame_buffer::with_scissor, renderer::renderer_base::RendererBase},
|
||||||
gl::{
|
|
||||||
frame_buffer::{with_scissor, GlFrameBuffer},
|
|
||||||
sys::{
|
|
||||||
glActiveTexture, glBindTexture, glDisableVertexAttribArray, glDrawArrays,
|
|
||||||
glEnableVertexAttribArray, glTexParameteri, glUniform1i, glUniform4f,
|
|
||||||
glUseProgram, glVertexAttribPointer, GL_FALSE, GL_FLOAT, GL_LINEAR,
|
|
||||||
GL_TEXTURE0, GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
|
||||||
},
|
|
||||||
texture::image_target,
|
|
||||||
},
|
|
||||||
renderer::context::RenderContext,
|
|
||||||
sys::{glDisable, glEnable, GL_BLEND},
|
|
||||||
Texture,
|
|
||||||
},
|
|
||||||
state::State,
|
state::State,
|
||||||
theme::Color,
|
theme::Color,
|
||||||
tree::{
|
tree::{
|
||||||
ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelNode,
|
ContainerNode, DisplayNode, FloatNode, OutputNode, PlaceholderNode, ToplevelNode,
|
||||||
WorkspaceNode,
|
WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::rc_eq::rc_eq,
|
|
||||||
},
|
},
|
||||||
std::{
|
std::{
|
||||||
fmt::{Debug, Formatter},
|
fmt::{Debug, Formatter},
|
||||||
|
|
@ -55,49 +40,26 @@ impl Debug for RenderResult {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Renderer<'a> {
|
pub struct Renderer<'a> {
|
||||||
pub(super) ctx: &'a Rc<RenderContext>,
|
pub base: RendererBase<'a>,
|
||||||
pub(super) fb: &'a GlFrameBuffer,
|
|
||||||
pub(super) state: &'a State,
|
pub(super) state: &'a State,
|
||||||
pub(super) on_output: bool,
|
pub(super) on_output: bool,
|
||||||
pub(super) result: &'a mut RenderResult,
|
pub(super) result: &'a mut RenderResult,
|
||||||
pub(super) scaled: bool,
|
|
||||||
pub(super) scale: Fixed,
|
|
||||||
pub(super) scalef: f64,
|
|
||||||
pub(super) logical_extents: Rect,
|
pub(super) logical_extents: Rect,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer<'_> {
|
impl Renderer<'_> {
|
||||||
pub fn scale(&self) -> Fixed {
|
pub fn scale(&self) -> Fixed {
|
||||||
self.scale
|
self.base.scale
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn physical_extents(&self) -> Rect {
|
pub fn physical_extents(&self) -> Rect {
|
||||||
Rect::new_sized(0, 0, self.fb.width, self.fb.height).unwrap()
|
self.base.physical_extents()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn logical_extents(&self) -> Rect {
|
pub fn logical_extents(&self) -> Rect {
|
||||||
self.logical_extents
|
self.logical_extents
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) {
|
|
||||||
if self.scaled {
|
|
||||||
x = (x as f64 * self.scalef).round() as _;
|
|
||||||
y = (y as f64 * self.scalef).round() as _;
|
|
||||||
}
|
|
||||||
(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn scale_rect(&self, mut rect: Rect) -> Rect {
|
|
||||||
if self.scaled {
|
|
||||||
let x1 = (rect.x1() as f64 * self.scalef).round() as _;
|
|
||||||
let y1 = (rect.y1() as f64 * self.scalef).round() as _;
|
|
||||||
let x2 = (rect.x2() as f64 * self.scalef).round() as _;
|
|
||||||
let y2 = (rect.y2() as f64 * self.scalef).round() as _;
|
|
||||||
rect = Rect::new(x1, y1, x2, y2).unwrap();
|
|
||||||
}
|
|
||||||
rect
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_display(&mut self, display: &DisplayNode, x: i32, y: i32) {
|
pub fn render_display(&mut self, display: &DisplayNode, x: i32, y: i32) {
|
||||||
let ext = display.extents.get();
|
let ext = display.extents.get();
|
||||||
let outputs = display.outputs.lock();
|
let outputs = display.outputs.lock();
|
||||||
|
|
@ -142,7 +104,7 @@ impl Renderer<'_> {
|
||||||
let th = theme.sizes.title_height.get();
|
let th = theme.sizes.title_height.get();
|
||||||
{
|
{
|
||||||
let c = theme.colors.bar_background.get();
|
let c = theme.colors.bar_background.get();
|
||||||
self.fill_boxes2(
|
self.base.fill_boxes2(
|
||||||
slice::from_ref(&Rect::new_sized(0, 0, opos.width(), th).unwrap()),
|
slice::from_ref(&Rect::new_sized(0, 0, opos.width(), th).unwrap()),
|
||||||
&c,
|
&c,
|
||||||
x,
|
x,
|
||||||
|
|
@ -151,20 +113,23 @@ impl Renderer<'_> {
|
||||||
let rd = output.render_data.borrow_mut();
|
let rd = output.render_data.borrow_mut();
|
||||||
if let Some(aw) = &rd.active_workspace {
|
if let Some(aw) = &rd.active_workspace {
|
||||||
let c = theme.colors.focused_title_background.get();
|
let c = theme.colors.focused_title_background.get();
|
||||||
self.fill_boxes2(slice::from_ref(aw), &c, x, y);
|
self.base.fill_boxes2(slice::from_ref(aw), &c, x, y);
|
||||||
}
|
}
|
||||||
let c = theme.colors.separator.get();
|
let c = theme.colors.separator.get();
|
||||||
self.fill_boxes2(slice::from_ref(&rd.underline), &c, x, y);
|
self.base
|
||||||
|
.fill_boxes2(slice::from_ref(&rd.underline), &c, x, y);
|
||||||
let c = theme.colors.unfocused_title_background.get();
|
let c = theme.colors.unfocused_title_background.get();
|
||||||
self.fill_boxes2(&rd.inactive_workspaces, &c, x, y);
|
self.base.fill_boxes2(&rd.inactive_workspaces, &c, x, y);
|
||||||
let scale = output.preferred_scale.get();
|
let scale = output.preferred_scale.get();
|
||||||
for title in &rd.titles {
|
for title in &rd.titles {
|
||||||
let (x, y) = self.scale_point(x + title.tex_x, y + title.tex_y);
|
let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y);
|
||||||
self.render_texture(&title.tex, x, y, ARGB8888, None, None, scale);
|
self.base
|
||||||
|
.render_texture(&title.tex, x, y, ARGB8888, None, None, scale);
|
||||||
}
|
}
|
||||||
if let Some(status) = &rd.status {
|
if let Some(status) = &rd.status {
|
||||||
let (x, y) = self.scale_point(x + status.tex_x, y + status.tex_y);
|
let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y);
|
||||||
self.render_texture(&status.tex, x, y, ARGB8888, None, None, scale);
|
self.base
|
||||||
|
.render_texture(&status.tex, x, y, ARGB8888, None, None, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ws) = output.workspace.get() {
|
if let Some(ws) = output.workspace.get() {
|
||||||
|
|
@ -189,68 +154,17 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn x_to_f(&self, x: i32) -> f32 {
|
|
||||||
2.0 * (x as f32 / self.fb.width as f32) - 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn y_to_f(&self, y: i32) -> f32 {
|
|
||||||
2.0 * (y as f32 / self.fb.height as f32) - 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_boxes(&self, boxes: &[Rect], color: &Color) {
|
|
||||||
self.fill_boxes2(boxes, color, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_boxes2(&self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) {
|
|
||||||
if boxes.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let (dx, dy) = self.scale_point(dx, dy);
|
|
||||||
let mut pos = Vec::with_capacity(boxes.len() * 12);
|
|
||||||
for bx in boxes {
|
|
||||||
let bx = self.scale_rect(*bx);
|
|
||||||
let x1 = self.x_to_f(bx.x1() + dx);
|
|
||||||
let y1 = self.y_to_f(bx.y1() + dy);
|
|
||||||
let x2 = self.x_to_f(bx.x2() + dx);
|
|
||||||
let y2 = self.y_to_f(bx.y2() + dy);
|
|
||||||
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.ctx.fill_prog.prog);
|
|
||||||
glUniform4f(self.ctx.fill_prog_color, color.r, color.g, color.b, color.a);
|
|
||||||
glVertexAttribPointer(
|
|
||||||
self.ctx.fill_prog_pos as _,
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
0,
|
|
||||||
pos.as_ptr() as _,
|
|
||||||
);
|
|
||||||
glEnableVertexAttribArray(self.ctx.fill_prog_pos as _);
|
|
||||||
glDrawArrays(GL_TRIANGLES, 0, (boxes.len() * 6) as _);
|
|
||||||
glDisableVertexAttribArray(self.ctx.fill_prog_pos as _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_placeholder(&mut self, placeholder: &PlaceholderNode, x: i32, y: i32) {
|
pub fn render_placeholder(&mut self, placeholder: &PlaceholderNode, x: i32, y: i32) {
|
||||||
let pos = placeholder.tl_data().pos.get();
|
let pos = placeholder.tl_data().pos.get();
|
||||||
self.fill_boxes(
|
self.base.fill_boxes(
|
||||||
std::slice::from_ref(&pos.at_point(x, y)),
|
std::slice::from_ref(&pos.at_point(x, y)),
|
||||||
&Color::from_rgba_straight(20, 20, 20, 255),
|
&Color::from_rgba_straight(20, 20, 20, 255),
|
||||||
);
|
);
|
||||||
if let Some(tex) = placeholder.textures.get(&self.scale) {
|
if let Some(tex) = placeholder.textures.get(&self.base.scale) {
|
||||||
let x = x + (pos.width() - tex.width()) / 2;
|
let x = x + (pos.width() - tex.width()) / 2;
|
||||||
let y = y + (pos.height() - tex.height()) / 2;
|
let y = y + (pos.height() - tex.height()) / 2;
|
||||||
self.render_texture(&tex, x, y, &ARGB8888, None, None, self.scale);
|
self.base
|
||||||
|
.render_texture(&tex, x, y, &ARGB8888, None, None, self.base.scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,13 +172,13 @@ impl Renderer<'_> {
|
||||||
{
|
{
|
||||||
let rd = container.render_data.borrow_mut();
|
let rd = container.render_data.borrow_mut();
|
||||||
let c = self.state.theme.colors.unfocused_title_background.get();
|
let c = self.state.theme.colors.unfocused_title_background.get();
|
||||||
self.fill_boxes2(&rd.title_rects, &c, x, y);
|
self.base.fill_boxes2(&rd.title_rects, &c, x, y);
|
||||||
let c = self.state.theme.colors.focused_title_background.get();
|
let c = self.state.theme.colors.focused_title_background.get();
|
||||||
self.fill_boxes2(&rd.active_title_rects, &c, x, y);
|
self.base.fill_boxes2(&rd.active_title_rects, &c, x, y);
|
||||||
let c = self.state.theme.colors.separator.get();
|
let c = self.state.theme.colors.separator.get();
|
||||||
self.fill_boxes2(&rd.underline_rects, &c, x, y);
|
self.base.fill_boxes2(&rd.underline_rects, &c, x, y);
|
||||||
let c = self.state.theme.colors.border.get();
|
let c = self.state.theme.colors.border.get();
|
||||||
self.fill_boxes2(&rd.border_rects, &c, x, y);
|
self.base.fill_boxes2(&rd.border_rects, &c, x, y);
|
||||||
if let Some(lar) = &rd.last_active_rect {
|
if let Some(lar) = &rd.last_active_rect {
|
||||||
let c = self
|
let c = self
|
||||||
.state
|
.state
|
||||||
|
|
@ -272,19 +186,27 @@ impl Renderer<'_> {
|
||||||
.colors
|
.colors
|
||||||
.focused_inactive_title_background
|
.focused_inactive_title_background
|
||||||
.get();
|
.get();
|
||||||
self.fill_boxes2(std::slice::from_ref(lar), &c, x, y);
|
self.base.fill_boxes2(std::slice::from_ref(lar), &c, x, y);
|
||||||
}
|
}
|
||||||
if let Some(titles) = rd.titles.get(&self.scale) {
|
if let Some(titles) = rd.titles.get(&self.base.scale) {
|
||||||
for title in titles {
|
for title in titles {
|
||||||
let (x, y) = self.scale_point(x + title.x, y + title.y);
|
let (x, y) = self.base.scale_point(x + title.x, y + title.y);
|
||||||
self.render_texture(&title.tex, x, y, ARGB8888, None, None, self.scale);
|
self.base.render_texture(
|
||||||
|
&title.tex,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
ARGB8888,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
self.base.scale,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(child) = container.mono_child.get() {
|
if let Some(child) = container.mono_child.get() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let body = container.mono_body.get().move_(x, y);
|
let body = container.mono_body.get().move_(x, y);
|
||||||
let body = self.scale_rect(body);
|
let body = self.base.scale_rect(body);
|
||||||
with_scissor(&body, || {
|
with_scissor(&body, || {
|
||||||
let content = container.mono_content.get();
|
let content = container.mono_content.get();
|
||||||
child
|
child
|
||||||
|
|
@ -299,7 +221,7 @@ impl Renderer<'_> {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
let body = body.move_(x, y);
|
let body = body.move_(x, y);
|
||||||
let body = self.scale_rect(body);
|
let body = self.base.scale_rect(body);
|
||||||
unsafe {
|
unsafe {
|
||||||
with_scissor(&body, || {
|
with_scissor(&body, || {
|
||||||
let content = child.content.get();
|
let content = child.content.get();
|
||||||
|
|
@ -323,7 +245,7 @@ impl Renderer<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_surface(&mut self, surface: &WlSurface, x: i32, y: i32) {
|
pub fn render_surface(&mut self, surface: &WlSurface, x: i32, y: i32) {
|
||||||
let (x, y) = self.scale_point(x, y);
|
let (x, y) = self.base.scale_point(x, y);
|
||||||
self.render_surface_scaled(surface, x, y, None);
|
self.render_surface_scaled(surface, x, y, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,11 +269,11 @@ impl Renderer<'_> {
|
||||||
let tpoints = surface.buffer_points_norm.borrow_mut();
|
let tpoints = surface.buffer_points_norm.borrow_mut();
|
||||||
let mut size = surface.buffer_abs_pos.get().size();
|
let mut size = surface.buffer_abs_pos.get().size();
|
||||||
if let Some((x_rel, y_rel)) = pos_rel {
|
if let Some((x_rel, y_rel)) = pos_rel {
|
||||||
let (x, y) = self.scale_point(x_rel, y_rel);
|
let (x, y) = self.base.scale_point(x_rel, y_rel);
|
||||||
let (w, h) = self.scale_point(x_rel + size.0, y_rel + size.1);
|
let (w, h) = self.base.scale_point(x_rel + size.0, y_rel + size.1);
|
||||||
size = (w - x, h - y);
|
size = (w - x, h - y);
|
||||||
} else {
|
} else {
|
||||||
size = self.scale_point(size.0, size.1);
|
size = self.base.scale_point(size.0, size.1);
|
||||||
}
|
}
|
||||||
if let Some(children) = children.deref() {
|
if let Some(children) = children.deref() {
|
||||||
macro_rules! render {
|
macro_rules! render {
|
||||||
|
|
@ -361,7 +283,7 @@ impl Renderer<'_> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let pos = child.sub_surface.position.get();
|
let pos = child.sub_surface.position.get();
|
||||||
let (x1, y1) = self.scale_point(pos.x1(), pos.y1());
|
let (x1, y1) = self.base.scale_point(pos.x1(), pos.y1());
|
||||||
self.render_surface_scaled(
|
self.render_surface_scaled(
|
||||||
&child.sub_surface.surface,
|
&child.sub_surface.surface,
|
||||||
x + x1,
|
x + x1,
|
||||||
|
|
@ -398,118 +320,18 @@ impl Renderer<'_> {
|
||||||
tsize: (i32, i32),
|
tsize: (i32, i32),
|
||||||
) {
|
) {
|
||||||
if let Some(tex) = buffer.texture.get() {
|
if let Some(tex) = buffer.texture.get() {
|
||||||
self.render_texture(
|
self.base.render_texture(
|
||||||
&tex,
|
&tex,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
buffer.format,
|
buffer.format,
|
||||||
Some(tpoints),
|
Some(tpoints),
|
||||||
Some(tsize),
|
Some(tsize),
|
||||||
self.scale,
|
self.base.scale,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_texture(
|
|
||||||
&mut self,
|
|
||||||
texture: &Texture,
|
|
||||||
x: i32,
|
|
||||||
y: i32,
|
|
||||||
format: &Format,
|
|
||||||
tpoints: Option<&[f32; 8]>,
|
|
||||||
tsize: Option<(i32, i32)>,
|
|
||||||
tscale: Fixed,
|
|
||||||
) {
|
|
||||||
assert!(rc_eq(&self.ctx.ctx, &texture.ctx.ctx));
|
|
||||||
unsafe {
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
|
|
||||||
let target = image_target(texture.gl.external_only);
|
|
||||||
|
|
||||||
glBindTexture(target, texture.gl.tex);
|
|
||||||
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
||||||
|
|
||||||
let progs = match texture.gl.external_only {
|
|
||||||
true => match &self.ctx.tex_external {
|
|
||||||
Some(p) => p,
|
|
||||||
_ => {
|
|
||||||
log::error!("Trying to render an external-only texture but context does not support the required extension");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
false => &self.ctx.tex_internal,
|
|
||||||
};
|
|
||||||
let prog = match format.has_alpha {
|
|
||||||
true => {
|
|
||||||
glEnable(GL_BLEND);
|
|
||||||
&progs.alpha
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
glDisable(GL_BLEND);
|
|
||||||
&progs.solid
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
glUseProgram(prog.prog.prog);
|
|
||||||
|
|
||||||
glUniform1i(prog.tex, 0);
|
|
||||||
|
|
||||||
static DEFAULT_TEXCOORD: [f32; 8] = [1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0];
|
|
||||||
|
|
||||||
let texcoord: &[f32; 8] = match tpoints {
|
|
||||||
None => &DEFAULT_TEXCOORD,
|
|
||||||
Some(tp) => tp,
|
|
||||||
};
|
|
||||||
|
|
||||||
let f_width = self.fb.width as f32;
|
|
||||||
let f_height = self.fb.height as f32;
|
|
||||||
|
|
||||||
let (twidth, theight) = if let Some(size) = tsize {
|
|
||||||
size
|
|
||||||
} else {
|
|
||||||
let (mut w, mut h) = (texture.gl.width, texture.gl.height);
|
|
||||||
if tscale != self.scale {
|
|
||||||
let tscale = tscale.to_f64();
|
|
||||||
w = (w as f64 * self.scalef / tscale).round() as _;
|
|
||||||
h = (h as f64 * self.scalef / tscale).round() as _;
|
|
||||||
}
|
|
||||||
(w, h)
|
|
||||||
};
|
|
||||||
|
|
||||||
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 + twidth) as f32 / f_width) - 1.0;
|
|
||||||
let y2 = 2.0 * ((y + theight) 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(
|
|
||||||
prog.texcoord as _,
|
|
||||||
2,
|
|
||||||
GL_FLOAT,
|
|
||||||
GL_FALSE,
|
|
||||||
0,
|
|
||||||
texcoord.as_ptr() as _,
|
|
||||||
);
|
|
||||||
glVertexAttribPointer(prog.pos as _, 2, GL_FLOAT, GL_FALSE, 0, pos.as_ptr() as _);
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(prog.texcoord as _);
|
|
||||||
glEnableVertexAttribArray(prog.pos as _);
|
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
|
|
||||||
glDisableVertexAttribArray(prog.texcoord as _);
|
|
||||||
glDisableVertexAttribArray(prog.pos as _);
|
|
||||||
|
|
||||||
glBindTexture(target, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) {
|
pub fn render_floating(&mut self, floating: &FloatNode, x: i32, y: i32) {
|
||||||
let child = match floating.child.get() {
|
let child = match floating.child.get() {
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
|
|
@ -531,15 +353,16 @@ impl Renderer<'_> {
|
||||||
Rect::new_sized(x + pos.width() - bw, y + bw, bw, pos.height() - bw).unwrap(),
|
Rect::new_sized(x + pos.width() - bw, y + bw, bw, pos.height() - bw).unwrap(),
|
||||||
Rect::new_sized(x + bw, y + pos.height() - bw, pos.width() - 2 * bw, bw).unwrap(),
|
Rect::new_sized(x + bw, y + pos.height() - bw, pos.width() - 2 * bw, bw).unwrap(),
|
||||||
];
|
];
|
||||||
self.fill_boxes(&borders, &bc);
|
self.base.fill_boxes(&borders, &bc);
|
||||||
let title = [Rect::new_sized(x + bw, y + bw, pos.width() - 2 * bw, th).unwrap()];
|
let title = [Rect::new_sized(x + bw, y + bw, pos.width() - 2 * bw, th).unwrap()];
|
||||||
self.fill_boxes(&title, &tc);
|
self.base.fill_boxes(&title, &tc);
|
||||||
let title_underline =
|
let title_underline =
|
||||||
[Rect::new_sized(x + bw, y + bw + th, pos.width() - 2 * bw, 1).unwrap()];
|
[Rect::new_sized(x + bw, y + bw + th, pos.width() - 2 * bw, 1).unwrap()];
|
||||||
self.fill_boxes(&title_underline, &uc);
|
self.base.fill_boxes(&title_underline, &uc);
|
||||||
if let Some(title) = floating.title_textures.get(&self.scale) {
|
if let Some(title) = floating.title_textures.get(&self.base.scale) {
|
||||||
let (x, y) = self.scale_point(x + bw, y + bw);
|
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
||||||
self.render_texture(&title, x, y, ARGB8888, None, None, self.scale);
|
self.base
|
||||||
|
.render_texture(&title, x, y, ARGB8888, None, None, self.base.scale);
|
||||||
}
|
}
|
||||||
let body = Rect::new_sized(
|
let body = Rect::new_sized(
|
||||||
x + bw,
|
x + bw,
|
||||||
|
|
@ -548,7 +371,7 @@ impl Renderer<'_> {
|
||||||
pos.height() - 2 * bw - th - 1,
|
pos.height() - 2 * bw - th - 1,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let scissor_body = self.scale_rect(body);
|
let scissor_body = self.base.scale_rect(body);
|
||||||
unsafe {
|
unsafe {
|
||||||
with_scissor(&scissor_body, || {
|
with_scissor(&scissor_body, || {
|
||||||
child.node_render(self, body.x1(), body.y1());
|
child.node_render(self, body.x1(), body.y1());
|
||||||
|
|
@ -559,7 +382,7 @@ impl Renderer<'_> {
|
||||||
pub fn render_layer_surface(&mut self, surface: &ZwlrLayerSurfaceV1, x: i32, y: i32) {
|
pub fn render_layer_surface(&mut self, surface: &ZwlrLayerSurfaceV1, x: i32, y: i32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let body = surface.position().at_point(x, y);
|
let body = surface.position().at_point(x, y);
|
||||||
let body = self.scale_rect(body);
|
let body = self.base.scale_rect(body);
|
||||||
with_scissor(&body, || {
|
with_scissor(&body, || {
|
||||||
self.render_surface(&surface.surface, x, y);
|
self.render_surface(&surface.surface, x, y);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
214
src/render/renderer/renderer_base.rs
Normal file
214
src/render/renderer/renderer_base.rs
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
fixed::Fixed,
|
||||||
|
format::Format,
|
||||||
|
rect::Rect,
|
||||||
|
render::{
|
||||||
|
gl::{
|
||||||
|
frame_buffer::GlFrameBuffer,
|
||||||
|
sys::{
|
||||||
|
glActiveTexture, glBindTexture, glDisableVertexAttribArray, glDrawArrays,
|
||||||
|
glEnableVertexAttribArray, glTexParameteri, glUniform1i, glUniform4f,
|
||||||
|
glUseProgram, glVertexAttribPointer, GL_FALSE, GL_FLOAT, GL_LINEAR,
|
||||||
|
GL_TEXTURE0, GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
||||||
|
},
|
||||||
|
texture::image_target,
|
||||||
|
},
|
||||||
|
renderer::context::RenderContext,
|
||||||
|
sys::{glDisable, glEnable, GL_BLEND},
|
||||||
|
Texture,
|
||||||
|
},
|
||||||
|
theme::Color,
|
||||||
|
utils::rc_eq::rc_eq,
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct RendererBase<'a> {
|
||||||
|
pub(super) ctx: &'a Rc<RenderContext>,
|
||||||
|
pub(super) fb: &'a GlFrameBuffer,
|
||||||
|
pub(super) scaled: bool,
|
||||||
|
pub(super) scale: Fixed,
|
||||||
|
pub(super) scalef: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RendererBase<'_> {
|
||||||
|
pub fn physical_extents(&self) -> Rect {
|
||||||
|
Rect::new_sized(0, 0, self.fb.width, self.fb.height).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) {
|
||||||
|
if self.scaled {
|
||||||
|
x = (x as f64 * self.scalef).round() as _;
|
||||||
|
y = (y as f64 * self.scalef).round() as _;
|
||||||
|
}
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn scale_rect(&self, mut rect: Rect) -> Rect {
|
||||||
|
if self.scaled {
|
||||||
|
let x1 = (rect.x1() as f64 * self.scalef).round() as _;
|
||||||
|
let y1 = (rect.y1() as f64 * self.scalef).round() as _;
|
||||||
|
let x2 = (rect.x2() as f64 * self.scalef).round() as _;
|
||||||
|
let y2 = (rect.y2() as f64 * self.scalef).round() as _;
|
||||||
|
rect = Rect::new(x1, y1, x2, y2).unwrap();
|
||||||
|
}
|
||||||
|
rect
|
||||||
|
}
|
||||||
|
|
||||||
|
fn x_to_f(&self, x: i32) -> f32 {
|
||||||
|
2.0 * (x as f32 / self.fb.width as f32) - 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn y_to_f(&self, y: i32) -> f32 {
|
||||||
|
2.0 * (y as f32 / self.fb.height as f32) - 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_boxes(&self, boxes: &[Rect], color: &Color) {
|
||||||
|
self.fill_boxes2(boxes, color, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fill_boxes2(&self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) {
|
||||||
|
if boxes.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (dx, dy) = self.scale_point(dx, dy);
|
||||||
|
let mut pos = Vec::with_capacity(boxes.len() * 12);
|
||||||
|
for bx in boxes {
|
||||||
|
let bx = self.scale_rect(*bx);
|
||||||
|
let x1 = self.x_to_f(bx.x1() + dx);
|
||||||
|
let y1 = self.y_to_f(bx.y1() + dy);
|
||||||
|
let x2 = self.x_to_f(bx.x2() + dx);
|
||||||
|
let y2 = self.y_to_f(bx.y2() + dy);
|
||||||
|
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
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
self.fill_boxes3(&pos, color)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_boxes3(&self, boxes: &[f32], color: &Color) {
|
||||||
|
unsafe {
|
||||||
|
glUseProgram(self.ctx.fill_prog.prog);
|
||||||
|
glUniform4f(self.ctx.fill_prog_color, color.r, color.g, color.b, color.a);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
self.ctx.fill_prog_pos as _,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
0,
|
||||||
|
boxes.as_ptr() as _,
|
||||||
|
);
|
||||||
|
glEnableVertexAttribArray(self.ctx.fill_prog_pos as _);
|
||||||
|
glDrawArrays(GL_TRIANGLES, 0, (boxes.len() / 2) as _);
|
||||||
|
glDisableVertexAttribArray(self.ctx.fill_prog_pos as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_texture(
|
||||||
|
&mut self,
|
||||||
|
texture: &Texture,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
format: &Format,
|
||||||
|
tpoints: Option<&[f32; 8]>,
|
||||||
|
tsize: Option<(i32, i32)>,
|
||||||
|
tscale: Fixed,
|
||||||
|
) {
|
||||||
|
assert!(rc_eq(&self.ctx.ctx, &texture.ctx.ctx));
|
||||||
|
unsafe {
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
let target = image_target(texture.gl.external_only);
|
||||||
|
|
||||||
|
glBindTexture(target, texture.gl.tex);
|
||||||
|
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
|
||||||
|
let progs = match texture.gl.external_only {
|
||||||
|
true => match &self.ctx.tex_external {
|
||||||
|
Some(p) => p,
|
||||||
|
_ => {
|
||||||
|
log::error!("Trying to render an external-only texture but context does not support the required extension");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false => &self.ctx.tex_internal,
|
||||||
|
};
|
||||||
|
let prog = match format.has_alpha {
|
||||||
|
true => {
|
||||||
|
glEnable(GL_BLEND);
|
||||||
|
&progs.alpha
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
&progs.solid
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
glUseProgram(prog.prog.prog);
|
||||||
|
|
||||||
|
glUniform1i(prog.tex, 0);
|
||||||
|
|
||||||
|
static DEFAULT_TEXCOORD: [f32; 8] = [1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0];
|
||||||
|
|
||||||
|
let texcoord: &[f32; 8] = match tpoints {
|
||||||
|
None => &DEFAULT_TEXCOORD,
|
||||||
|
Some(tp) => tp,
|
||||||
|
};
|
||||||
|
|
||||||
|
let f_width = self.fb.width as f32;
|
||||||
|
let f_height = self.fb.height as f32;
|
||||||
|
|
||||||
|
let (twidth, theight) = if let Some(size) = tsize {
|
||||||
|
size
|
||||||
|
} else {
|
||||||
|
let (mut w, mut h) = (texture.gl.width, texture.gl.height);
|
||||||
|
if tscale != self.scale {
|
||||||
|
let tscale = tscale.to_f64();
|
||||||
|
w = (w as f64 * self.scalef / tscale).round() as _;
|
||||||
|
h = (h as f64 * self.scalef / tscale).round() as _;
|
||||||
|
}
|
||||||
|
(w, h)
|
||||||
|
};
|
||||||
|
|
||||||
|
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 + twidth) as f32 / f_width) - 1.0;
|
||||||
|
let y2 = 2.0 * ((y + theight) 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(
|
||||||
|
prog.texcoord as _,
|
||||||
|
2,
|
||||||
|
GL_FLOAT,
|
||||||
|
GL_FALSE,
|
||||||
|
0,
|
||||||
|
texcoord.as_ptr() as _,
|
||||||
|
);
|
||||||
|
glVertexAttribPointer(prog.pos as _, 2, GL_FLOAT, GL_FALSE, 0, pos.as_ptr() as _);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(prog.texcoord as _);
|
||||||
|
glEnableVertexAttribArray(prog.pos as _);
|
||||||
|
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(prog.texcoord as _);
|
||||||
|
glDisableVertexAttribArray(prog.pos as _);
|
||||||
|
|
||||||
|
glBindTexture(target, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue