1
0
Эх сурвалжийг харах

Add gs_blend_function_separate

This allows the ability to separate the blend states of color and alpha.

The default blend state has also changed so that alpha is always added
together to ensure that the destination image always gets an alpha value
that is actually usable after the operation (for render targets).

Old default state:
  color source: GS_BLEND_SRCALPHA, color dest: GS_BLEND_INVSRCALPHA
  alpha source: GS_BLEND_SRCALPHA, alpha dest: GS_BLEND_INVSRCALPHA

New default state:
  color source: GS_BLEND_SRCALPHA, color dest: GS_BLEND_INVSRCALPHA
  alpha source: GS_BLEND_ONE,      alpha dest: GS_BLEND_ONE
jp9000 10 жил өмнө
parent
commit
be52fa26f9

+ 29 - 8
libobs-d3d11/d3d11-subsystem.cpp

@@ -302,13 +302,13 @@ ID3D11BlendState *gs_device::AddBlendState()
 		bd.RenderTarget[i].BlendOp        = D3D11_BLEND_OP_ADD;
 		bd.RenderTarget[i].BlendOp        = D3D11_BLEND_OP_ADD;
 		bd.RenderTarget[i].BlendOpAlpha   = D3D11_BLEND_OP_ADD;
 		bd.RenderTarget[i].BlendOpAlpha   = D3D11_BLEND_OP_ADD;
 		bd.RenderTarget[i].SrcBlend =
 		bd.RenderTarget[i].SrcBlend =
-			ConvertGSBlendType(blendState.srcFactor);
+			ConvertGSBlendType(blendState.srcFactorC);
 		bd.RenderTarget[i].DestBlend =
 		bd.RenderTarget[i].DestBlend =
-			ConvertGSBlendType(blendState.destFactor);
+			ConvertGSBlendType(blendState.destFactorC);
 		bd.RenderTarget[i].SrcBlendAlpha =
 		bd.RenderTarget[i].SrcBlendAlpha =
-			bd.RenderTarget[i].SrcBlend;
+			ConvertGSBlendType(blendState.srcFactorA);
 		bd.RenderTarget[i].DestBlendAlpha =
 		bd.RenderTarget[i].DestBlendAlpha =
-			bd.RenderTarget[i].DestBlend;
+			ConvertGSBlendType(blendState.destFactorA);
 		bd.RenderTarget[i].RenderTargetWriteMask =
 		bd.RenderTarget[i].RenderTargetWriteMask =
 			D3D11_COLOR_WRITE_ENABLE_ALL;
 			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,
 void device_blend_function(gs_device_t *device, enum gs_blend_type src,
 		enum gs_blend_type dest)
 		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;
 		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;
 	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)
 void device_depth_function(gs_device_t *device, enum gs_depth_test test)
 {
 {
 	if (device->zstencilState.depthFunc == test)
 	if (device->zstencilState.depthFunc == test)

+ 8 - 4
libobs-d3d11/d3d11-subsystem.hpp

@@ -495,8 +495,10 @@ struct gs_swap_chain {
 
 
 struct BlendState {
 struct BlendState {
 	bool          blendEnabled;
 	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          redEnabled;
 	bool          greenEnabled;
 	bool          greenEnabled;
@@ -505,8 +507,10 @@ struct BlendState {
 
 
 	inline BlendState()
 	inline BlendState()
 		: blendEnabled (true),
 		: 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),
 		  redEnabled   (true),
 		  greenEnabled (true),
 		  greenEnabled (true),
 		  blueEnabled  (true),
 		  blueEnabled  (true),

+ 16 - 0
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);
 	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)
 void device_depth_function(gs_device_t *device, enum gs_depth_test test)
 {
 {
 	GLenum gl_test = convert_gs_depth_test(test);
 	GLenum gl_test = convert_gs_depth_test(test);

+ 3 - 0
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);
 		bool blue, bool alpha);
 EXPORT void device_blend_function(gs_device_t *device, enum gs_blend_type src,
 EXPORT void device_blend_function(gs_device_t *device, enum gs_blend_type src,
 		enum gs_blend_type dest);
 		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_depth_function(gs_device_t *device, enum gs_depth_test test);
 EXPORT void device_stencil_function(gs_device_t *device,
 EXPORT void device_stencil_function(gs_device_t *device,
 		enum gs_stencil_side side, enum gs_depth_test test);
 		enum gs_stencil_side side, enum gs_depth_test test);

+ 1 - 0
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_stencil_write);
 	GRAPHICS_IMPORT(device_enable_color);
 	GRAPHICS_IMPORT(device_enable_color);
 	GRAPHICS_IMPORT(device_blend_function);
 	GRAPHICS_IMPORT(device_blend_function);
+	GRAPHICS_IMPORT(device_blend_function_separate);
 	GRAPHICS_IMPORT(device_depth_function);
 	GRAPHICS_IMPORT(device_depth_function);
 	GRAPHICS_IMPORT(device_stencil_function);
 	GRAPHICS_IMPORT(device_stencil_function);
 	GRAPHICS_IMPORT(device_stencil_op);
 	GRAPHICS_IMPORT(device_stencil_op);

+ 7 - 2
libobs/graphics/graphics-internal.h

@@ -125,6 +125,9 @@ struct gs_exports {
 			bool blue, bool alpha);
 			bool blue, bool alpha);
 	void (*device_blend_function)(gs_device_t *device,
 	void (*device_blend_function)(gs_device_t *device,
 			enum gs_blend_type src, enum gs_blend_type dest);
 			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,
 	void (*device_depth_function)(gs_device_t *device,
 			enum gs_depth_test test);
 			enum gs_depth_test test);
 	void (*device_stencil_function)(gs_device_t *device,
 	void (*device_stencil_function)(gs_device_t *device,
@@ -258,8 +261,10 @@ struct gs_exports {
 
 
 struct blend_state {
 struct blend_state {
 	bool               enabled;
 	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 {
 struct graphics_subsystem {

+ 35 - 10
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)
 	if (pthread_mutex_init(&graphics->effect_mutex, NULL) != 0)
 		return false;
 		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.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);
 	graphics->exports.device_leave_context(graphics->device);
 
 
@@ -1023,7 +1026,8 @@ void gs_blend_state_pop(void)
 		return;
 		return;
 
 
 	gs_enable_blending(state->enabled);
 	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);
 	da_pop_back(graphics->blend_state_stack);
 }
 }
@@ -1036,9 +1040,13 @@ void gs_reset_blend_state(void)
 	if (!graphics->cur_blend_state.enabled)
 	if (!graphics->cur_blend_state.enabled)
 		gs_enable_blending(true);
 		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;
 	graphics_t *graphics = thread_graphics;
 	if (!graphics) return;
 	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);
 	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)
 void gs_depth_function(enum gs_depth_test test)
 {
 {
 	graphics_t *graphics = thread_graphics;
 	graphics_t *graphics = thread_graphics;

+ 3 - 0
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_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(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_depth_function(enum gs_depth_test test);
 
 
 EXPORT void gs_stencil_function(enum gs_stencil_side side,
 EXPORT void gs_stencil_function(enum gs_stencil_side side,