diff --git a/Userland/Libraries/LibGL/Blending.cpp b/Userland/Libraries/LibGL/Blending.cpp index b2b87fc2a38..9053ce22aef 100644 --- a/Userland/Libraries/LibGL/Blending.cpp +++ b/Userland/Libraries/LibGL/Blending.cpp @@ -8,6 +8,19 @@ namespace GL { +void GLContext::gl_blend_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +{ + APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_blend_color, red, green, blue, alpha); + RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); + + m_blend_color = { red, green, blue, alpha }; + m_blend_color.clamp(0.f, 1.f); + + auto options = m_rasterizer->options(); + options.blend_color = m_blend_color; + m_rasterizer->set_options(options); +} + void GLContext::gl_blend_equation_separate(GLenum rgb_mode, GLenum alpha_mode) { APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_blend_equation_separate, rgb_mode, alpha_mode); @@ -119,6 +132,14 @@ void GLContext::gl_blend_func(GLenum src_factor, GLenum dst_factor) return GPU::BlendFactor::DstAlpha; case GL_ONE_MINUS_DST_ALPHA: return GPU::BlendFactor::OneMinusDstAlpha; + case GL_CONSTANT_COLOR: + return GPU::BlendFactor::ConstantColor; + case GL_ONE_MINUS_CONSTANT_COLOR: + return GPU::BlendFactor::OneMinusConstantColor; + case GL_CONSTANT_ALPHA: + return GPU::BlendFactor::ConstantAlpha; + case GL_ONE_MINUS_CONSTANT_ALPHA: + return GPU::BlendFactor::OneMinusConstantAlpha; case GL_SRC_ALPHA_SATURATE: return GPU::BlendFactor::SrcAlphaSaturate; default: diff --git a/Userland/Libraries/LibGL/GLAPI.json b/Userland/Libraries/LibGL/GLAPI.json index 558257b3219..216b8ddbdf9 100644 --- a/Userland/Libraries/LibGL/GLAPI.json +++ b/Userland/Libraries/LibGL/GLAPI.json @@ -48,6 +48,11 @@ {"type": "GLubyte const*", "name": "bitmap"} ] }, + "BlendColor": { + "arguments": [ + {"type": "GLclampf", "name": ["red", "green", "blue", "alpha"]} + ] + }, "BlendEquation": { "arguments": [ {"type": "GLenum", "name": "mode"}, diff --git a/Userland/Libraries/LibGL/GLContext.h b/Userland/Libraries/LibGL/GLContext.h index 6556d82f89a..6f25d4370da 100644 --- a/Userland/Libraries/LibGL/GLContext.h +++ b/Userland/Libraries/LibGL/GLContext.h @@ -148,6 +148,7 @@ public: GLboolean gl_is_list(GLuint list); void gl_flush(); void gl_finish(); + void gl_blend_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha); void gl_blend_equation_separate(GLenum rgb_mode, GLenum alpha_mode); void gl_blend_func(GLenum src_factor, GLenum dst_factor); void gl_shade_model(GLenum mode); @@ -334,6 +335,7 @@ private: GLenum m_culled_sides = GL_BACK; bool m_blend_enabled = false; + FloatVector4 m_blend_color { 0.f, 0.f, 0.f, 0.f }; GLenum m_blend_source_factor = GL_ONE; GLenum m_blend_destination_factor = GL_ZERO; @@ -473,6 +475,7 @@ private: decltype(&GLContext::gl_cull_face), decltype(&GLContext::gl_call_list), decltype(&GLContext::gl_call_lists), + decltype(&GLContext::gl_blend_color), decltype(&GLContext::gl_blend_equation_separate), decltype(&GLContext::gl_blend_func), decltype(&GLContext::gl_shade_model), diff --git a/Userland/Libraries/LibGPU/Enums.h b/Userland/Libraries/LibGPU/Enums.h index e42af041652..f6d131cab6d 100644 --- a/Userland/Libraries/LibGPU/Enums.h +++ b/Userland/Libraries/LibGPU/Enums.h @@ -33,14 +33,18 @@ enum class BlendEquation { enum class BlendFactor { Zero, One, - SrcAlpha, - OneMinusSrcAlpha, SrcColor, OneMinusSrcColor, - DstAlpha, - OneMinusDstAlpha, DstColor, OneMinusDstColor, + SrcAlpha, + OneMinusSrcAlpha, + DstAlpha, + OneMinusDstAlpha, + ConstantColor, + OneMinusConstantColor, + ConstantAlpha, + OneMinusConstantAlpha, SrcAlphaSaturate, }; diff --git a/Userland/Libraries/LibGPU/RasterizerOptions.h b/Userland/Libraries/LibGPU/RasterizerOptions.h index 184267587d8..a9e24f678b9 100644 --- a/Userland/Libraries/LibGPU/RasterizerOptions.h +++ b/Userland/Libraries/LibGPU/RasterizerOptions.h @@ -23,6 +23,7 @@ struct RasterizerOptions { AlphaTestFunction alpha_test_func { AlphaTestFunction::Always }; float alpha_test_ref_value { 0 }; bool enable_blending { false }; + FloatVector4 blend_color { 0.f, 0.f, 0.f, 0.f }; BlendEquation blend_equation_rgb { BlendEquation::Add }; BlendEquation blend_equation_alpha { BlendEquation::Add }; BlendFactor blend_source_factor { BlendFactor::One }; diff --git a/Userland/Libraries/LibSoftGPU/Device.cpp b/Userland/Libraries/LibSoftGPU/Device.cpp index 5e4e486ff8c..cd5cedf26bf 100644 --- a/Userland/Libraries/LibSoftGPU/Device.cpp +++ b/Userland/Libraries/LibSoftGPU/Device.cpp @@ -137,37 +137,50 @@ ALWAYS_INLINE static void test_alpha(PixelQuad& quad, GPU::AlphaTestFunction alp ALWAYS_INLINE static bool is_blend_factor_constant(GPU::BlendFactor blend_factor) { - return (blend_factor == GPU::BlendFactor::One || blend_factor == GPU::BlendFactor::Zero); + return blend_factor == GPU::BlendFactor::Zero + || blend_factor == GPU::BlendFactor::One + || blend_factor == GPU::BlendFactor::ConstantColor + || blend_factor == GPU::BlendFactor::OneMinusConstantColor + || blend_factor == GPU::BlendFactor::ConstantAlpha + || blend_factor == GPU::BlendFactor::OneMinusConstantAlpha; } // OpenGL 2.0 ยง 4.1.8, table 4.2 -ALWAYS_INLINE static Vector4 get_blend_factor(GPU::BlendFactor blend_factor, Vector4 const& source_color, Vector4 const& destination_color) +ALWAYS_INLINE static Vector4 get_blend_factor(GPU::BlendFactor blend_factor, FloatVector4 blend_color, Vector4 const& source_color, Vector4 const& destination_color) { switch (blend_factor) { - case GPU::BlendFactor::DstAlpha: - return to_vec4(destination_color.w()); - case GPU::BlendFactor::DstColor: - return destination_color; + case GPU::BlendFactor::Zero: + return to_vec4(expand4(0.f)); case GPU::BlendFactor::One: return to_vec4(expand4(1.f)); - case GPU::BlendFactor::OneMinusDstAlpha: - return to_vec4(1.f - destination_color.w()); - case GPU::BlendFactor::OneMinusDstColor: - return to_vec4(expand4(1.f)) - destination_color; - case GPU::BlendFactor::OneMinusSrcAlpha: - return to_vec4(1.f - source_color.w()); + case GPU::BlendFactor::SrcColor: + return source_color; case GPU::BlendFactor::OneMinusSrcColor: return to_vec4(expand4(1.f)) - source_color; + case GPU::BlendFactor::DstColor: + return destination_color; + case GPU::BlendFactor::OneMinusDstColor: + return to_vec4(expand4(1.f)) - destination_color; case GPU::BlendFactor::SrcAlpha: return to_vec4(source_color.w()); + case GPU::BlendFactor::OneMinusSrcAlpha: + return to_vec4(1.f - source_color.w()); + case GPU::BlendFactor::DstAlpha: + return to_vec4(destination_color.w()); + case GPU::BlendFactor::OneMinusDstAlpha: + return to_vec4(1.f - destination_color.w()); + case GPU::BlendFactor::ConstantColor: + return expand4(blend_color); + case GPU::BlendFactor::OneMinusConstantColor: + return expand4(FloatVector4 { 1.f, 1.f, 1.f, 1.f } - blend_color); + case GPU::BlendFactor::ConstantAlpha: + return to_vec4(expand4(blend_color.w())); + case GPU::BlendFactor::OneMinusConstantAlpha: + return to_vec4(expand4(1.f - blend_color.w())); case GPU::BlendFactor::SrcAlphaSaturate: { auto saturated = min(source_color.w(), 1.f - destination_color.w()); return { saturated, saturated, saturated, expand4(1.f) }; } - case GPU::BlendFactor::SrcColor: - return source_color; - case GPU::BlendFactor::Zero: - return to_vec4(expand4(0.f)); default: VERIFY_NOT_REACHED(); } @@ -282,9 +295,9 @@ ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_covera auto const destination_weights_are_constant = is_blend_factor_constant(m_options.blend_destination_factor); if (m_options.enable_blending) { if (source_weights_are_constant) - source_weights = get_blend_factor(m_options.blend_source_factor, {}, {}); + source_weights = get_blend_factor(m_options.blend_source_factor, m_options.blend_color, {}, {}); if (destination_weights_are_constant) - destination_weights = get_blend_factor(m_options.blend_destination_factor, {}, {}); + destination_weights = get_blend_factor(m_options.blend_destination_factor, m_options.blend_color, {}, {}); } // Rasterize all quads @@ -480,9 +493,9 @@ ALWAYS_INLINE void Device::rasterize(Gfx::IntRect& render_bounds, CB1 set_covera auto const destination_color = to_vec4(dst_u32); if (!source_weights_are_constant) - source_weights = get_blend_factor(m_options.blend_source_factor, source_color, destination_color); + source_weights = get_blend_factor(m_options.blend_source_factor, m_options.blend_color, source_color, destination_color); if (!destination_weights_are_constant) - destination_weights = get_blend_factor(m_options.blend_destination_factor, source_color, destination_color); + destination_weights = get_blend_factor(m_options.blend_destination_factor, m_options.blend_color, source_color, destination_color); out_color = blend_colors(m_options.blend_equation_rgb, m_options.blend_equation_alpha, source_color, source_weights, destination_color, destination_weights); }