diff --git a/docs/sphinx/reference-libobs-graphics-graphics.rst b/docs/sphinx/reference-libobs-graphics-graphics.rst index 6a99101b7..7820d8eca 100644 --- a/docs/sphinx/reference-libobs-graphics-graphics.rst +++ b/docs/sphinx/reference-libobs-graphics-graphics.rst @@ -768,21 +768,29 @@ Draw Functions .. function:: void gs_blend_function(enum gs_blend_type src, enum gs_blend_type dest) - Sets the blend function + Sets the blend function's source and destination factors - :param src: Blend type for the source - :param dest: Blend type for the destination + :param src: Blend type for the blending equation's source factors + :param dest: Blend type for the blending equation's destination factors --------------------- .. function:: void gs_blend_function_separate(enum gs_blend_type src_c, enum gs_blend_type dest_c, enum gs_blend_type src_a, enum gs_blend_type dest_a) - Sets the blend function for RGB and alpha separately + Sets the blend function's source and destination factors for RGB and alpha separately - :param src_c: Blend type for the source RGB - :param dest_c: Blend type for the destination RGB - :param src_a: Blend type for the source alpha - :param dest_a: Blend type for the destination alpha + :param src_c: Blend type for the blending equation's source RGB factor + :param dest_c: Blend type for the blending equation's destination RGB factor + :param src_a: Blend type for the blending equation's source alpha factor + :param dest_a: Blend type for the blending equation's destination alpha factor + +--------------------- + +.. function:: void gs_blend_op(enum gs_blend_op_type op) + + Sets the blend function's operation type + + :param op: Operation type for the blending equation --------------------- @@ -881,7 +889,7 @@ Texture Functions :param data: Pointer to array of texture data pointers :param flags: Can be 0 or a bitwise-OR combination of one or more of the following value: - + - GS_BUILD_MIPMAPS - Automatically builds mipmaps (Note: not fully tested) - GS_DYNAMIC - Dynamic @@ -1080,7 +1088,7 @@ Cube Texture Functions :param data: Pointer to array of texture data pointers :param flags: Can be 0 or a bitwise-OR combination of one or more of the following value: - + - GS_BUILD_MIPMAPS - Automatically builds mipmaps (Note: not fully tested) - GS_DYNAMIC - Dynamic diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index e32fc9642..5db6087d2 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -705,8 +705,10 @@ ID3D11BlendState *gs_device::AddBlendState() memset(&bd, 0, sizeof(bd)); for (int i = 0; i < 8; i++) { bd.RenderTarget[i].BlendEnable = blendState.blendEnabled; - bd.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; - bd.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; + bd.RenderTarget[i].BlendOp = + ConvertGSBlendOpType(blendState.op); + bd.RenderTarget[i].BlendOpAlpha = + ConvertGSBlendOpType(blendState.op); bd.RenderTarget[i].SrcBlend = ConvertGSBlendType(blendState.srcFactorC); bd.RenderTarget[i].DestBlend = @@ -2159,6 +2161,15 @@ void device_blend_function_separate(gs_device_t *device, device->blendStateChanged = true; } +void device_blend_op(gs_device_t *device, enum gs_blend_op_type op) +{ + if (device->blendState.op == op) + return; + + device->blendState.op = op; + device->blendStateChanged = true; +} + void device_depth_function(gs_device_t *device, enum gs_depth_test test) { if (device->zstencilState.depthFunc == test) diff --git a/libobs-d3d11/d3d11-subsystem.hpp b/libobs-d3d11/d3d11-subsystem.hpp index 0c12a655a..45d5e4dda 100644 --- a/libobs-d3d11/d3d11-subsystem.hpp +++ b/libobs-d3d11/d3d11-subsystem.hpp @@ -281,6 +281,24 @@ static inline D3D11_BLEND ConvertGSBlendType(gs_blend_type type) return D3D11_BLEND_ONE; } +static inline D3D11_BLEND_OP ConvertGSBlendOpType(gs_blend_op_type type) +{ + switch (type) { + case GS_BLEND_OP_ADD: + return D3D11_BLEND_OP_ADD; + case GS_BLEND_OP_SUBTRACT: + return D3D11_BLEND_OP_SUBTRACT; + case GS_BLEND_OP_REVERSE_SUBTRACT: + return D3D11_BLEND_OP_REV_SUBTRACT; + case GS_BLEND_OP_MIN: + return D3D11_BLEND_OP_MIN; + case GS_BLEND_OP_MAX: + return D3D11_BLEND_OP_MAX; + } + + return D3D11_BLEND_OP_ADD; +} + static inline D3D11_CULL_MODE ConvertGSCullMode(gs_cull_mode mode) { switch (mode) { @@ -832,6 +850,7 @@ struct BlendState { gs_blend_type destFactorC; gs_blend_type srcFactorA; gs_blend_type destFactorA; + gs_blend_op_type op; bool redEnabled; bool greenEnabled; @@ -844,6 +863,7 @@ struct BlendState { destFactorC(GS_BLEND_INVSRCALPHA), srcFactorA(GS_BLEND_ONE), destFactorA(GS_BLEND_INVSRCALPHA), + op(GS_BLEND_OP_ADD), redEnabled(true), greenEnabled(true), blueEnabled(true), diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index 4c33991bb..d53f9e123 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -1262,6 +1262,17 @@ void device_blend_function_separate(gs_device_t *device, UNUSED_PARAMETER(device); } +void device_blend_op(gs_device_t *device, enum gs_blend_op_type op) +{ + GLenum gl_blend_op = convert_gs_blend_op_type(op); + + glBlendEquation(gl_blend_op); + if (!gl_success("glBlendEquation")) + blog(LOG_ERROR, "device_blend_op (GL) failed"); + + UNUSED_PARAMETER(device); +} + void device_depth_function(gs_device_t *device, enum gs_depth_test test) { GLenum gl_test = convert_gs_depth_test(test); diff --git a/libobs-opengl/gl-subsystem.h b/libobs-opengl/gl-subsystem.h index da0d5819b..e1958b72a 100644 --- a/libobs-opengl/gl-subsystem.h +++ b/libobs-opengl/gl-subsystem.h @@ -294,6 +294,24 @@ static inline GLenum convert_gs_blend_type(enum gs_blend_type type) return GL_ONE; } +static inline GLenum convert_gs_blend_op_type(enum gs_blend_op_type type) +{ + switch (type) { + case GS_BLEND_OP_ADD: + return GL_FUNC_ADD; + case GS_BLEND_OP_SUBTRACT: + return GL_FUNC_SUBTRACT; + case GS_BLEND_OP_REVERSE_SUBTRACT: + return GL_FUNC_REVERSE_SUBTRACT; + case GS_BLEND_OP_MIN: + return GL_MIN; + case GS_BLEND_OP_MAX: + return GL_MAX; + } + + return GL_FUNC_ADD; +} + static inline GLenum convert_shader_type(enum gs_shader_type type) { switch (type) { diff --git a/libobs/graphics/device-exports.h b/libobs/graphics/device-exports.h index 5ea55e71c..7adbc5510 100644 --- a/libobs/graphics/device-exports.h +++ b/libobs/graphics/device-exports.h @@ -145,6 +145,8 @@ EXPORT void device_blend_function_separate(gs_device_t *device, enum gs_blend_type dest_c, enum gs_blend_type src_a, enum gs_blend_type dest_a); +EXPORT void device_blend_op(gs_device_t *device, enum gs_blend_op_type op); + EXPORT void device_depth_function(gs_device_t *device, enum gs_depth_test test); EXPORT void device_stencil_function(gs_device_t *device, enum gs_stencil_side side, diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index 948a854ca..c00ce5945 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -104,6 +104,7 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, GRAPHICS_IMPORT(device_enable_color); GRAPHICS_IMPORT(device_blend_function); GRAPHICS_IMPORT(device_blend_function_separate); + GRAPHICS_IMPORT(device_blend_op); GRAPHICS_IMPORT(device_depth_function); GRAPHICS_IMPORT(device_stencil_function); GRAPHICS_IMPORT(device_stencil_op); diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 8d2812c04..c3a91dd5f 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -147,6 +147,8 @@ struct gs_exports { enum gs_blend_type dest_c, enum gs_blend_type src_a, enum gs_blend_type dest_a); + void (*device_blend_op)(gs_device_t *device, enum gs_blend_op_type op); + void (*device_depth_function)(gs_device_t *device, enum gs_depth_test test); void (*device_stencil_function)(gs_device_t *device, @@ -344,6 +346,7 @@ struct blend_state { enum gs_blend_type dest_c; enum gs_blend_type src_a; enum gs_blend_type dest_a; + enum gs_blend_op_type op; }; struct graphics_subsystem { diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 3fae4d1b0..616f6c541 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -172,6 +172,10 @@ static bool graphics_init(struct graphics_subsystem *graphics) graphics->cur_blend_state.src_a = GS_BLEND_ONE; graphics->cur_blend_state.dest_a = GS_BLEND_INVSRCALPHA; + graphics->cur_blend_state.op = GS_BLEND_OP_ADD; + graphics->exports.device_blend_op(graphics->device, + graphics->cur_blend_state.op); + graphics->exports.device_leave_context(graphics->device); gs_init_image_deps(); @@ -1241,6 +1245,7 @@ void gs_blend_state_pop(void) gs_enable_blending(state->enabled); gs_blend_function_separate(state->src_c, state->dest_c, state->src_a, state->dest_a); + gs_blend_op(state->op); da_pop_back(graphics->blend_state_stack); } @@ -1258,10 +1263,12 @@ void gs_reset_blend_state(void) if (graphics->cur_blend_state.src_c != GS_BLEND_SRCALPHA || graphics->cur_blend_state.dest_c != GS_BLEND_INVSRCALPHA || graphics->cur_blend_state.src_a != GS_BLEND_ONE || - graphics->cur_blend_state.dest_a != GS_BLEND_INVSRCALPHA) + graphics->cur_blend_state.dest_a != GS_BLEND_INVSRCALPHA) { gs_blend_function_separate(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, GS_BLEND_ONE, GS_BLEND_INVSRCALPHA); + gs_blend_op(GS_BLEND_OP_ADD); + } } /* ------------------------------------------------------------------------- */ @@ -1998,6 +2005,18 @@ void gs_blend_function_separate(enum gs_blend_type src_c, graphics->device, src_c, dest_c, src_a, dest_a); } +void gs_blend_op(enum gs_blend_op_type op) +{ + graphics_t *graphics = thread_graphics; + + if (!gs_valid("gs_blend_op")) + return; + + graphics->cur_blend_state.op = op; + graphics->exports.device_blend_op(graphics->device, + graphics->cur_blend_state.op); +} + void gs_depth_function(enum gs_depth_test test) { graphics_t *graphics = thread_graphics; diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index c8f2c70ad..181f1f25d 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -111,6 +111,14 @@ enum gs_blend_type { GS_BLEND_SRCALPHASAT, }; +enum gs_blend_op_type { + GS_BLEND_OP_ADD, + GS_BLEND_OP_SUBTRACT, + GS_BLEND_OP_REVERSE_SUBTRACT, + GS_BLEND_OP_MIN, + GS_BLEND_OP_MAX +}; + enum gs_depth_test { GS_NEVER, GS_LESS, @@ -728,6 +736,8 @@ EXPORT void gs_blend_function_separate(enum gs_blend_type src_c, enum gs_blend_type dest_c, enum gs_blend_type src_a, enum gs_blend_type dest_a); +EXPORT void gs_blend_op(enum gs_blend_op_type op); + EXPORT void gs_depth_function(enum gs_depth_test test); EXPORT void gs_stencil_function(enum gs_stencil_side side,