mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:27:35 +00:00
LibGL+LibGPU+LibSoftGPU: Implement blend equations
This implements support for `glBlendEquation` and `glBlendEquationSeparate`. These functions modify the calculation of the resulting color in blending mode.
This commit is contained in:
parent
55668c3e48
commit
aa3a6767f6
10 changed files with 202 additions and 30 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
|
||||
* Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
|
||||
* Copyright (c) 2022-2023, Jelle Raaijmakers <jelle@gmta.nl>
|
||||
* Copyright (c) 2022-2024, Jelle Raaijmakers <jelle@gmta.nl>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
@ -140,7 +140,7 @@ ALWAYS_INLINE static bool is_blend_factor_constant(GPU::BlendFactor blend_factor
|
|||
return (blend_factor == GPU::BlendFactor::One || blend_factor == GPU::BlendFactor::Zero);
|
||||
}
|
||||
|
||||
// OpenGL 1.5 § 4.1.8, table 4.1
|
||||
// OpenGL 2.0 § 4.1.8, table 4.2
|
||||
ALWAYS_INLINE static Vector4<f32x4> get_blend_factor(GPU::BlendFactor blend_factor, Vector4<f32x4> const& source_color, Vector4<f32x4> const& destination_color)
|
||||
{
|
||||
switch (blend_factor) {
|
||||
|
@ -173,6 +173,42 @@ ALWAYS_INLINE static Vector4<f32x4> get_blend_factor(GPU::BlendFactor blend_fact
|
|||
}
|
||||
}
|
||||
|
||||
// OpenGL 2.0 § 4.1.8, table 4.1
|
||||
ALWAYS_INLINE static Vector4<f32x4> blend_colors(
|
||||
GPU::BlendEquation rgb_mode,
|
||||
GPU::BlendEquation alpha_mode,
|
||||
Vector4<f32x4> const& source,
|
||||
Vector4<f32x4> const& source_weights,
|
||||
Vector4<f32x4> const& destination,
|
||||
Vector4<f32x4> const& destination_weights)
|
||||
{
|
||||
auto apply_equation = [&](GPU::BlendEquation mode, auto source, auto source_weights, auto destination, auto destination_weights) -> auto {
|
||||
switch (mode) {
|
||||
case GPU::BlendEquation::Add:
|
||||
return source * source_weights + destination * destination_weights;
|
||||
case GPU::BlendEquation::Subtract:
|
||||
return source * source_weights - destination * destination_weights;
|
||||
case GPU::BlendEquation::ReverseSubtract:
|
||||
return destination * source_weights - source * destination_weights;
|
||||
case GPU::BlendEquation::Min:
|
||||
return AK::min(source, destination);
|
||||
case GPU::BlendEquation::Max:
|
||||
return AK::max(source, destination);
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
// Single calculation if RGB mode is the same as the alpha mode
|
||||
if (rgb_mode == alpha_mode)
|
||||
return apply_equation(rgb_mode, source, source_weights, destination, destination_weights);
|
||||
|
||||
// Split RGB/alpha calculation
|
||||
auto rgb = apply_equation(rgb_mode, source.xyz(), source_weights.xyz(), destination.xyz(), destination_weights.xyz());
|
||||
auto alpha = apply_equation(alpha_mode, source.w(), source_weights.w(), destination.w(), destination_weights.w());
|
||||
return { rgb.x(), rgb.y(), rgb.z(), alpha };
|
||||
}
|
||||
|
||||
template<typename CB1, typename CB2, typename CB3>
|
||||
ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_coverage_mask, CB2 set_quad_depth, CB3 set_quad_attributes)
|
||||
{
|
||||
|
@ -239,16 +275,16 @@ ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_covera
|
|||
auto const qy0 = render_bounds_top & ~1;
|
||||
auto const qy1 = render_bounds_bottom & ~1;
|
||||
|
||||
// Blend factors
|
||||
Vector4<f32x4> src_factor;
|
||||
Vector4<f32x4> dst_factor;
|
||||
auto const src_factor_is_constant = is_blend_factor_constant(m_options.blend_source_factor);
|
||||
auto const dst_factor_is_constant = is_blend_factor_constant(m_options.blend_destination_factor);
|
||||
// Blend weights
|
||||
Vector4<f32x4> source_weights;
|
||||
Vector4<f32x4> destination_weights;
|
||||
auto const source_weights_are_constant = is_blend_factor_constant(m_options.blend_source_factor);
|
||||
auto const destination_weights_are_constant = is_blend_factor_constant(m_options.blend_destination_factor);
|
||||
if (m_options.enable_blending) {
|
||||
if (src_factor_is_constant)
|
||||
src_factor = get_blend_factor(m_options.blend_source_factor, {}, {});
|
||||
if (dst_factor_is_constant)
|
||||
dst_factor = get_blend_factor(m_options.blend_destination_factor, {}, {});
|
||||
if (source_weights_are_constant)
|
||||
source_weights = get_blend_factor(m_options.blend_source_factor, {}, {});
|
||||
if (destination_weights_are_constant)
|
||||
destination_weights = get_blend_factor(m_options.blend_destination_factor, {}, {});
|
||||
}
|
||||
|
||||
// Rasterize all quads
|
||||
|
@ -436,19 +472,19 @@ ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_covera
|
|||
|
||||
auto out_color = quad.get_output_vector4(SHADER_OUTPUT_FIRST_COLOR);
|
||||
|
||||
// Blend color values from pixel_staging into color_buffer
|
||||
if (m_options.enable_blending) {
|
||||
INCREASE_STATISTICS_COUNTER(g_num_pixels_blended, maskcount(quad.mask));
|
||||
|
||||
// Blend color values from pixel_staging into color_buffer
|
||||
auto const& src = out_color;
|
||||
auto const dst = to_vec4(dst_u32);
|
||||
auto const& source_color = out_color;
|
||||
auto const destination_color = to_vec4(dst_u32);
|
||||
|
||||
if (!src_factor_is_constant)
|
||||
src_factor = get_blend_factor(m_options.blend_source_factor, src, dst);
|
||||
if (!dst_factor_is_constant)
|
||||
dst_factor = get_blend_factor(m_options.blend_destination_factor, src, dst);
|
||||
if (!source_weights_are_constant)
|
||||
source_weights = get_blend_factor(m_options.blend_source_factor, source_color, destination_color);
|
||||
if (!destination_weights_are_constant)
|
||||
destination_weights = get_blend_factor(m_options.blend_destination_factor, source_color, destination_color);
|
||||
|
||||
out_color = src * src_factor + dst * dst_factor;
|
||||
out_color = blend_colors(m_options.blend_equation_rgb, m_options.blend_equation_alpha, source_color, source_weights, destination_color, destination_weights);
|
||||
}
|
||||
|
||||
auto const argb32_color = to_argb32(out_color);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue