diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 33dc087f4..4c77a3b01 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -302,13 +302,13 @@ ID3D11BlendState *gs_device::AddBlendState() bd.RenderTarget[i].BlendOp = D3D11_BLEND_OP_ADD; bd.RenderTarget[i].BlendOpAlpha = D3D11_BLEND_OP_ADD; bd.RenderTarget[i].SrcBlend = - ConvertGSBlendType(blendState.srcFactor); + ConvertGSBlendType(blendState.srcFactorC); bd.RenderTarget[i].DestBlend = - ConvertGSBlendType(blendState.destFactor); + ConvertGSBlendType(blendState.destFactorC); bd.RenderTarget[i].SrcBlendAlpha = - bd.RenderTarget[i].SrcBlend; + ConvertGSBlendType(blendState.srcFactorA); bd.RenderTarget[i].DestBlendAlpha = - bd.RenderTarget[i].DestBlend; + ConvertGSBlendType(blendState.destFactorA); bd.RenderTarget[i].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; } @@ -1388,15 +1388,36 @@ void device_enable_color(gs_device_t *device, bool red, bool green, void device_blend_function(gs_device_t *device, enum gs_blend_type src, enum gs_blend_type dest) { - if (device->blendState.srcFactor == src && - device->blendState.destFactor == dest) + if (device->blendState.srcFactorC == src && + device->blendState.destFactorC == dest && + device->blendState.srcFactorA == src && + device->blendState.destFactorA == dest) return; - device->blendState.srcFactor = src; - device->blendState.destFactor = dest; + device->blendState.srcFactorC = src; + device->blendState.destFactorC= dest; + device->blendState.srcFactorA = src; + device->blendState.destFactorA= dest; device->blendStateChanged = true; } +void device_blend_function_separate(gs_device_t *device, + enum gs_blend_type src_c, enum gs_blend_type dest_c, + enum gs_blend_type src_a, enum gs_blend_type dest_a) +{ + if (device->blendState.srcFactorC == src_c && + device->blendState.destFactorC == dest_c && + device->blendState.srcFactorA == src_a && + device->blendState.destFactorA == dest_a) + return; + + device->blendState.srcFactorC = src_c; + device->blendState.destFactorC = dest_c; + device->blendState.srcFactorA = src_a; + device->blendState.destFactorA = dest_a; + 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 73b6d6f2f..188cad339 100644 --- a/libobs-d3d11/d3d11-subsystem.hpp +++ b/libobs-d3d11/d3d11-subsystem.hpp @@ -495,8 +495,10 @@ struct gs_swap_chain { struct BlendState { bool blendEnabled; - gs_blend_type srcFactor; - gs_blend_type destFactor; + gs_blend_type srcFactorC; + gs_blend_type destFactorC; + gs_blend_type srcFactorA; + gs_blend_type destFactorA; bool redEnabled; bool greenEnabled; @@ -505,8 +507,10 @@ struct BlendState { inline BlendState() : blendEnabled (true), - srcFactor (GS_BLEND_SRCALPHA), - destFactor (GS_BLEND_INVSRCALPHA), + srcFactorC (GS_BLEND_SRCALPHA), + destFactorC (GS_BLEND_INVSRCALPHA), + srcFactorA (GS_BLEND_ONE), + destFactorA (GS_BLEND_ONE), redEnabled (true), greenEnabled (true), blueEnabled (true), diff --git a/libobs-opengl/gl-subsystem.c b/libobs-opengl/gl-subsystem.c index 9eb82754a..021fe1879 100644 --- a/libobs-opengl/gl-subsystem.c +++ b/libobs-opengl/gl-subsystem.c @@ -1115,6 +1115,22 @@ void device_blend_function(gs_device_t *device, enum gs_blend_type src, UNUSED_PARAMETER(device); } +void device_blend_function_separate(gs_device_t *device, + enum gs_blend_type src_c, enum gs_blend_type dest_c, + enum gs_blend_type src_a, enum gs_blend_type dest_a) +{ + GLenum gl_src_c = convert_gs_blend_type(src_c); + GLenum gl_dst_c = convert_gs_blend_type(dest_c); + GLenum gl_src_a = convert_gs_blend_type(src_a); + GLenum gl_dst_a = convert_gs_blend_type(dest_a); + + glBlendFuncSeparate(gl_src_c, gl_dst_c, gl_src_a, gl_dst_a); + if (!gl_success("glBlendFuncSeparate")) + blog(LOG_ERROR, "device_blend_function_separate (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/graphics/device-exports.h b/libobs/graphics/device-exports.h index 849271f78..f044b9bb7 100644 --- a/libobs/graphics/device-exports.h +++ b/libobs/graphics/device-exports.h @@ -121,6 +121,9 @@ EXPORT void device_enable_color(gs_device_t *device, bool red, bool green, bool blue, bool alpha); EXPORT void device_blend_function(gs_device_t *device, enum gs_blend_type src, enum gs_blend_type dest); +EXPORT void device_blend_function_separate(gs_device_t *device, + 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 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, enum gs_depth_test test); diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index 2e5187c92..cdf9cfb58 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -95,6 +95,7 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, GRAPHICS_IMPORT(device_enable_stencil_write); GRAPHICS_IMPORT(device_enable_color); GRAPHICS_IMPORT(device_blend_function); + GRAPHICS_IMPORT(device_blend_function_separate); 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 43155795c..e41bf4d0d 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -125,6 +125,9 @@ struct gs_exports { bool blue, bool alpha); void (*device_blend_function)(gs_device_t *device, enum gs_blend_type src, enum gs_blend_type dest); + void (*device_blend_function_separate)(gs_device_t *device, + enum gs_blend_type src_c, enum gs_blend_type dest_c, + enum gs_blend_type src_a, enum gs_blend_type dest_a); void (*device_depth_function)(gs_device_t *device, enum gs_depth_test test); void (*device_stencil_function)(gs_device_t *device, @@ -258,8 +261,10 @@ struct gs_exports { struct blend_state { bool enabled; - enum gs_blend_type src; - enum gs_blend_type dest; + enum gs_blend_type src_c; + enum gs_blend_type dest_c; + enum gs_blend_type src_a; + enum gs_blend_type dest_a; }; struct graphics_subsystem { diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index 54092a7d1..9808d46f4 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -127,11 +127,14 @@ static bool graphics_init(struct graphics_subsystem *graphics) if (pthread_mutex_init(&graphics->effect_mutex, NULL) != 0) return false; - graphics->exports.device_blend_function(graphics->device, - GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA); + graphics->exports.device_blend_function_separate(graphics->device, + GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, + GS_BLEND_ONE, GS_BLEND_ONE); graphics->cur_blend_state.enabled = true; - graphics->cur_blend_state.src = GS_BLEND_SRCALPHA; - graphics->cur_blend_state.dest = GS_BLEND_INVSRCALPHA; + 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_ONE; graphics->exports.device_leave_context(graphics->device); @@ -1023,7 +1026,8 @@ void gs_blend_state_pop(void) return; gs_enable_blending(state->enabled); - gs_blend_function(state->src, state->dest); + gs_blend_function_separate(state->src_c, state->dest_c, + state->src_a, state->dest_a); da_pop_back(graphics->blend_state_stack); } @@ -1036,9 +1040,13 @@ void gs_reset_blend_state(void) if (!graphics->cur_blend_state.enabled) gs_enable_blending(true); - if (graphics->cur_blend_state.src != GS_BLEND_SRCALPHA || - graphics->cur_blend_state.dest != GS_BLEND_INVSRCALPHA) - gs_blend_function(GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA); + 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_ONE) + gs_blend_function_separate( + GS_BLEND_SRCALPHA, GS_BLEND_INVSRCALPHA, + GS_BLEND_ONE, GS_BLEND_ONE); } /* ------------------------------------------------------------------------- */ @@ -1518,11 +1526,28 @@ void gs_blend_function(enum gs_blend_type src, enum gs_blend_type dest) graphics_t *graphics = thread_graphics; if (!graphics) return; - graphics->cur_blend_state.src = src; - graphics->cur_blend_state.dest = dest; + graphics->cur_blend_state.src_c = src; + graphics->cur_blend_state.dest_c = dest; + graphics->cur_blend_state.src_a = src; + graphics->cur_blend_state.dest_a = dest; graphics->exports.device_blend_function(graphics->device, src, dest); } +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) +{ + graphics_t *graphics = thread_graphics; + if (!graphics) return; + + graphics->cur_blend_state.src_c = src_c; + graphics->cur_blend_state.dest_c = dest_c; + graphics->cur_blend_state.src_a = src_a; + graphics->cur_blend_state.dest_a = dest_a; + graphics->exports.device_blend_function_separate(graphics->device, + src_c, dest_c, src_a, dest_a); +} + 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 d4b560c7b..4c5188cd5 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -633,6 +633,9 @@ EXPORT void gs_enable_stencil_write(bool enable); EXPORT void gs_enable_color(bool red, bool green, bool blue, bool alpha); EXPORT void gs_blend_function(enum gs_blend_type src, enum gs_blend_type dest); +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_depth_function(enum gs_depth_test test); EXPORT void gs_stencil_function(enum gs_stencil_side side,