wayland: implement alpha_modifier_v1
This commit is contained in:
parent
131f0481e8
commit
ff54a8ab96
37 changed files with 655 additions and 89 deletions
|
|
@ -73,7 +73,11 @@ use {
|
|||
},
|
||||
gfx_apis::gl::{
|
||||
gl::texture::image_target,
|
||||
renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture},
|
||||
renderer::{
|
||||
context::{GlRenderContext, TexCopyType, TexSourceType},
|
||||
framebuffer::Framebuffer,
|
||||
texture::Texture,
|
||||
},
|
||||
sys::{
|
||||
GL_BLEND, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, GL_TEXTURE_MIN_FILTER,
|
||||
GL_TRIANGLES, GL_TRIANGLE_STRIP,
|
||||
|
|
@ -336,16 +340,20 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
|||
},
|
||||
false => &ctx.tex_internal,
|
||||
};
|
||||
let prog = match texture.gl.format.has_alpha {
|
||||
true => {
|
||||
(gles.glEnable)(GL_BLEND);
|
||||
&progs.alpha
|
||||
}
|
||||
false => {
|
||||
(gles.glDisable)(GL_BLEND);
|
||||
&progs.solid
|
||||
}
|
||||
let copy_type = match tex.alpha.is_some() {
|
||||
true => TexCopyType::Multiply,
|
||||
false => TexCopyType::Identity,
|
||||
};
|
||||
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);
|
||||
|
||||
|
|
@ -354,6 +362,10 @@ fn render_texture(ctx: &GlRenderContext, tex: &CopyTexture) {
|
|||
let texcoord = tex.source.to_points();
|
||||
let pos = tex.target.to_points();
|
||||
|
||||
if let Some(alpha) = tex.alpha {
|
||||
(gles.glUniform1f)(prog.alpha, alpha);
|
||||
}
|
||||
|
||||
(gles.glVertexAttribPointer)(
|
||||
prog.texcoord as _,
|
||||
2,
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ use {
|
|||
},
|
||||
},
|
||||
ahash::AHashMap,
|
||||
enum_map::{enum_map, Enum, EnumMap},
|
||||
jay_config::video::GfxApi,
|
||||
std::{
|
||||
cell::{Cell, RefCell},
|
||||
|
|
@ -36,22 +37,35 @@ pub(crate) struct TexProg {
|
|||
pub(crate) pos: GLint,
|
||||
pub(crate) texcoord: GLint,
|
||||
pub(crate) tex: GLint,
|
||||
pub(crate) alpha: GLint,
|
||||
}
|
||||
|
||||
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 {
|
||||
pos: prog.get_attrib_location(ustr!("pos")),
|
||||
texcoord: prog.get_attrib_location(ustr!("texcoord")),
|
||||
tex: prog.get_uniform_location(ustr!("tex")),
|
||||
alpha,
|
||||
prog,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct TexProgs {
|
||||
pub alpha: TexProg,
|
||||
pub solid: TexProg,
|
||||
#[derive(Copy, Clone, PartialEq, Enum)]
|
||||
pub(in crate::gfx_apis::gl) enum TexCopyType {
|
||||
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 {
|
||||
|
|
@ -61,8 +75,8 @@ pub(in crate::gfx_apis::gl) struct GlRenderContext {
|
|||
|
||||
pub(crate) render_node: Rc<CString>,
|
||||
|
||||
pub(crate) tex_internal: TexProgs,
|
||||
pub(crate) tex_external: Option<TexProgs>,
|
||||
pub(crate) tex_internal: EnumMap<TexCopyType, EnumMap<TexSourceType, TexProg>>,
|
||||
pub(crate) tex_external: Option<EnumMap<TexCopyType, EnumMap<TexSourceType, TexProg>>>,
|
||||
|
||||
pub(crate) fill_prog: GlProgram,
|
||||
pub(crate) fill_prog_pos: GLint,
|
||||
|
|
@ -100,28 +114,37 @@ impl GlRenderContext {
|
|||
|
||||
unsafe fn new(ctx: &Rc<EglContext>, node: &Rc<CString>) -> Result<Self, RenderError> {
|
||||
let tex_vert = include_str!("../shaders/tex.vert.glsl");
|
||||
let tex_prog =
|
||||
GlProgram::from_shaders(ctx, tex_vert, include_str!("../shaders/tex.frag.glsl"))?;
|
||||
let tex_alpha_prog = GlProgram::from_shaders(
|
||||
ctx,
|
||||
tex_vert,
|
||||
include_str!("../shaders/tex-alpha.frag.glsl"),
|
||||
)?;
|
||||
let tex_external = if ctx.ext.contains(GL_OES_EGL_IMAGE_EXTERNAL) {
|
||||
let solid = GlProgram::from_shaders(
|
||||
ctx,
|
||||
tex_vert,
|
||||
include_str!("../shaders/tex-external.frag.glsl"),
|
||||
)?;
|
||||
let alpha = GlProgram::from_shaders(
|
||||
ctx,
|
||||
tex_vert,
|
||||
include_str!("../shaders/tex-external-alpha.frag.glsl"),
|
||||
)?;
|
||||
Some(TexProgs {
|
||||
alpha: TexProg::from(alpha),
|
||||
solid: TexProg::from(solid),
|
||||
let tex_frag = include_str!("../shaders/tex.frag.glsl");
|
||||
let create_programs = |external: bool| {
|
||||
let create_program = |alpha_multiplier: bool, alpha: bool| {
|
||||
let mut tex_frac_src = String::new();
|
||||
if external {
|
||||
tex_frac_src.push_str("#define EXTERNAL\n");
|
||||
}
|
||||
if alpha_multiplier {
|
||||
tex_frac_src.push_str("#define ALPHA_MULTIPLIER\n");
|
||||
}
|
||||
if alpha {
|
||||
tex_frac_src.push_str("#define ALPHA\n");
|
||||
}
|
||||
tex_frac_src.push_str(tex_frag);
|
||||
let prog = GlProgram::from_shaders(ctx, tex_vert, &tex_frac_src)?;
|
||||
Ok::<_, RenderError>(TexProg::from(prog, alpha_multiplier))
|
||||
};
|
||||
Ok::<_, RenderError>(enum_map! {
|
||||
TexCopyType::Identity => enum_map! {
|
||||
TexSourceType::Opaque => create_program(false, false)?,
|
||||
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 {
|
||||
None
|
||||
};
|
||||
|
|
@ -137,10 +160,7 @@ impl GlRenderContext {
|
|||
|
||||
render_node: node.clone(),
|
||||
|
||||
tex_internal: TexProgs {
|
||||
solid: TexProg::from(tex_prog),
|
||||
alpha: TexProg::from(tex_alpha_prog),
|
||||
},
|
||||
tex_internal,
|
||||
tex_external,
|
||||
|
||||
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;
|
||||
varying vec2 v_texcoord;
|
||||
#ifdef EXTERNAL
|
||||
uniform samplerExternalOES tex;
|
||||
#else
|
||||
uniform sampler2D tex;
|
||||
#endif
|
||||
#ifdef ALPHA_MULTIPLIER
|
||||
uniform float alpha;
|
||||
#endif
|
||||
|
||||
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);
|
||||
#endif // ALPHA_MULTIPLIER
|
||||
|
||||
#endif // ALPHA
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,9 @@ use {
|
|||
pipeline::{PipelineCreateInfo, VulkanPipeline},
|
||||
semaphore::VulkanSemaphore,
|
||||
shaders::{
|
||||
FillFragPushConstants, FillVertPushConstants, TexVertPushConstants, FILL_FRAG,
|
||||
FILL_VERT, TEX_FRAG, TEX_VERT,
|
||||
FillFragPushConstants, FillVertPushConstants, TexFragPushConstants,
|
||||
TexVertPushConstants, VulkanShader, FILL_FRAG, FILL_VERT, TEX_FRAG,
|
||||
TEX_FRAG_MULT_ALPHA, TEX_FRAG_MULT_OPAQUE, TEX_VERT,
|
||||
},
|
||||
staging::VulkanStagingBuffer,
|
||||
VulkanError,
|
||||
|
|
@ -41,6 +42,7 @@ use {
|
|||
},
|
||||
Device,
|
||||
},
|
||||
enum_map::{enum_map, Enum, EnumMap},
|
||||
isnt::std_1::collections::IsntHashMapExt,
|
||||
std::{
|
||||
cell::{Cell, RefCell},
|
||||
|
|
@ -56,8 +58,7 @@ pub struct VulkanRenderer {
|
|||
pub(super) formats: Rc<AHashMap<u32, GfxFormat>>,
|
||||
pub(super) device: Rc<VulkanDevice>,
|
||||
pub(super) fill_pipeline: Rc<VulkanPipeline>,
|
||||
pub(super) tex_opaque_pipeline: Rc<VulkanPipeline>,
|
||||
pub(super) tex_alpha_pipeline: Rc<VulkanPipeline>,
|
||||
pub(super) tex_pipelines: EnumMap<TexCopyType, EnumMap<TexSourceType, Rc<VulkanPipeline>>>,
|
||||
pub(super) command_pool: Rc<VulkanCommandPool>,
|
||||
pub(super) command_buffers: Stack<Rc<VulkanCommandBuffer>>,
|
||||
pub(super) wait_semaphores: Stack<Rc<VulkanSemaphore>>,
|
||||
|
|
@ -76,6 +77,18 @@ pub(super) struct UsedTexture {
|
|||
release_sync: ReleaseSync,
|
||||
}
|
||||
|
||||
#[derive(Enum)]
|
||||
pub(super) enum TexCopyType {
|
||||
Identity,
|
||||
Multiply,
|
||||
}
|
||||
|
||||
#[derive(Enum)]
|
||||
pub(super) enum TexSourceType {
|
||||
Opaque,
|
||||
HasAlpha,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(super) struct Memory {
|
||||
sample: Vec<Rc<VulkanImage>>,
|
||||
|
|
@ -115,6 +128,8 @@ impl VulkanDevice {
|
|||
let tex_descriptor_set_layout = self.create_descriptor_set_layout(&sampler)?;
|
||||
let tex_vert_shader = self.create_shader(TEX_VERT)?;
|
||||
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| {
|
||||
self.create_pipeline::<TexVertPushConstants, ()>(PipelineCreateInfo {
|
||||
vert: tex_vert_shader.clone(),
|
||||
|
|
@ -123,8 +138,18 @@ impl VulkanDevice {
|
|||
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_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 formats: AHashMap<u32, _> = self
|
||||
.formats
|
||||
|
|
@ -155,8 +180,16 @@ impl VulkanDevice {
|
|||
formats: Rc::new(formats),
|
||||
device: self.clone(),
|
||||
fill_pipeline,
|
||||
tex_opaque_pipeline,
|
||||
tex_alpha_pipeline,
|
||||
tex_pipelines: enum_map! {
|
||||
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_buffers: Default::default(),
|
||||
wait_semaphores: Default::default(),
|
||||
|
|
@ -449,10 +482,15 @@ impl VulkanRenderer {
|
|||
}
|
||||
GfxApiOpt::CopyTexture(c) => {
|
||||
let tex = c.tex.as_vk(&self.device.device);
|
||||
let pipeline = match tex.format.has_alpha {
|
||||
true => &self.tex_alpha_pipeline,
|
||||
false => &self.tex_opaque_pipeline,
|
||||
let copy_type = match c.alpha.is_some() {
|
||||
true => TexCopyType::Multiply,
|
||||
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);
|
||||
let vert = TexVertPushConstants {
|
||||
pos: c.target.to_points(),
|
||||
|
|
@ -480,6 +518,16 @@ impl VulkanRenderer {
|
|||
0,
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 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_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(super) device: Rc<VulkanDevice>,
|
||||
|
|
@ -38,7 +42,14 @@ pub struct TexVertPushConstants {
|
|||
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 TexFragPushConstants {}
|
||||
|
||||
impl VulkanDevice {
|
||||
pub(super) fn create_shader(
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
#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(location = 0) in vec2 tex_pos;
|
||||
layout(location = 0) out vec4 out_color;
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue