mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:14:58 +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