mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:52:44 +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,10 +1,11 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com> |  * Copyright (c) 2021, Leon Albrecht <leon2002.la@gmail.com> | ||||||
|  * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl> |  * Copyright (c) 2022-2024, Jelle Raaijmakers <jelle@gmta.nl> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
|  | #include <AK/Array.h> | ||||||
| #include <AK/ByteString.h> | #include <AK/ByteString.h> | ||||||
| #include <AK/LexicalPath.h> | #include <AK/LexicalPath.h> | ||||||
| #include <LibCore/File.h> | #include <LibCore/File.h> | ||||||
|  | @ -21,9 +22,9 @@ | ||||||
| #endif | #endif | ||||||
| #define SAVE_OUTPUT false | #define SAVE_OUTPUT false | ||||||
| 
 | 
 | ||||||
| static NonnullOwnPtr<GL::GLContext> create_testing_context(int width, int height) | static NonnullOwnPtr<GL::GLContext> create_testing_context(int width, int height, Gfx::BitmapFormat format = Gfx::BitmapFormat::BGRx8888) | ||||||
| { | { | ||||||
|     auto bitmap = MUST(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRx8888, { width, height })); |     auto bitmap = MUST(Gfx::Bitmap::create(format, { width, height })); | ||||||
|     auto context = MUST(GL::create_context(*bitmap)); |     auto context = MUST(GL::create_context(*bitmap)); | ||||||
|     GL::make_context_current(context); |     GL::make_context_current(context); | ||||||
|     return context; |     return context; | ||||||
|  | @ -317,3 +318,61 @@ TEST_CASE(0011_tex_env_combine_with_constant_color) | ||||||
|     context->present(); |     context->present(); | ||||||
|     expect_bitmap_equals_reference(context->frontbuffer(), "0011_tex_env_combine_with_constant_color"sv); |     expect_bitmap_equals_reference(context->frontbuffer(), "0011_tex_env_combine_with_constant_color"sv); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | TEST_CASE(0012_blend_equations) | ||||||
|  | { | ||||||
|  |     auto context = create_testing_context(64, 64, Gfx::BitmapFormat::BGRA8888); | ||||||
|  | 
 | ||||||
|  |     // Assert initial state
 | ||||||
|  |     int actual_mode; | ||||||
|  |     glGetIntegerv(GL_BLEND_EQUATION_RGB, &actual_mode); | ||||||
|  |     EXPECT_EQ(actual_mode, GL_FUNC_ADD); | ||||||
|  |     glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &actual_mode); | ||||||
|  |     EXPECT_EQ(actual_mode, GL_FUNC_ADD); | ||||||
|  | 
 | ||||||
|  |     // Clear with alpha 0 so we get a transparent color buffer
 | ||||||
|  |     glClearColor(0, 0, 0, 0); | ||||||
|  |     glClear(GL_COLOR_BUFFER_BIT); | ||||||
|  | 
 | ||||||
|  |     glColor4f(.8f, .2f, .3f, .7f); | ||||||
|  |     glRecti(-1, -1, 1, 1); | ||||||
|  | 
 | ||||||
|  |     glColor4f(.3f, .1f, .8f, .5f); | ||||||
|  |     glEnable(GL_BLEND); | ||||||
|  |     glBlendFunc(GL_ONE, GL_ONE); | ||||||
|  | 
 | ||||||
|  |     static constexpr Array<GLenum, 5> blend_modes = { | ||||||
|  |         GL_FUNC_ADD, | ||||||
|  |         GL_FUNC_SUBTRACT, | ||||||
|  |         GL_FUNC_REVERSE_SUBTRACT, | ||||||
|  |         GL_MIN, | ||||||
|  |         GL_MAX, | ||||||
|  |     }; | ||||||
|  |     auto constexpr grid_size = blend_modes.size(); | ||||||
|  |     auto constexpr cell_size = 2.f / grid_size; | ||||||
|  |     for (size_t x = 0; x < grid_size; ++x) { | ||||||
|  |         for (size_t y = 0; y < grid_size; ++y) { | ||||||
|  |             auto rgb_mode = blend_modes[x]; | ||||||
|  |             auto alpha_mode = blend_modes[y]; | ||||||
|  | 
 | ||||||
|  |             glBlendEquationSeparate(rgb_mode, alpha_mode); | ||||||
|  | 
 | ||||||
|  |             glGetIntegerv(GL_BLEND_EQUATION_RGB, &actual_mode); | ||||||
|  |             EXPECT_EQ(static_cast<GLenum>(actual_mode), rgb_mode); | ||||||
|  | 
 | ||||||
|  |             glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &actual_mode); | ||||||
|  |             EXPECT_EQ(static_cast<GLenum>(actual_mode), alpha_mode); | ||||||
|  | 
 | ||||||
|  |             glRectf( | ||||||
|  |                 -1.f + cell_size * static_cast<float>(x), | ||||||
|  |                 1.f - cell_size * static_cast<float>(y), | ||||||
|  |                 -1.f + cell_size * static_cast<float>(x + 1), | ||||||
|  |                 1.f - cell_size * static_cast<float>(y + 1)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     EXPECT_EQ(glGetError(), 0u); | ||||||
|  | 
 | ||||||
|  |     context->present(); | ||||||
|  |     expect_bitmap_equals_reference(context->frontbuffer(), "0012_blend_equations"sv); | ||||||
|  | } | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								Tests/LibGL/reference-images/0012_blend_equations.qoi
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								Tests/LibGL/reference-images/0012_blend_equations.qoi
									
										
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> |  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl> |  * Copyright (c) 2022-2024, Jelle Raaijmakers <jelle@gmta.nl> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -25,6 +25,10 @@ Optional<ContextParameter> GLContext::get_context_parameter(GLenum name) | ||||||
|     case GL_BLEND_DST: |     case GL_BLEND_DST: | ||||||
|     case GL_BLEND_DST_ALPHA: |     case GL_BLEND_DST_ALPHA: | ||||||
|         return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } }; |         return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } }; | ||||||
|  |     case GL_BLEND_EQUATION_ALPHA: | ||||||
|  |         return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_equation_alpha) } }; | ||||||
|  |     case GL_BLEND_EQUATION_RGB: | ||||||
|  |         return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_equation_rgb) } }; | ||||||
|     case GL_BLEND_SRC: |     case GL_BLEND_SRC: | ||||||
|     case GL_BLEND_SRC_ALPHA: |     case GL_BLEND_SRC_ALPHA: | ||||||
|         return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } }; |         return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } }; | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> |  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  * Copyright (c) 2021-2022, Jelle Raaijmakers <jelle@gmta.nl> |  * Copyright (c) 2021-2024, Jelle Raaijmakers <jelle@gmta.nl> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -380,11 +380,18 @@ extern "C" { | ||||||
| #define GL_LIGHT6 0x4006 | #define GL_LIGHT6 0x4006 | ||||||
| #define GL_LIGHT7 0x4007 | #define GL_LIGHT7 0x4007 | ||||||
| 
 | 
 | ||||||
| // More blend factors
 | // Blend factors & modes
 | ||||||
| #define GL_CONSTANT_COLOR 0x8001 | #define GL_CONSTANT_COLOR 0x8001 | ||||||
| #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 | #define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 | ||||||
| #define GL_CONSTANT_ALPHA 0x8003 | #define GL_CONSTANT_ALPHA 0x8003 | ||||||
| #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 | #define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 | ||||||
|  | #define GL_FUNC_ADD 0x8006 | ||||||
|  | #define GL_MIN 0x8007 | ||||||
|  | #define GL_MAX 0x8008 | ||||||
|  | #define GL_BLEND_EQUATION_RGB 0x8009 | ||||||
|  | #define GL_FUNC_SUBTRACT 0x800A | ||||||
|  | #define GL_FUNC_REVERSE_SUBTRACT 0x800B | ||||||
|  | #define GL_BLEND_EQUATION_ALPHA 0x883D | ||||||
| 
 | 
 | ||||||
| // Points
 | // Points
 | ||||||
| #define GL_POINT_SMOOTH 0x0B10 | #define GL_POINT_SMOOTH 0x0B10 | ||||||
|  |  | ||||||
|  | @ -50,9 +50,15 @@ | ||||||
|     }, |     }, | ||||||
|     "BlendEquation": { |     "BlendEquation": { | ||||||
|         "arguments": [ |         "arguments": [ | ||||||
|             {"type": "GLenum", "name": "mode"} |             {"type": "GLenum", "name": "mode"}, | ||||||
|  |             {"expression": "mode"} | ||||||
|         ], |         ], | ||||||
|         "unimplemented": true |         "implementation": "blend_equation_separate" | ||||||
|  |     }, | ||||||
|  |     "BlendEquationSeparate": { | ||||||
|  |         "arguments": [ | ||||||
|  |             {"type": "GLenum", "name": ["modeRGB", "modeAlpha"]} | ||||||
|  |         ] | ||||||
|     }, |     }, | ||||||
|     "BlendFunc": { |     "BlendFunc": { | ||||||
|         "arguments": [ |         "arguments": [ | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> |  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  * Copyright (c) 2022-2023, Jelle Raaijmakers <jelle@gmta.nl> |  * Copyright (c) 2022-2024, Jelle Raaijmakers <jelle@gmta.nl> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -261,6 +261,50 @@ void GLContext::gl_finish() | ||||||
|     // No-op since GLContext is completely synchronous at the moment
 |     // No-op since GLContext is completely synchronous at the moment
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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); | ||||||
|  | 
 | ||||||
|  |     RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); | ||||||
|  |     RETURN_WITH_ERROR_IF(!(rgb_mode == GL_FUNC_ADD | ||||||
|  |                              || rgb_mode == GL_FUNC_SUBTRACT | ||||||
|  |                              || rgb_mode == GL_FUNC_REVERSE_SUBTRACT | ||||||
|  |                              || rgb_mode == GL_MIN | ||||||
|  |                              || rgb_mode == GL_MAX), | ||||||
|  |         GL_INVALID_ENUM); | ||||||
|  |     RETURN_WITH_ERROR_IF(!(alpha_mode == GL_FUNC_ADD | ||||||
|  |                              || alpha_mode == GL_FUNC_SUBTRACT | ||||||
|  |                              || alpha_mode == GL_FUNC_REVERSE_SUBTRACT | ||||||
|  |                              || alpha_mode == GL_MIN | ||||||
|  |                              || alpha_mode == GL_MAX), | ||||||
|  |         GL_INVALID_ENUM); | ||||||
|  | 
 | ||||||
|  |     m_blend_equation_rgb = rgb_mode; | ||||||
|  |     m_blend_equation_alpha = alpha_mode; | ||||||
|  | 
 | ||||||
|  |     auto map_gl_blend_equation_to_device = [](GLenum equation) constexpr { | ||||||
|  |         switch (equation) { | ||||||
|  |         case GL_FUNC_ADD: | ||||||
|  |             return GPU::BlendEquation::Add; | ||||||
|  |         case GL_FUNC_SUBTRACT: | ||||||
|  |             return GPU::BlendEquation::Subtract; | ||||||
|  |         case GL_FUNC_REVERSE_SUBTRACT: | ||||||
|  |             return GPU::BlendEquation::ReverseSubtract; | ||||||
|  |         case GL_MIN: | ||||||
|  |             return GPU::BlendEquation::Min; | ||||||
|  |         case GL_MAX: | ||||||
|  |             return GPU::BlendEquation::Max; | ||||||
|  |         default: | ||||||
|  |             VERIFY_NOT_REACHED(); | ||||||
|  |         } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     auto options = m_rasterizer->options(); | ||||||
|  |     options.blend_equation_rgb = map_gl_blend_equation_to_device(m_blend_equation_rgb); | ||||||
|  |     options.blend_equation_alpha = map_gl_blend_equation_to_device(m_blend_equation_alpha); | ||||||
|  |     m_rasterizer->set_options(options); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void GLContext::gl_blend_func(GLenum src_factor, GLenum dst_factor) | void GLContext::gl_blend_func(GLenum src_factor, GLenum dst_factor) | ||||||
| { | { | ||||||
|     APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_blend_func, src_factor, dst_factor); |     APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_blend_func, src_factor, dst_factor); | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  * Copyright (c) 2021-2022, Jesse Buhagiar <jooster669@gmail.com> |  * Copyright (c) 2021-2022, 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 |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -148,6 +148,7 @@ public: | ||||||
|     GLboolean gl_is_list(GLuint list); |     GLboolean gl_is_list(GLuint list); | ||||||
|     void gl_flush(); |     void gl_flush(); | ||||||
|     void gl_finish(); |     void gl_finish(); | ||||||
|  |     void gl_blend_equation_separate(GLenum rgb_mode, GLenum alpha_mode); | ||||||
|     void gl_blend_func(GLenum src_factor, GLenum dst_factor); |     void gl_blend_func(GLenum src_factor, GLenum dst_factor); | ||||||
|     void gl_shade_model(GLenum mode); |     void gl_shade_model(GLenum mode); | ||||||
|     void gl_alpha_func(GLenum func, GLclampf ref); |     void gl_alpha_func(GLenum func, GLclampf ref); | ||||||
|  | @ -336,6 +337,9 @@ private: | ||||||
|     GLenum m_blend_source_factor = GL_ONE; |     GLenum m_blend_source_factor = GL_ONE; | ||||||
|     GLenum m_blend_destination_factor = GL_ZERO; |     GLenum m_blend_destination_factor = GL_ZERO; | ||||||
| 
 | 
 | ||||||
|  |     GLenum m_blend_equation_rgb = GL_FUNC_ADD; | ||||||
|  |     GLenum m_blend_equation_alpha = GL_FUNC_ADD; | ||||||
|  | 
 | ||||||
|     bool m_alpha_test_enabled = false; |     bool m_alpha_test_enabled = false; | ||||||
|     GLenum m_alpha_test_func = GL_ALWAYS; |     GLenum m_alpha_test_func = GL_ALWAYS; | ||||||
|     GLclampf m_alpha_test_ref_value = 0; |     GLclampf m_alpha_test_ref_value = 0; | ||||||
|  | @ -469,6 +473,7 @@ private: | ||||||
|             decltype(&GLContext::gl_cull_face), |             decltype(&GLContext::gl_cull_face), | ||||||
|             decltype(&GLContext::gl_call_list), |             decltype(&GLContext::gl_call_list), | ||||||
|             decltype(&GLContext::gl_call_lists), |             decltype(&GLContext::gl_call_lists), | ||||||
|  |             decltype(&GLContext::gl_blend_equation_separate), | ||||||
|             decltype(&GLContext::gl_blend_func), |             decltype(&GLContext::gl_blend_func), | ||||||
|             decltype(&GLContext::gl_shade_model), |             decltype(&GLContext::gl_shade_model), | ||||||
|             decltype(&GLContext::gl_alpha_func), |             decltype(&GLContext::gl_alpha_func), | ||||||
|  |  | ||||||
|  | @ -1,5 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  |  * Copyright (c) 2024, Jelle Raaijmakers <jelle@gmta.nl> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -21,6 +22,14 @@ enum class AlphaTestFunction { | ||||||
|     Greater, |     Greater, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum class BlendEquation { | ||||||
|  |     Add, | ||||||
|  |     Subtract, | ||||||
|  |     ReverseSubtract, | ||||||
|  |     Min, | ||||||
|  |     Max, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| enum class BlendFactor { | enum class BlendFactor { | ||||||
|     Zero, |     Zero, | ||||||
|     One, |     One, | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl> |  * Copyright (c) 2022-2024, Jelle Raaijmakers <jelle@gmta.nl> | ||||||
|  * |  * | ||||||
|  * SPDX-License-Identifier: BSD-2-Clause |  * SPDX-License-Identifier: BSD-2-Clause | ||||||
|  */ |  */ | ||||||
|  | @ -23,6 +23,8 @@ struct RasterizerOptions { | ||||||
|     AlphaTestFunction alpha_test_func { AlphaTestFunction::Always }; |     AlphaTestFunction alpha_test_func { AlphaTestFunction::Always }; | ||||||
|     float alpha_test_ref_value { 0 }; |     float alpha_test_ref_value { 0 }; | ||||||
|     bool enable_blending { false }; |     bool enable_blending { false }; | ||||||
|  |     BlendEquation blend_equation_rgb { BlendEquation::Add }; | ||||||
|  |     BlendEquation blend_equation_alpha { BlendEquation::Add }; | ||||||
|     BlendFactor blend_source_factor { BlendFactor::One }; |     BlendFactor blend_source_factor { BlendFactor::One }; | ||||||
|     BlendFactor blend_destination_factor { BlendFactor::One }; |     BlendFactor blend_destination_factor { BlendFactor::One }; | ||||||
|     u32 color_mask { 0xffffffff }; |     u32 color_mask { 0xffffffff }; | ||||||
|  |  | ||||||
|  | @ -1,7 +1,7 @@ | ||||||
| /*
 | /*
 | ||||||
|  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> |  * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org> | ||||||
|  * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com> |  * 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 |  * 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); |     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) | 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) { |     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> | 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) | 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 qy0 = render_bounds_top & ~1; | ||||||
|     auto const qy1 = render_bounds_bottom & ~1; |     auto const qy1 = render_bounds_bottom & ~1; | ||||||
| 
 | 
 | ||||||
|     // Blend factors
 |     // Blend weights
 | ||||||
|     Vector4<f32x4> src_factor; |     Vector4<f32x4> source_weights; | ||||||
|     Vector4<f32x4> dst_factor; |     Vector4<f32x4> destination_weights; | ||||||
|     auto const src_factor_is_constant = is_blend_factor_constant(m_options.blend_source_factor); |     auto const source_weights_are_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); |     auto const destination_weights_are_constant = is_blend_factor_constant(m_options.blend_destination_factor); | ||||||
|     if (m_options.enable_blending) { |     if (m_options.enable_blending) { | ||||||
|         if (src_factor_is_constant) |         if (source_weights_are_constant) | ||||||
|             src_factor = get_blend_factor(m_options.blend_source_factor, {}, {}); |             source_weights = get_blend_factor(m_options.blend_source_factor, {}, {}); | ||||||
|         if (dst_factor_is_constant) |         if (destination_weights_are_constant) | ||||||
|             dst_factor = get_blend_factor(m_options.blend_destination_factor, {}, {}); |             destination_weights = get_blend_factor(m_options.blend_destination_factor, {}, {}); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Rasterize all quads
 |     // 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); |             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) { |             if (m_options.enable_blending) { | ||||||
|                 INCREASE_STATISTICS_COUNTER(g_num_pixels_blended, maskcount(quad.mask)); |                 INCREASE_STATISTICS_COUNTER(g_num_pixels_blended, maskcount(quad.mask)); | ||||||
| 
 | 
 | ||||||
|                 // Blend color values from pixel_staging into color_buffer
 |                 auto const& source_color = out_color; | ||||||
|                 auto const& src = out_color; |                 auto const destination_color = to_vec4(dst_u32); | ||||||
|                 auto const dst = to_vec4(dst_u32); |  | ||||||
| 
 | 
 | ||||||
|                 if (!src_factor_is_constant) |                 if (!source_weights_are_constant) | ||||||
|                     src_factor = get_blend_factor(m_options.blend_source_factor, src, dst); |                     source_weights = get_blend_factor(m_options.blend_source_factor, source_color, destination_color); | ||||||
|                 if (!dst_factor_is_constant) |                 if (!destination_weights_are_constant) | ||||||
|                     dst_factor = get_blend_factor(m_options.blend_destination_factor, src, dst); |                     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); |             auto const argb32_color = to_argb32(out_color); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Jelle Raaijmakers
						Jelle Raaijmakers