Merge pull request #135 from mahkoh/jorth/alpha-multiplier
wayland: implement alpha_modifier_v1
This commit is contained in:
commit
47d1dffd37
37 changed files with 655 additions and 89 deletions
|
|
@ -16,4 +16,5 @@ tasks:
|
||||||
- test: |
|
- test: |
|
||||||
cd jay
|
cd jay
|
||||||
export RUST_BACKTRACE=1
|
export RUST_BACKTRACE=1
|
||||||
|
export GALLIUM_DRIVER=softpipe
|
||||||
./target/debug/jay run-tests
|
./target/debug/jay run-tests
|
||||||
|
|
|
||||||
21
Cargo.lock
generated
21
Cargo.lock
generated
|
|
@ -314,6 +314,26 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-map"
|
||||||
|
version = "2.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
|
||||||
|
dependencies = [
|
||||||
|
"enum-map-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "enum-map-derive"
|
||||||
|
version = "0.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.48",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -516,6 +536,7 @@ dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
"enum-map",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"gpu-alloc",
|
"gpu-alloc",
|
||||||
"gpu-alloc-ash",
|
"gpu-alloc-ash",
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ ash = "0.37.3"
|
||||||
gpu-alloc = "0.6.0"
|
gpu-alloc = "0.6.0"
|
||||||
gpu-alloc-ash = "0.6.0"
|
gpu-alloc-ash = "0.6.0"
|
||||||
serde = { version = "1.0.196", features = ["derive"] }
|
serde = { version = "1.0.196", features = ["derive"] }
|
||||||
|
enum-map = "2.7.3"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
repc = "0.1.1"
|
repc = "0.1.1"
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::open,
|
crate::open,
|
||||||
anyhow::{bail, Context},
|
anyhow::{bail, Context},
|
||||||
|
shaderc::CompileOptions,
|
||||||
std::{io::Write, path::Path},
|
std::{io::Write, path::Path},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -8,15 +9,32 @@ const ROOT: &str = "src/gfx_apis/vulkan/shaders";
|
||||||
|
|
||||||
pub fn main() -> anyhow::Result<()> {
|
pub fn main() -> anyhow::Result<()> {
|
||||||
println!("cargo:rerun-if-changed={}", ROOT);
|
println!("cargo:rerun-if-changed={}", ROOT);
|
||||||
for shader in std::fs::read_dir(ROOT)? {
|
compile_simple("fill.frag")?;
|
||||||
let shader = shader?;
|
compile_simple("fill.vert")?;
|
||||||
let name = shader.file_name().to_string_lossy().into_owned();
|
compile_simple("tex.vert")?;
|
||||||
compile_shader(&name).context(name)?;
|
compile_tex_frag("tex.frag.spv", false, false)?;
|
||||||
}
|
compile_tex_frag("tex.frag.mult+opaque.spv", false, true)?;
|
||||||
|
compile_tex_frag("tex.frag.mult+alpha.spv", true, true)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compile_shader(name: &str) -> anyhow::Result<()> {
|
fn compile_tex_frag(out: &str, alpha: bool, alpha_multiplier: bool) -> anyhow::Result<()> {
|
||||||
|
let mut opts = CompileOptions::new().unwrap();
|
||||||
|
if alpha {
|
||||||
|
opts.add_macro_definition("ALPHA", None);
|
||||||
|
}
|
||||||
|
if alpha_multiplier {
|
||||||
|
opts.add_macro_definition("ALPHA_MULTIPLIER", None);
|
||||||
|
}
|
||||||
|
compile_shader("tex.frag", out, Some(&opts)).with_context(|| out.to_string())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_simple(name: &str) -> anyhow::Result<()> {
|
||||||
|
compile_shader(name, &format!("{name}.spv"), None).with_context(|| name.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_shader(name: &str, out: &str, options: Option<&CompileOptions>) -> anyhow::Result<()> {
|
||||||
let stage = match Path::new(name)
|
let stage = match Path::new(name)
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|e| e.to_str())
|
.and_then(|e| e.to_str())
|
||||||
|
|
@ -29,9 +47,9 @@ fn compile_shader(name: &str) -> anyhow::Result<()> {
|
||||||
let src = std::fs::read_to_string(format!("{}/{}", ROOT, name))?;
|
let src = std::fs::read_to_string(format!("{}/{}", ROOT, name))?;
|
||||||
let compiler = shaderc::Compiler::new().unwrap();
|
let compiler = shaderc::Compiler::new().unwrap();
|
||||||
let binary = compiler
|
let binary = compiler
|
||||||
.compile_into_spirv(&src, stage, name, "main", None)
|
.compile_into_spirv(&src, stage, name, "main", options)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let mut file = open(&format!("{}.spv", name))?;
|
let mut file = open(out)?;
|
||||||
file.write_all(binary.as_binary_u8())?;
|
file.write_all(binary.as_binary_u8())?;
|
||||||
file.flush()?;
|
file.flush()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -426,6 +426,10 @@ impl MetalConnector {
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
if ct.alpha.is_some() {
|
||||||
|
// Direct scanout with alpha factor is not supported.
|
||||||
|
return None;
|
||||||
|
}
|
||||||
if !ct.tex.format().has_alpha && ct.target.is_covering() {
|
if !ct.tex.format().has_alpha && ct.target.is_covering() {
|
||||||
// Texture covers the entire screen and is opaque.
|
// Texture covers the entire screen and is opaque.
|
||||||
break 'ct ct;
|
break 'ct ct;
|
||||||
|
|
|
||||||
|
|
@ -377,6 +377,7 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed
|
||||||
if extents.intersects(&renderer.pixel_extents()) {
|
if extents.intersects(&renderer.pixel_extents()) {
|
||||||
renderer.base.render_texture(
|
renderer.base.render_texture(
|
||||||
&img.tex,
|
&img.tex,
|
||||||
|
None,
|
||||||
extents.x1(),
|
extents.x1(),
|
||||||
extents.y1(),
|
extents.y1(),
|
||||||
None,
|
None,
|
||||||
|
|
@ -399,6 +400,7 @@ impl Cursor for StaticCursor {
|
||||||
if let Some(img) = self.image.scales.get(&renderer.scale()) {
|
if let Some(img) = self.image.scales.get(&renderer.scale()) {
|
||||||
renderer.base.render_texture(
|
renderer.base.render_texture(
|
||||||
&img.tex,
|
&img.tex,
|
||||||
|
None,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
|
|
@ -438,6 +440,7 @@ impl Cursor for AnimatedCursor {
|
||||||
if let Some(img) = img.scales.get(&renderer.scale()) {
|
if let Some(img) = img.scales.get(&renderer.scale()) {
|
||||||
renderer.base.render_texture(
|
renderer.base.render_texture(
|
||||||
&img.tex,
|
&img.tex,
|
||||||
|
None,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ pub struct CopyTexture {
|
||||||
pub buffer_resv: Option<Rc<dyn BufferResv>>,
|
pub buffer_resv: Option<Rc<dyn BufferResv>>,
|
||||||
pub acquire_sync: AcquireSync,
|
pub acquire_sync: AcquireSync,
|
||||||
pub release_sync: ReleaseSync,
|
pub release_sync: ReleaseSync,
|
||||||
|
pub alpha: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|
@ -292,6 +293,7 @@ impl dyn GfxFramebuffer {
|
||||||
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
let mut renderer = self.renderer_base(&mut ops, scale, Transform::None);
|
||||||
renderer.render_texture(
|
renderer.render_texture(
|
||||||
texture,
|
texture,
|
||||||
|
None,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,11 @@ use {
|
||||||
},
|
},
|
||||||
gfx_apis::gl::{
|
gfx_apis::gl::{
|
||||||
gl::texture::image_target,
|
gl::texture::image_target,
|
||||||
renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture},
|
renderer::{
|
||||||
|
context::{GlRenderContext, TexCopyType, TexSourceType},
|
||||||
|
framebuffer::Framebuffer,
|
||||||
|
texture::Texture,
|
||||||
|
},
|
||||||
sys::{
|
sys::{
|
||||||
GL_BLEND, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER,
|
GL_BLEND, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER,
|
||||||
GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
||||||
|
|
@ -336,16 +340,20 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
||||||
},
|
},
|
||||||
false => &ctx.tex_internal,
|
false => &ctx.tex_internal,
|
||||||
};
|
};
|
||||||
let prog = match texture.gl.format.has_alpha {
|
let copy_type = match tex.alpha.is_some() {
|
||||||
true => {
|
true => TexCopyType::Multiply,
|
||||||
(gles.glEnable)(GL_BLEND);
|
false => TexCopyType::Identity,
|
||||||
&progs.alpha
|
|
||||||
}
|
|
||||||
false => {
|
|
||||||
(gles.glDisable)(GL_BLEND);
|
|
||||||
&progs.solid
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
let source_type = match texture.gl.format.has_alpha {
|
||||||
|
true => TexSourceType::HasAlpha,
|
||||||
|
false => TexSourceType::Opaque,
|
||||||
|
};
|
||||||
|
if (copy_type, source_type) == (TexCopyType::Identity, TexSourceType::Opaque) {
|
||||||
|
(gles.glDisable)(GL_BLEND);
|
||||||
|
} else {
|
||||||
|
(gles.glEnable)(GL_BLEND);
|
||||||
|
}
|
||||||
|
let prog = &progs[copy_type][source_type];
|
||||||
|
|
||||||
(gles.glUseProgram)(prog.prog.prog);
|
(gles.glUseProgram)(prog.prog.prog);
|
||||||
|
|
||||||
|
|
@ -354,6 +362,10 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
||||||
let texcoord = tex.source.to_points();
|
let texcoord = tex.source.to_points();
|
||||||
let pos = tex.target.to_points();
|
let pos = tex.target.to_points();
|
||||||
|
|
||||||
|
if let Some(alpha) = tex.alpha {
|
||||||
|
(gles.glUniform1f)(prog.alpha, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
(gles.glVertexAttribPointer)(
|
(gles.glVertexAttribPointer)(
|
||||||
prog.texcoord as _,
|
prog.texcoord as _,
|
||||||
2,
|
2,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ use {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ahash::AHashMap,
|
ahash::AHashMap,
|
||||||
|
enum_map::{enum_map, Enum, EnumMap},
|
||||||
jay_config::video::GfxApi,
|
jay_config::video::GfxApi,
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
|
|
@ -36,22 +37,35 @@ pub(crate) struct TexProg {
|
||||||
pub(crate) pos: GLint,
|
pub(crate) pos: GLint,
|
||||||
pub(crate) texcoord: GLint,
|
pub(crate) texcoord: GLint,
|
||||||
pub(crate) tex: GLint,
|
pub(crate) tex: GLint,
|
||||||
|
pub(crate) alpha: GLint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TexProg {
|
impl TexProg {
|
||||||
unsafe fn from(prog: GlProgram) -> Self {
|
unsafe fn from(prog: GlProgram, alpha_multiplier: bool) -> Self {
|
||||||
|
let alpha = match alpha_multiplier {
|
||||||
|
true => prog.get_uniform_location(ustr!("alpha")),
|
||||||
|
false => 0,
|
||||||
|
};
|
||||||
Self {
|
Self {
|
||||||
pos: prog.get_attrib_location(ustr!("pos")),
|
pos: prog.get_attrib_location(ustr!("pos")),
|
||||||
texcoord: prog.get_attrib_location(ustr!("texcoord")),
|
texcoord: prog.get_attrib_location(ustr!("texcoord")),
|
||||||
tex: prog.get_uniform_location(ustr!("tex")),
|
tex: prog.get_uniform_location(ustr!("tex")),
|
||||||
|
alpha,
|
||||||
prog,
|
prog,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct TexProgs {
|
#[derive(Copy, Clone, PartialEq, Enum)]
|
||||||
pub alpha: TexProg,
|
pub(in crate::gfx_apis::gl) enum TexCopyType {
|
||||||
pub solid: TexProg,
|
Identity,
|
||||||
|
Multiply,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Enum)]
|
||||||
|
pub(in crate::gfx_apis::gl) enum TexSourceType {
|
||||||
|
Opaque,
|
||||||
|
HasAlpha,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in crate::gfx_apis::gl) struct GlRenderContext {
|
pub(in crate::gfx_apis::gl) struct GlRenderContext {
|
||||||
|
|
@ -61,8 +75,8 @@ pub(in crate::gfx_apis::gl) struct GlRenderContext {
|
||||||
|
|
||||||
pub(crate) render_node: Rc<CString>,
|
pub(crate) render_node: Rc<CString>,
|
||||||
|
|
||||||
pub(crate) tex_internal: TexProgs,
|
pub(crate) tex_internal: EnumMap<TexCopyType, EnumMap<TexSourceType, TexProg>>,
|
||||||
pub(crate) tex_external: Option<TexProgs>,
|
pub(crate) tex_external: Option<EnumMap<TexCopyType, EnumMap<TexSourceType, TexProg>>>,
|
||||||
|
|
||||||
pub(crate) fill_prog: GlProgram,
|
pub(crate) fill_prog: GlProgram,
|
||||||
pub(crate) fill_prog_pos: GLint,
|
pub(crate) fill_prog_pos: GLint,
|
||||||
|
|
@ -100,28 +114,37 @@ impl GlRenderContext {
|
||||||
|
|
||||||
unsafe fn new(ctx: &Rc<EglContext>, node: &Rc<CString>) -> Result<Self, RenderError> {
|
unsafe fn new(ctx: &Rc<EglContext>, node: &Rc<CString>) -> Result<Self, RenderError> {
|
||||||
let tex_vert = include_str!("../shaders/tex.vert.glsl");
|
let tex_vert = include_str!("../shaders/tex.vert.glsl");
|
||||||
let tex_prog =
|
let tex_frag = include_str!("../shaders/tex.frag.glsl");
|
||||||
GlProgram::from_shaders(ctx, tex_vert, include_str!("../shaders/tex.frag.glsl"))?;
|
let create_programs = |external: bool| {
|
||||||
let tex_alpha_prog = GlProgram::from_shaders(
|
let create_program = |alpha_multiplier: bool, alpha: bool| {
|
||||||
ctx,
|
let mut tex_frac_src = String::new();
|
||||||
tex_vert,
|
if external {
|
||||||
include_str!("../shaders/tex-alpha.frag.glsl"),
|
tex_frac_src.push_str("#define EXTERNAL\n");
|
||||||
)?;
|
}
|
||||||
let tex_external = if ctx.ext.contains(GL_OES_EGL_IMAGE_EXTERNAL) {
|
if alpha_multiplier {
|
||||||
let solid = GlProgram::from_shaders(
|
tex_frac_src.push_str("#define ALPHA_MULTIPLIER\n");
|
||||||
ctx,
|
}
|
||||||
tex_vert,
|
if alpha {
|
||||||
include_str!("../shaders/tex-external.frag.glsl"),
|
tex_frac_src.push_str("#define ALPHA\n");
|
||||||
)?;
|
}
|
||||||
let alpha = GlProgram::from_shaders(
|
tex_frac_src.push_str(tex_frag);
|
||||||
ctx,
|
let prog = GlProgram::from_shaders(ctx, tex_vert, &tex_frac_src)?;
|
||||||
tex_vert,
|
Ok::<_, RenderError>(TexProg::from(prog, alpha_multiplier))
|
||||||
include_str!("../shaders/tex-external-alpha.frag.glsl"),
|
};
|
||||||
)?;
|
Ok::<_, RenderError>(enum_map! {
|
||||||
Some(TexProgs {
|
TexCopyType::Identity => enum_map! {
|
||||||
alpha: TexProg::from(alpha),
|
TexSourceType::Opaque => create_program(false, false)?,
|
||||||
solid: TexProg::from(solid),
|
TexSourceType::HasAlpha => create_program(false, true)?,
|
||||||
|
},
|
||||||
|
TexCopyType::Multiply => enum_map! {
|
||||||
|
TexSourceType::Opaque => create_program(true, false)?,
|
||||||
|
TexSourceType::HasAlpha => create_program(true, true)?,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
};
|
||||||
|
let tex_internal = create_programs(false)?;
|
||||||
|
let tex_external = if ctx.ext.contains(GL_OES_EGL_IMAGE_EXTERNAL) {
|
||||||
|
Some(create_programs(true)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
@ -137,10 +160,7 @@ impl GlRenderContext {
|
||||||
|
|
||||||
render_node: node.clone(),
|
render_node: node.clone(),
|
||||||
|
|
||||||
tex_internal: TexProgs {
|
tex_internal,
|
||||||
solid: TexProg::from(tex_prog),
|
|
||||||
alpha: TexProg::from(tex_alpha_prog),
|
|
||||||
},
|
|
||||||
tex_external,
|
tex_external,
|
||||||
|
|
||||||
fill_prog_pos: fill_prog.get_attrib_location(ustr!("pos")),
|
fill_prog_pos: fill_prog.get_attrib_location(ustr!("pos")),
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
precision mediump float;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
uniform sampler2D tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = texture2D(tex, v_texcoord);
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#extension GL_OES_EGL_image_external : require
|
|
||||||
|
|
||||||
precision mediump float;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
uniform samplerExternalOES tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = texture2D(tex, v_texcoord);
|
|
||||||
}
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
#extension GL_OES_EGL_image_external : require
|
|
||||||
|
|
||||||
precision mediump float;
|
|
||||||
varying vec2 v_texcoord;
|
|
||||||
uniform samplerExternalOES tex;
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,34 @@
|
||||||
|
#ifdef EXTERNAL
|
||||||
|
#extension GL_OES_EGL_image_external : require
|
||||||
|
#endif
|
||||||
|
|
||||||
precision mediump float;
|
precision mediump float;
|
||||||
varying vec2 v_texcoord;
|
varying vec2 v_texcoord;
|
||||||
|
#ifdef EXTERNAL
|
||||||
|
uniform samplerExternalOES tex;
|
||||||
|
#else
|
||||||
uniform sampler2D tex;
|
uniform sampler2D tex;
|
||||||
|
#endif
|
||||||
|
#ifdef ALPHA_MULTIPLIER
|
||||||
|
uniform float alpha;
|
||||||
|
#endif
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
#ifdef ALPHA
|
||||||
|
|
||||||
|
#ifdef ALPHA_MULTIPLIER
|
||||||
|
gl_FragColor = texture2D(tex, v_texcoord) * alpha;
|
||||||
|
#else // !ALPHA_MULTIPLIER
|
||||||
|
gl_FragColor = texture2D(tex, v_texcoord);
|
||||||
|
#endif // ALPHA_MULTIPLIER
|
||||||
|
|
||||||
|
#else // !ALPHA
|
||||||
|
|
||||||
|
#ifdef ALPHA_MULTIPLIER
|
||||||
|
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb * alpha, alpha);
|
||||||
|
#else // !ALPHA_MULTIPLIER
|
||||||
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
gl_FragColor = vec4(texture2D(tex, v_texcoord).rgb, 1.0);
|
||||||
|
#endif // ALPHA_MULTIPLIER
|
||||||
|
|
||||||
|
#endif // ALPHA
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,9 @@ use {
|
||||||
pipeline::{PipelineCreateInfo, VulkanPipeline},
|
pipeline::{PipelineCreateInfo, VulkanPipeline},
|
||||||
semaphore::VulkanSemaphore,
|
semaphore::VulkanSemaphore,
|
||||||
shaders::{
|
shaders::{
|
||||||
FillFragPushConstants, FillVertPushConstants, TexVertPushConstants, FILL_FRAG,
|
FillFragPushConstants, FillVertPushConstants, TexFragPushConstants,
|
||||||
FILL_VERT, TEX_FRAG, TEX_VERT,
|
TexVertPushConstants, VulkanShader, FILL_FRAG, FILL_VERT, TEX_FRAG,
|
||||||
|
TEX_FRAG_MULT_ALPHA, TEX_FRAG_MULT_OPAQUE, TEX_VERT,
|
||||||
},
|
},
|
||||||
staging::VulkanStagingBuffer,
|
staging::VulkanStagingBuffer,
|
||||||
VulkanError,
|
VulkanError,
|
||||||
|
|
@ -41,6 +42,7 @@ use {
|
||||||
},
|
},
|
||||||
Device,
|
Device,
|
||||||
},
|
},
|
||||||
|
enum_map::{enum_map, Enum, EnumMap},
|
||||||
isnt::std_1::collections::IsntHashMapExt,
|
isnt::std_1::collections::IsntHashMapExt,
|
||||||
std::{
|
std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
|
|
@ -56,8 +58,7 @@ pub struct VulkanRenderer {
|
||||||
pub(super) formats: Rc<AHashMap<u32, GfxFormat>>,
|
pub(super) formats: Rc<AHashMap<u32, GfxFormat>>,
|
||||||
pub(super) device: Rc<VulkanDevice>,
|
pub(super) device: Rc<VulkanDevice>,
|
||||||
pub(super) fill_pipeline: Rc<VulkanPipeline>,
|
pub(super) fill_pipeline: Rc<VulkanPipeline>,
|
||||||
pub(super) tex_opaque_pipeline: Rc<VulkanPipeline>,
|
pub(super) tex_pipelines: EnumMap<TexCopyType, EnumMap<TexSourceType, Rc<VulkanPipeline>>>,
|
||||||
pub(super) tex_alpha_pipeline: Rc<VulkanPipeline>,
|
|
||||||
pub(super) command_pool: Rc<VulkanCommandPool>,
|
pub(super) command_pool: Rc<VulkanCommandPool>,
|
||||||
pub(super) command_buffers: Stack<Rc<VulkanCommandBuffer>>,
|
pub(super) command_buffers: Stack<Rc<VulkanCommandBuffer>>,
|
||||||
pub(super) wait_semaphores: Stack<Rc<VulkanSemaphore>>,
|
pub(super) wait_semaphores: Stack<Rc<VulkanSemaphore>>,
|
||||||
|
|
@ -76,6 +77,18 @@ pub(super) struct UsedTexture {
|
||||||
release_sync: ReleaseSync,
|
release_sync: ReleaseSync,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Enum)]
|
||||||
|
pub(super) enum TexCopyType {
|
||||||
|
Identity,
|
||||||
|
Multiply,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Enum)]
|
||||||
|
pub(super) enum TexSourceType {
|
||||||
|
Opaque,
|
||||||
|
HasAlpha,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub(super) struct Memory {
|
pub(super) struct Memory {
|
||||||
sample: Vec<Rc<VulkanImage>>,
|
sample: Vec<Rc<VulkanImage>>,
|
||||||
|
|
@ -115,6 +128,8 @@ impl VulkanDevice {
|
||||||
let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?;
|
let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?;
|
||||||
let tex_vert_shader = self.create_shader(TEX_VERT)?;
|
let tex_vert_shader = self.create_shader(TEX_VERT)?;
|
||||||
let tex_frag_shader = self.create_shader(TEX_FRAG)?;
|
let tex_frag_shader = self.create_shader(TEX_FRAG)?;
|
||||||
|
let tex_frag_mult_opaque_shader = self.create_shader(TEX_FRAG_MULT_OPAQUE)?;
|
||||||
|
let tex_frag_mult_alpha_shader = self.create_shader(TEX_FRAG_MULT_ALPHA)?;
|
||||||
let create_tex_pipeline = |alpha| {
|
let create_tex_pipeline = |alpha| {
|
||||||
self.create_pipeline::<TexVertPushConstants, ()>(PipelineCreateInfo {
|
self.create_pipeline::<TexVertPushConstants, ()>(PipelineCreateInfo {
|
||||||
vert: tex_vert_shader.clone(),
|
vert: tex_vert_shader.clone(),
|
||||||
|
|
@ -123,8 +138,18 @@ impl VulkanDevice {
|
||||||
frag_descriptor_set_layout: Some(tex_descriptor_set_layout.clone()),
|
frag_descriptor_set_layout: Some(tex_descriptor_set_layout.clone()),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
let create_tex_mult_pipeline = |frag: &Rc<VulkanShader>| {
|
||||||
|
self.create_pipeline::<TexVertPushConstants, TexFragPushConstants>(PipelineCreateInfo {
|
||||||
|
vert: tex_vert_shader.clone(),
|
||||||
|
frag: frag.clone(),
|
||||||
|
alpha: true,
|
||||||
|
frag_descriptor_set_layout: Some(tex_descriptor_set_layout.clone()),
|
||||||
|
})
|
||||||
|
};
|
||||||
let tex_opaque_pipeline = create_tex_pipeline(false)?;
|
let tex_opaque_pipeline = create_tex_pipeline(false)?;
|
||||||
let tex_alpha_pipeline = create_tex_pipeline(true)?;
|
let tex_alpha_pipeline = create_tex_pipeline(true)?;
|
||||||
|
let tex_mult_opaque_pipeline = create_tex_mult_pipeline(&tex_frag_mult_opaque_shader)?;
|
||||||
|
let tex_mult_alpha_pipeline = create_tex_mult_pipeline(&tex_frag_mult_alpha_shader)?;
|
||||||
let command_pool = self.create_command_pool()?;
|
let command_pool = self.create_command_pool()?;
|
||||||
let formats: AHashMap<u32, _> = self
|
let formats: AHashMap<u32, _> = self
|
||||||
.formats
|
.formats
|
||||||
|
|
@ -155,8 +180,16 @@ impl VulkanDevice {
|
||||||
formats: Rc::new(formats),
|
formats: Rc::new(formats),
|
||||||
device: self.clone(),
|
device: self.clone(),
|
||||||
fill_pipeline,
|
fill_pipeline,
|
||||||
tex_opaque_pipeline,
|
tex_pipelines: enum_map! {
|
||||||
tex_alpha_pipeline,
|
TexCopyType::Identity => enum_map! {
|
||||||
|
TexSourceType::HasAlpha => tex_alpha_pipeline.clone(),
|
||||||
|
TexSourceType::Opaque => tex_opaque_pipeline.clone(),
|
||||||
|
},
|
||||||
|
TexCopyType::Multiply => enum_map! {
|
||||||
|
TexSourceType::HasAlpha => tex_mult_alpha_pipeline.clone(),
|
||||||
|
TexSourceType::Opaque => tex_mult_opaque_pipeline.clone(),
|
||||||
|
},
|
||||||
|
},
|
||||||
command_pool,
|
command_pool,
|
||||||
command_buffers: Default::default(),
|
command_buffers: Default::default(),
|
||||||
wait_semaphores: Default::default(),
|
wait_semaphores: Default::default(),
|
||||||
|
|
@ -449,10 +482,15 @@ impl VulkanRenderer {
|
||||||
}
|
}
|
||||||
GfxApiOpt::CopyTexture(c) => {
|
GfxApiOpt::CopyTexture(c) => {
|
||||||
let tex = c.tex.as_vk(&self.device.device);
|
let tex = c.tex.as_vk(&self.device.device);
|
||||||
let pipeline = match tex.format.has_alpha {
|
let copy_type = match c.alpha.is_some() {
|
||||||
true => &self.tex_alpha_pipeline,
|
true => TexCopyType::Multiply,
|
||||||
false => &self.tex_opaque_pipeline,
|
false => TexCopyType::Identity,
|
||||||
};
|
};
|
||||||
|
let source_type = match tex.format.has_alpha {
|
||||||
|
true => TexSourceType::HasAlpha,
|
||||||
|
false => TexSourceType::Opaque,
|
||||||
|
};
|
||||||
|
let pipeline = &self.tex_pipelines[copy_type][source_type];
|
||||||
bind(pipeline);
|
bind(pipeline);
|
||||||
let vert = TexVertPushConstants {
|
let vert = TexVertPushConstants {
|
||||||
pos: c.target.to_points(),
|
pos: c.target.to_points(),
|
||||||
|
|
@ -480,6 +518,16 @@ impl VulkanRenderer {
|
||||||
0,
|
0,
|
||||||
uapi::as_bytes(&vert),
|
uapi::as_bytes(&vert),
|
||||||
);
|
);
|
||||||
|
if let Some(alpha) = c.alpha {
|
||||||
|
let frag = TexFragPushConstants { alpha };
|
||||||
|
dev.cmd_push_constants(
|
||||||
|
buf,
|
||||||
|
pipeline.pipeline_layout,
|
||||||
|
ShaderStageFlags::FRAGMENT,
|
||||||
|
mem::size_of_val(&vert) as _,
|
||||||
|
uapi::as_bytes(&frag),
|
||||||
|
);
|
||||||
|
}
|
||||||
dev.cmd_draw(buf, 4, 1, 0, 0);
|
dev.cmd_draw(buf, 4, 1, 0, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,10 @@ pub const FILL_VERT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/fill.vert
|
||||||
pub const FILL_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/fill.frag.spv"));
|
pub const FILL_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/fill.frag.spv"));
|
||||||
pub const TEX_VERT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.vert.spv"));
|
pub const TEX_VERT: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.vert.spv"));
|
||||||
pub const TEX_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.frag.spv"));
|
pub const TEX_FRAG: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/tex.frag.spv"));
|
||||||
|
pub const TEX_FRAG_MULT_OPAQUE: &[u8] =
|
||||||
|
include_bytes!(concat!(env!("OUT_DIR"), "/tex.frag.mult+opaque.spv"));
|
||||||
|
pub const TEX_FRAG_MULT_ALPHA: &[u8] =
|
||||||
|
include_bytes!(concat!(env!("OUT_DIR"), "/tex.frag.mult+alpha.spv"));
|
||||||
|
|
||||||
pub struct VulkanShader {
|
pub struct VulkanShader {
|
||||||
pub(super) device: Rc<VulkanDevice>,
|
pub(super) device: Rc<VulkanDevice>,
|
||||||
|
|
@ -38,7 +42,14 @@ pub struct TexVertPushConstants {
|
||||||
pub tex_pos: [[f32; 2]; 4],
|
pub tex_pos: [[f32; 2]; 4],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct TexFragPushConstants {
|
||||||
|
pub alpha: f32,
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl Packed for TexVertPushConstants {}
|
unsafe impl Packed for TexVertPushConstants {}
|
||||||
|
unsafe impl Packed for TexFragPushConstants {}
|
||||||
|
|
||||||
impl VulkanDevice {
|
impl VulkanDevice {
|
||||||
pub(super) fn create_shader(
|
pub(super) fn create_shader(
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,21 @@
|
||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
|
#ifdef ALPHA_MULTIPLIER
|
||||||
|
layout(push_constant, std430) uniform Data {
|
||||||
|
layout(offset = 64) float mul;
|
||||||
|
} data;
|
||||||
|
#endif
|
||||||
layout(set = 0, binding = 0) uniform sampler2D tex;
|
layout(set = 0, binding = 0) uniform sampler2D tex;
|
||||||
layout(location = 0) in vec2 tex_pos;
|
layout(location = 0) in vec2 tex_pos;
|
||||||
layout(location = 0) out vec4 out_color;
|
layout(location = 0) out vec4 out_color;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
#ifdef ALPHA_MULTIPLIER
|
||||||
|
#ifdef ALPHA
|
||||||
|
out_color = textureLod(tex, tex_pos, 0) * data.mul;
|
||||||
|
#endif // !ALPHA
|
||||||
|
out_color = vec4(textureLod(tex, tex_pos, 0).rgb * data.mul, data.mul);
|
||||||
|
#else // !ALPHA_MULTIPLIER
|
||||||
out_color = textureLod(tex, tex_pos, 0);
|
out_color = textureLod(tex, tex_pos, 0);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ use {
|
||||||
wl_shm::WlShmGlobal,
|
wl_shm::WlShmGlobal,
|
||||||
wl_subcompositor::WlSubcompositorGlobal,
|
wl_subcompositor::WlSubcompositorGlobal,
|
||||||
wl_surface::xwayland_shell_v1::XwaylandShellV1Global,
|
wl_surface::xwayland_shell_v1::XwaylandShellV1Global,
|
||||||
|
wp_alpha_modifier_v1::WpAlphaModifierV1Global,
|
||||||
wp_content_type_manager_v1::WpContentTypeManagerV1Global,
|
wp_content_type_manager_v1::WpContentTypeManagerV1Global,
|
||||||
wp_cursor_shape_manager_v1::WpCursorShapeManagerV1Global,
|
wp_cursor_shape_manager_v1::WpCursorShapeManagerV1Global,
|
||||||
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1Global,
|
wp_fractional_scale_manager_v1::WpFractionalScaleManagerV1Global,
|
||||||
|
|
@ -173,6 +174,7 @@ impl Globals {
|
||||||
add_singleton!(ExtIdleNotifierV1Global);
|
add_singleton!(ExtIdleNotifierV1Global);
|
||||||
add_singleton!(XdgToplevelDragManagerV1Global);
|
add_singleton!(XdgToplevelDragManagerV1Global);
|
||||||
add_singleton!(ZwlrDataControlManagerV1Global);
|
add_singleton!(ZwlrDataControlManagerV1Global);
|
||||||
|
add_singleton!(WpAlphaModifierV1Global);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_backend_singletons(&self, backend: &Rc<dyn Backend>) {
|
pub fn add_backend_singletons(&self, backend: &Rc<dyn Backend>) {
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ pub mod wl_shm;
|
||||||
pub mod wl_shm_pool;
|
pub mod wl_shm_pool;
|
||||||
pub mod wl_subcompositor;
|
pub mod wl_subcompositor;
|
||||||
pub mod wl_surface;
|
pub mod wl_surface;
|
||||||
|
pub mod wp_alpha_modifier_v1;
|
||||||
pub mod wp_content_type_manager_v1;
|
pub mod wp_content_type_manager_v1;
|
||||||
pub mod wp_content_type_v1;
|
pub mod wp_content_type_v1;
|
||||||
pub mod wp_cursor_shape_device_v1;
|
pub mod wp_cursor_shape_device_v1;
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ pub mod commit_timeline;
|
||||||
pub mod cursor;
|
pub mod cursor;
|
||||||
pub mod ext_session_lock_surface_v1;
|
pub mod ext_session_lock_surface_v1;
|
||||||
pub mod wl_subsurface;
|
pub mod wl_subsurface;
|
||||||
|
pub mod wp_alpha_modifier_surface_v1;
|
||||||
pub mod wp_fractional_scale_v1;
|
pub mod wp_fractional_scale_v1;
|
||||||
pub mod wp_linux_drm_syncobj_surface_v1;
|
pub mod wp_linux_drm_syncobj_surface_v1;
|
||||||
pub mod wp_tearing_control_v1;
|
pub mod wp_tearing_control_v1;
|
||||||
|
|
@ -30,6 +31,7 @@ use {
|
||||||
commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError},
|
commit_timeline::{ClearReason, CommitTimeline, CommitTimelineError},
|
||||||
cursor::CursorSurface,
|
cursor::CursorSurface,
|
||||||
wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface},
|
wl_subsurface::{PendingSubsurfaceData, SubsurfaceId, WlSubsurface},
|
||||||
|
wp_alpha_modifier_surface_v1::WpAlphaModifierSurfaceV1,
|
||||||
wp_fractional_scale_v1::WpFractionalScaleV1,
|
wp_fractional_scale_v1::WpFractionalScaleV1,
|
||||||
wp_linux_drm_syncobj_surface_v1::WpLinuxDrmSyncobjSurfaceV1,
|
wp_linux_drm_syncobj_surface_v1::WpLinuxDrmSyncobjSurfaceV1,
|
||||||
wp_tearing_control_v1::WpTearingControlV1,
|
wp_tearing_control_v1::WpTearingControlV1,
|
||||||
|
|
@ -245,6 +247,8 @@ pub struct WlSurface {
|
||||||
sync_obj_surface: CloneCell<Option<Rc<WpLinuxDrmSyncobjSurfaceV1>>>,
|
sync_obj_surface: CloneCell<Option<Rc<WpLinuxDrmSyncobjSurfaceV1>>>,
|
||||||
destroyed: Cell<bool>,
|
destroyed: Cell<bool>,
|
||||||
commit_timeline: CommitTimeline,
|
commit_timeline: CommitTimeline,
|
||||||
|
alpha_modifier: CloneCell<Option<Rc<WpAlphaModifierSurfaceV1>>>,
|
||||||
|
alpha: Cell<Option<f32>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for WlSurface {
|
impl Debug for WlSurface {
|
||||||
|
|
@ -366,6 +370,7 @@ struct PendingState {
|
||||||
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
|
subsurfaces: AHashMap<SubsurfaceId, AttachedSubsurfaceState>,
|
||||||
acquire_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
acquire_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
||||||
release_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
release_point: Option<(Rc<SyncObj>, SyncObjPoint)>,
|
||||||
|
alpha_multiplier: Option<Option<f32>>,
|
||||||
explicit_sync: bool,
|
explicit_sync: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -416,6 +421,7 @@ impl PendingState {
|
||||||
opt!(xwayland_serial);
|
opt!(xwayland_serial);
|
||||||
opt!(tearing);
|
opt!(tearing);
|
||||||
opt!(content_type);
|
opt!(content_type);
|
||||||
|
opt!(alpha_multiplier);
|
||||||
{
|
{
|
||||||
let (dx1, dy1) = self.offset;
|
let (dx1, dy1) = self.offset;
|
||||||
let (dx2, dy2) = mem::take(&mut next.offset);
|
let (dx2, dy2) = mem::take(&mut next.offset);
|
||||||
|
|
@ -525,6 +531,8 @@ impl WlSurface {
|
||||||
sync_obj_surface: Default::default(),
|
sync_obj_surface: Default::default(),
|
||||||
destroyed: Cell::new(false),
|
destroyed: Cell::new(false),
|
||||||
commit_timeline: client.commit_timelines.create_timeline(),
|
commit_timeline: client.commit_timelines.create_timeline(),
|
||||||
|
alpha_modifier: Default::default(),
|
||||||
|
alpha: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -915,6 +923,11 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let mut alpha_changed = false;
|
||||||
|
if let Some(alpha) = pending.alpha_multiplier.take() {
|
||||||
|
alpha_changed = true;
|
||||||
|
self.alpha.set(alpha);
|
||||||
|
}
|
||||||
let mut buffer_changed = false;
|
let mut buffer_changed = false;
|
||||||
let mut old_raw_size = None;
|
let mut old_raw_size = None;
|
||||||
let (dx, dy) = mem::take(&mut pending.offset);
|
let (dx, dy) = mem::take(&mut pending.offset);
|
||||||
|
|
@ -1076,7 +1089,7 @@ impl WlSurface {
|
||||||
if self.need_extents_update.get() {
|
if self.need_extents_update.get() {
|
||||||
self.calculate_extents();
|
self.calculate_extents();
|
||||||
}
|
}
|
||||||
if buffer_changed || transform_changed {
|
if buffer_changed || transform_changed || alpha_changed {
|
||||||
for (_, cursor) in &self.cursors {
|
for (_, cursor) in &self.cursors {
|
||||||
cursor.handle_buffer_change();
|
cursor.handle_buffer_change();
|
||||||
cursor.update_hardware_cursor();
|
cursor.update_hardware_cursor();
|
||||||
|
|
@ -1278,6 +1291,10 @@ impl WlSurface {
|
||||||
}
|
}
|
||||||
self.set_visible(self.dnd_icons.is_not_empty() && self.client.state.root_visible());
|
self.set_visible(self.dnd_icons.is_not_empty() && self.client.state.root_visible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn alpha(&self) -> Option<f32> {
|
||||||
|
self.alpha.get()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object_base! {
|
object_base! {
|
||||||
|
|
@ -1304,6 +1321,7 @@ impl Object for WlSurface {
|
||||||
self.constraints.clear();
|
self.constraints.clear();
|
||||||
self.drm_feedback.clear();
|
self.drm_feedback.clear();
|
||||||
self.commit_timeline.clear(ClearReason::BreakLoops);
|
self.commit_timeline.clear(ClearReason::BreakLoops);
|
||||||
|
self.alpha_modifier.take();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
78
src/ifs/wl_surface/wp_alpha_modifier_surface_v1.rs
Normal file
78
src/ifs/wl_surface/wp_alpha_modifier_surface_v1.rs
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
client::{Client, ClientError},
|
||||||
|
ifs::wl_surface::WlSurface,
|
||||||
|
leaks::Tracker,
|
||||||
|
object::{Object, Version},
|
||||||
|
wire::{wp_alpha_modifier_surface_v1::*, WpAlphaModifierSurfaceV1Id},
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct WpAlphaModifierSurfaceV1 {
|
||||||
|
pub id: WpAlphaModifierSurfaceV1Id,
|
||||||
|
pub version: Version,
|
||||||
|
pub client: Rc<Client>,
|
||||||
|
pub surface: Rc<WlSurface>,
|
||||||
|
pub tracker: Tracker<Self>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WpAlphaModifierSurfaceV1 {
|
||||||
|
pub fn new(id: WpAlphaModifierSurfaceV1Id, surface: &Rc<WlSurface>, version: Version) -> Self {
|
||||||
|
Self {
|
||||||
|
id,
|
||||||
|
version,
|
||||||
|
client: surface.client.clone(),
|
||||||
|
surface: surface.clone(),
|
||||||
|
tracker: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn install(self: &Rc<Self>) -> Result<(), WpAlphaModifierSurfaceV1Error> {
|
||||||
|
if self.surface.alpha_modifier.is_some() {
|
||||||
|
return Err(WpAlphaModifierSurfaceV1Error::Exists);
|
||||||
|
}
|
||||||
|
self.surface.alpha_modifier.set(Some(self.clone()));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WpAlphaModifierSurfaceV1RequestHandler for WpAlphaModifierSurfaceV1 {
|
||||||
|
type Error = WpAlphaModifierSurfaceV1Error;
|
||||||
|
|
||||||
|
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.surface.alpha_modifier.take();
|
||||||
|
self.surface.pending.borrow_mut().alpha_multiplier = Some(None);
|
||||||
|
self.client.remove_obj(self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_multiplier(&self, req: SetMultiplier, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
let multiplier = if req.factor == u32::MAX {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(((req.factor as f64) / (u32::MAX as f64)) as f32)
|
||||||
|
};
|
||||||
|
self.surface.pending.borrow_mut().alpha_multiplier = Some(multiplier);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object_base! {
|
||||||
|
self = WpAlphaModifierSurfaceV1;
|
||||||
|
version = self.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for WpAlphaModifierSurfaceV1 {}
|
||||||
|
|
||||||
|
simple_add_obj!(WpAlphaModifierSurfaceV1);
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum WpAlphaModifierSurfaceV1Error {
|
||||||
|
#[error(transparent)]
|
||||||
|
ClientError(Box<ClientError>),
|
||||||
|
#[error("The surface already has an alpha modifier extension attached")]
|
||||||
|
Exists,
|
||||||
|
}
|
||||||
|
efrom!(WpAlphaModifierSurfaceV1Error, ClientError);
|
||||||
106
src/ifs/wp_alpha_modifier_v1.rs
Normal file
106
src/ifs/wp_alpha_modifier_v1.rs
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
client::{Client, ClientError},
|
||||||
|
globals::{Global, GlobalName},
|
||||||
|
ifs::wl_surface::wp_alpha_modifier_surface_v1::{
|
||||||
|
WpAlphaModifierSurfaceV1, WpAlphaModifierSurfaceV1Error,
|
||||||
|
},
|
||||||
|
leaks::Tracker,
|
||||||
|
object::{Object, Version},
|
||||||
|
wire::{wp_alpha_modifier_v1::*, WpAlphaModifierV1Id},
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
thiserror::Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct WpAlphaModifierV1Global {
|
||||||
|
name: GlobalName,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WpAlphaModifierV1 {
|
||||||
|
id: WpAlphaModifierV1Id,
|
||||||
|
client: Rc<Client>,
|
||||||
|
version: Version,
|
||||||
|
pub tracker: Tracker<Self>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WpAlphaModifierV1Global {
|
||||||
|
pub fn new(name: GlobalName) -> Self {
|
||||||
|
Self { name }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bind_(
|
||||||
|
self: Rc<Self>,
|
||||||
|
id: WpAlphaModifierV1Id,
|
||||||
|
client: &Rc<Client>,
|
||||||
|
version: Version,
|
||||||
|
) -> Result<(), WpAlphaModifierV1Error> {
|
||||||
|
let obj = Rc::new(WpAlphaModifierV1 {
|
||||||
|
id,
|
||||||
|
client: client.clone(),
|
||||||
|
version,
|
||||||
|
tracker: Default::default(),
|
||||||
|
});
|
||||||
|
track!(client, obj);
|
||||||
|
client.add_client_obj(&obj)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl WpAlphaModifierV1RequestHandler for WpAlphaModifierV1 {
|
||||||
|
type Error = WpAlphaModifierV1Error;
|
||||||
|
|
||||||
|
fn destroy(&self, _req: Destroy, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
self.client.remove_obj(self)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_surface(&self, req: GetSurface, _slf: &Rc<Self>) -> Result<(), Self::Error> {
|
||||||
|
let surface = self.client.lookup(req.surface)?;
|
||||||
|
let modifier = Rc::new(WpAlphaModifierSurfaceV1::new(
|
||||||
|
req.id,
|
||||||
|
&surface,
|
||||||
|
self.version,
|
||||||
|
));
|
||||||
|
track!(self.client, surface);
|
||||||
|
self.client.add_client_obj(&modifier)?;
|
||||||
|
modifier.install()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
global_base!(
|
||||||
|
WpAlphaModifierV1Global,
|
||||||
|
WpAlphaModifierV1,
|
||||||
|
WpAlphaModifierV1Error
|
||||||
|
);
|
||||||
|
|
||||||
|
impl Global for WpAlphaModifierV1Global {
|
||||||
|
fn singleton(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn version(&self) -> u32 {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
simple_add_global!(WpAlphaModifierV1Global);
|
||||||
|
|
||||||
|
object_base! {
|
||||||
|
self = WpAlphaModifierV1;
|
||||||
|
version = self.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Object for WpAlphaModifierV1 {}
|
||||||
|
|
||||||
|
simple_add_obj!(WpAlphaModifierV1);
|
||||||
|
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum WpAlphaModifierV1Error {
|
||||||
|
#[error(transparent)]
|
||||||
|
ClientError(Box<ClientError>),
|
||||||
|
#[error(transparent)]
|
||||||
|
WpAlphaModifierSurfaceV1Error(#[from] WpAlphaModifierSurfaceV1Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
efrom!(WpAlphaModifierV1Error, ClientError);
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
mod test_buffer;
|
pub mod test_alpha_modifier;
|
||||||
|
pub mod test_alpha_modifier_surface;
|
||||||
|
pub mod test_buffer;
|
||||||
pub mod test_callback;
|
pub mod test_callback;
|
||||||
pub mod test_compositor;
|
pub mod test_compositor;
|
||||||
pub mod test_content_type;
|
pub mod test_content_type;
|
||||||
|
|
|
||||||
49
src/it/test_ifs/test_alpha_modifier.rs
Normal file
49
src/it/test_ifs/test_alpha_modifier.rs
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{
|
||||||
|
test_error::TestResult,
|
||||||
|
test_ifs::{
|
||||||
|
test_alpha_modifier_surface::TestAlphaModifierSurface, test_surface::TestSurface,
|
||||||
|
},
|
||||||
|
test_object::TestObject,
|
||||||
|
test_transport::TestTransport,
|
||||||
|
},
|
||||||
|
wire::{wp_alpha_modifier_v1::*, WpAlphaModifierV1Id},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestAlphaModifier {
|
||||||
|
pub id: WpAlphaModifierV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestAlphaModifier {
|
||||||
|
pub fn new(tran: &Rc<TestTransport>) -> Self {
|
||||||
|
Self {
|
||||||
|
id: tran.id(),
|
||||||
|
tran: tran.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_surface(&self, surface: &TestSurface) -> TestResult<Rc<TestAlphaModifierSurface>> {
|
||||||
|
let obj = Rc::new(TestAlphaModifierSurface {
|
||||||
|
id: self.tran.id(),
|
||||||
|
tran: self.tran.clone(),
|
||||||
|
destroyed: Cell::new(false),
|
||||||
|
});
|
||||||
|
self.tran.add_obj(obj.clone())?;
|
||||||
|
self.tran.send(GetSurface {
|
||||||
|
self_id: self.id,
|
||||||
|
id: obj.id,
|
||||||
|
surface: surface.id,
|
||||||
|
})?;
|
||||||
|
Ok(obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestAlphaModifier, WpAlphaModifierV1;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestAlphaModifier {}
|
||||||
41
src/it/test_ifs/test_alpha_modifier_surface.rs
Normal file
41
src/it/test_ifs/test_alpha_modifier_surface.rs
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{test_error::TestError, test_object::TestObject, test_transport::TestTransport},
|
||||||
|
wire::{wp_alpha_modifier_surface_v1::*, WpAlphaModifierSurfaceV1Id},
|
||||||
|
},
|
||||||
|
std::{cell::Cell, rc::Rc},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct TestAlphaModifierSurface {
|
||||||
|
pub id: WpAlphaModifierSurfaceV1Id,
|
||||||
|
pub tran: Rc<TestTransport>,
|
||||||
|
pub destroyed: Cell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestAlphaModifierSurface {
|
||||||
|
pub fn destroy(&self) -> Result<(), TestError> {
|
||||||
|
if !self.destroyed.replace(true) {
|
||||||
|
self.tran.send(Destroy { self_id: self.id })?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_multiplier(&self, factor: f64) -> Result<(), TestError> {
|
||||||
|
self.tran.send(SetMultiplier {
|
||||||
|
self_id: self.id,
|
||||||
|
factor: (factor * u32::MAX as f64) as u32,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for TestAlphaModifierSurface {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let _ = self.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test_object! {
|
||||||
|
TestAlphaModifierSurface, WpAlphaModifierSurfaceV1;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TestObject for TestAlphaModifierSurface {}
|
||||||
|
|
@ -5,7 +5,8 @@ use {
|
||||||
it::{
|
it::{
|
||||||
test_error::TestError,
|
test_error::TestError,
|
||||||
test_ifs::{
|
test_ifs::{
|
||||||
test_compositor::TestCompositor, test_content_type_manager::TestContentTypeManager,
|
test_alpha_modifier::TestAlphaModifier, test_compositor::TestCompositor,
|
||||||
|
test_content_type_manager::TestContentTypeManager,
|
||||||
test_cursor_shape_manager::TestCursorShapeManager,
|
test_cursor_shape_manager::TestCursorShapeManager,
|
||||||
test_data_control_manager::TestDataControlManager,
|
test_data_control_manager::TestDataControlManager,
|
||||||
test_data_device_manager::TestDataDeviceManager, test_dmabuf::TestDmabuf,
|
test_data_device_manager::TestDataDeviceManager, test_dmabuf::TestDmabuf,
|
||||||
|
|
@ -50,6 +51,7 @@ pub struct TestRegistrySingletons {
|
||||||
pub zwlr_data_control_manager_v1: u32,
|
pub zwlr_data_control_manager_v1: u32,
|
||||||
pub zwp_linux_dmabuf_v1: u32,
|
pub zwp_linux_dmabuf_v1: u32,
|
||||||
pub xdg_toplevel_drag_manager_v1: u32,
|
pub xdg_toplevel_drag_manager_v1: u32,
|
||||||
|
pub wp_alpha_modifier_v1: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestRegistry {
|
pub struct TestRegistry {
|
||||||
|
|
@ -73,6 +75,7 @@ pub struct TestRegistry {
|
||||||
pub data_control_manager: CloneCell<Option<Rc<TestDataControlManager>>>,
|
pub data_control_manager: CloneCell<Option<Rc<TestDataControlManager>>>,
|
||||||
pub dmabuf: CloneCell<Option<Rc<TestDmabuf>>>,
|
pub dmabuf: CloneCell<Option<Rc<TestDmabuf>>>,
|
||||||
pub drag_manager: CloneCell<Option<Rc<TestToplevelDragManager>>>,
|
pub drag_manager: CloneCell<Option<Rc<TestToplevelDragManager>>>,
|
||||||
|
pub alpha_modifier: CloneCell<Option<Rc<TestAlphaModifier>>>,
|
||||||
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
pub seats: CopyHashMap<GlobalName, Rc<WlSeatGlobal>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -140,6 +143,7 @@ impl TestRegistry {
|
||||||
zwlr_data_control_manager_v1,
|
zwlr_data_control_manager_v1,
|
||||||
zwp_linux_dmabuf_v1,
|
zwp_linux_dmabuf_v1,
|
||||||
xdg_toplevel_drag_manager_v1,
|
xdg_toplevel_drag_manager_v1,
|
||||||
|
wp_alpha_modifier_v1,
|
||||||
};
|
};
|
||||||
self.singletons.set(Some(singletons.clone()));
|
self.singletons.set(Some(singletons.clone()));
|
||||||
Ok(singletons)
|
Ok(singletons)
|
||||||
|
|
@ -227,6 +231,13 @@ impl TestRegistry {
|
||||||
1,
|
1,
|
||||||
TestToplevelDragManager
|
TestToplevelDragManager
|
||||||
);
|
);
|
||||||
|
create_singleton!(
|
||||||
|
get_alpha_modifier,
|
||||||
|
alpha_modifier,
|
||||||
|
wp_alpha_modifier_v1,
|
||||||
|
1,
|
||||||
|
TestAlphaModifier
|
||||||
|
);
|
||||||
|
|
||||||
pub fn bind<O: TestObject>(
|
pub fn bind<O: TestObject>(
|
||||||
&self,
|
&self,
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,7 @@ impl TestTransport {
|
||||||
data_control_manager: Default::default(),
|
data_control_manager: Default::default(),
|
||||||
dmabuf: Default::default(),
|
dmabuf: Default::default(),
|
||||||
drag_manager: Default::default(),
|
drag_manager: Default::default(),
|
||||||
|
alpha_modifier: Default::default(),
|
||||||
seats: Default::default(),
|
seats: Default::default(),
|
||||||
});
|
});
|
||||||
self.send(wl_display::GetRegistry {
|
self.send(wl_display::GetRegistry {
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ mod t0035_scanout_feedback;
|
||||||
mod t0036_idle;
|
mod t0036_idle;
|
||||||
mod t0037_toplevel_drag;
|
mod t0037_toplevel_drag;
|
||||||
mod t0038_subsurface_parent_state;
|
mod t0038_subsurface_parent_state;
|
||||||
|
mod t0039_alpha_modifier;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -127,5 +128,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0036_idle,
|
t0036_idle,
|
||||||
t0037_toplevel_drag,
|
t0037_toplevel_drag,
|
||||||
t0038_subsurface_parent_state,
|
t0038_subsurface_parent_state,
|
||||||
|
t0039_alpha_modifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
56
src/it/tests/t0039_alpha_modifier.rs
Normal file
56
src/it/tests/t0039_alpha_modifier.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
it::{test_error::TestResult, testrun::TestRun},
|
||||||
|
theme::Color,
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
testcase!();
|
||||||
|
|
||||||
|
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
|
let _ds = run.create_default_setup().await?;
|
||||||
|
|
||||||
|
let client = run.create_client().await?;
|
||||||
|
let win = client.create_window().await?;
|
||||||
|
win.set_color(255, 0, 0, 255);
|
||||||
|
win.map2().await?;
|
||||||
|
|
||||||
|
macro_rules! create_surface {
|
||||||
|
($buf:expr, $x:expr, $y:expr) => {{
|
||||||
|
let ss = client.comp.create_surface().await?;
|
||||||
|
let vp = client.viewporter.get_viewport(&ss)?;
|
||||||
|
vp.set_destination(100, 100)?;
|
||||||
|
ss.attach($buf.id)?;
|
||||||
|
ss.commit()?;
|
||||||
|
let alpha = client
|
||||||
|
.registry
|
||||||
|
.get_alpha_modifier()
|
||||||
|
.await?
|
||||||
|
.get_surface(&ss)?;
|
||||||
|
let sub = client.sub.get_subsurface(ss.id, win.surface.id).await?;
|
||||||
|
sub.set_desync()?;
|
||||||
|
sub.set_position($x, $y)?;
|
||||||
|
win.surface.commit()?;
|
||||||
|
(ss, alpha)
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
let buf1 = client.spbm.create_buffer(Color::from_rgb(0, 255, 0))?;
|
||||||
|
let (ss1, alpha1) = create_surface!(&buf1, 0, 0);
|
||||||
|
|
||||||
|
let buf2 = client.shm.create_buffer(1, 1)?;
|
||||||
|
buf2.fill(Color::from_rgb(0, 255, 0));
|
||||||
|
let (ss2, alpha2) = create_surface!(&buf2.buffer, 100, 0);
|
||||||
|
|
||||||
|
client.compare_screenshot("1", false).await?;
|
||||||
|
|
||||||
|
alpha1.set_multiplier(0.5)?;
|
||||||
|
ss1.commit()?;
|
||||||
|
alpha2.set_multiplier(0.5)?;
|
||||||
|
ss2.commit()?;
|
||||||
|
|
||||||
|
client.compare_screenshot("2", false).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
BIN
src/it/tests/t0039_alpha_modifier/screenshot_1.qoi
Normal file
BIN
src/it/tests/t0039_alpha_modifier/screenshot_1.qoi
Normal file
Binary file not shown.
BIN
src/it/tests/t0039_alpha_modifier/screenshot_2.qoi
Normal file
BIN
src/it/tests/t0039_alpha_modifier/screenshot_2.qoi
Normal file
Binary file not shown.
|
|
@ -216,6 +216,7 @@ impl GuiElement for Button {
|
||||||
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
|
let (tx, ty) = r.scale_point_f(x1 + self.tex_off_x.get(), y1 + self.tex_off_y.get());
|
||||||
r.render_texture(
|
r.render_texture(
|
||||||
&tex.texture,
|
&tex.texture,
|
||||||
|
None,
|
||||||
tx.round() as _,
|
tx.round() as _,
|
||||||
ty.round() as _,
|
ty.round() as _,
|
||||||
None,
|
None,
|
||||||
|
|
@ -320,6 +321,7 @@ impl GuiElement for Label {
|
||||||
let (tx, ty) = r.scale_point_f(x, y);
|
let (tx, ty) = r.scale_point_f(x, y);
|
||||||
r.render_texture(
|
r.render_texture(
|
||||||
&tex.texture,
|
&tex.texture,
|
||||||
|
None,
|
||||||
tx.round() as _,
|
tx.round() as _,
|
||||||
ty.round() as _,
|
ty.round() as _,
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -152,6 +152,7 @@ impl Renderer<'_> {
|
||||||
let (x, y) = self.base.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.base.render_texture(
|
self.base.render_texture(
|
||||||
&title.tex,
|
&title.tex,
|
||||||
|
None,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
None,
|
None,
|
||||||
|
|
@ -167,6 +168,7 @@ impl Renderer<'_> {
|
||||||
let (x, y) = self.base.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.base.render_texture(
|
self.base.render_texture(
|
||||||
&status.tex.texture,
|
&status.tex.texture,
|
||||||
|
None,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
None,
|
None,
|
||||||
|
|
@ -215,6 +217,7 @@ impl Renderer<'_> {
|
||||||
let y = y + (pos.height() - tex_height) / 2;
|
let y = y + (pos.height() - tex_height) / 2;
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&tex.texture,
|
&tex.texture,
|
||||||
|
None,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
None,
|
None,
|
||||||
|
|
@ -255,6 +258,7 @@ impl Renderer<'_> {
|
||||||
let (x, y) = self.base.scale_point(x + title.x, y + title.y);
|
let (x, y) = self.base.scale_point(x + title.x, y + title.y);
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&title.tex.texture,
|
&title.tex.texture,
|
||||||
|
None,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
None,
|
None,
|
||||||
|
|
@ -338,6 +342,7 @@ impl Renderer<'_> {
|
||||||
} else {
|
} else {
|
||||||
size = self.base.scale_point(size.0, size.1);
|
size = self.base.scale_point(size.0, size.1);
|
||||||
}
|
}
|
||||||
|
let alpha = surface.alpha();
|
||||||
if let Some(children) = children.deref() {
|
if let Some(children) = children.deref() {
|
||||||
macro_rules! render {
|
macro_rules! render {
|
||||||
($children:expr) => {
|
($children:expr) => {
|
||||||
|
|
@ -359,10 +364,10 @@ impl Renderer<'_> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
render!(&children.below);
|
render!(&children.below);
|
||||||
self.render_buffer(&buffer, x, y, *tpoints, size, bounds);
|
self.render_buffer(&buffer, alpha, x, y, *tpoints, size, bounds);
|
||||||
render!(&children.above);
|
render!(&children.above);
|
||||||
} else {
|
} else {
|
||||||
self.render_buffer(&buffer, x, y, *tpoints, size, bounds);
|
self.render_buffer(&buffer, alpha, x, y, *tpoints, size, bounds);
|
||||||
}
|
}
|
||||||
if let Some(result) = self.result.as_deref_mut() {
|
if let Some(result) = self.result.as_deref_mut() {
|
||||||
{
|
{
|
||||||
|
|
@ -379,6 +384,7 @@ impl Renderer<'_> {
|
||||||
pub fn render_buffer(
|
pub fn render_buffer(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &Rc<SurfaceBuffer>,
|
buffer: &Rc<SurfaceBuffer>,
|
||||||
|
alpha: Option<f32>,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
tpoints: SampleRect,
|
tpoints: SampleRect,
|
||||||
|
|
@ -388,6 +394,7 @@ impl Renderer<'_> {
|
||||||
if let Some(tex) = buffer.buffer.texture.get() {
|
if let Some(tex) = buffer.buffer.texture.get() {
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&tex,
|
&tex,
|
||||||
|
alpha,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
Some(tpoints),
|
Some(tpoints),
|
||||||
|
|
@ -406,7 +413,11 @@ impl Renderer<'_> {
|
||||||
};
|
};
|
||||||
if !rect.is_empty() {
|
if !rect.is_empty() {
|
||||||
self.base.ops.push(GfxApiOpt::Sync);
|
self.base.ops.push(GfxApiOpt::Sync);
|
||||||
self.base.fill_boxes(&[rect], color);
|
let mut color = *color;
|
||||||
|
if let Some(alpha) = alpha {
|
||||||
|
color = color * alpha;
|
||||||
|
}
|
||||||
|
self.base.fill_boxes(&[rect], &color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -448,6 +459,7 @@ impl Renderer<'_> {
|
||||||
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
let (x, y) = self.base.scale_point(x + bw, y + bw);
|
||||||
self.base.render_texture(
|
self.base.render_texture(
|
||||||
&title.texture,
|
&title.texture,
|
||||||
|
None,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ impl RendererBase<'_> {
|
||||||
pub fn render_texture(
|
pub fn render_texture(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture: &Rc<dyn GfxTexture>,
|
texture: &Rc<dyn GfxTexture>,
|
||||||
|
alpha: Option<f32>,
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
tpoints: Option<SampleRect>,
|
tpoints: Option<SampleRect>,
|
||||||
|
|
@ -174,6 +175,7 @@ impl RendererBase<'_> {
|
||||||
tex: texture.clone(),
|
tex: texture.clone(),
|
||||||
source: texcoord,
|
source: texcoord,
|
||||||
target,
|
target,
|
||||||
|
alpha,
|
||||||
buffer_resv,
|
buffer_resv,
|
||||||
acquire_sync,
|
acquire_sync,
|
||||||
release_sync,
|
release_sync,
|
||||||
|
|
|
||||||
|
|
@ -836,6 +836,7 @@ impl State {
|
||||||
sample_rect.buffer_transform = transform;
|
sample_rect.buffer_transform = transform;
|
||||||
renderer.base.render_texture(
|
renderer.base.render_texture(
|
||||||
src,
|
src,
|
||||||
|
None,
|
||||||
x_off,
|
x_off,
|
||||||
y_off,
|
y_off,
|
||||||
Some(sample_rect),
|
Some(sample_rect),
|
||||||
|
|
|
||||||
14
src/theme.rs
14
src/theme.rs
|
|
@ -1,6 +1,7 @@
|
||||||
use std::{
|
use std::{
|
||||||
cell::{Cell, RefCell},
|
cell::{Cell, RefCell},
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
|
ops::Mul,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||||
|
|
@ -23,6 +24,19 @@ impl Ord for Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<f32> for Color {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn mul(self, rhs: f32) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
r: self.r * rhs,
|
||||||
|
g: self.g * rhs,
|
||||||
|
b: self.b * rhs,
|
||||||
|
a: self.a * rhs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl PartialOrd for Color {
|
impl PartialOrd for Color {
|
||||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
Some(self.cmp(other))
|
Some(self.cmp(other))
|
||||||
|
|
|
||||||
6
wire/wp_alpha_modifier_surface_v1.txt
Normal file
6
wire/wp_alpha_modifier_surface_v1.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
request destroy {
|
||||||
|
}
|
||||||
|
|
||||||
|
request set_multiplier {
|
||||||
|
factor: u32,
|
||||||
|
}
|
||||||
7
wire/wp_alpha_modifier_v1.txt
Normal file
7
wire/wp_alpha_modifier_v1.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
request destroy {
|
||||||
|
}
|
||||||
|
|
||||||
|
request get_surface {
|
||||||
|
id: id(wp_alpha_modifier_surface_v1),
|
||||||
|
surface: id(wl_surface),
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue