浏览代码

libobs: Expose blending operation types

jw0z96 4 年之前
父节点
当前提交
33a6d2a5fd

+ 18 - 10
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

+ 13 - 2
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)

+ 20 - 0
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),

+ 11 - 0
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);

+ 18 - 0
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) {

+ 2 - 0
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,

+ 1 - 0
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);

+ 3 - 0
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 {

+ 20 - 1
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;

+ 10 - 0
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,