From 7bc498d325247ba38b7437b25f15c08e6655617b Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sun, 27 Mar 2022 09:12:12 -0400 Subject: [PATCH] direct3d: Implement missing blend operations. This is only for Direct3D 9; Direct3D 11 already had this implemented. Fixes #5375. --- include/SDL_blendmode.h | 10 +++---- src/render/direct3d/SDL_render_d3d.c | 44 ++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/include/SDL_blendmode.h b/include/SDL_blendmode.h index b6d140dbb..08c9f9dd6 100644 --- a/include/SDL_blendmode.h +++ b/include/SDL_blendmode.h @@ -67,9 +67,8 @@ typedef enum SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */ SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */ SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */ - SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D11 */ - SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D11 */ - + SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */ + SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */ } SDL_BlendOperation; /** @@ -87,7 +86,6 @@ typedef enum SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */ SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */ SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */ - } SDL_BlendFactor; /** @@ -135,10 +133,10 @@ typedef enum * SDL 2.0.6. All renderers support the four blend modes listed in the * SDL_BlendMode enumeration. * - * - **direct3d**: Supports `SDL_BLENDOPERATION_ADD` with all factors. - * - **direct3d11**: Supports all operations with all factors. However, some + * - **direct3d**: Supports all operations with all factors. However, some * factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and * `SDL_BLENDOPERATION_MAXIMUM`. + * - **direct3d11**: Same as Direct3D 9. * - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all * factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL * 2.0.6. diff --git a/src/render/direct3d/SDL_render_d3d.c b/src/render/direct3d/SDL_render_d3d.c index b267fb23e..477f4e975 100644 --- a/src/render/direct3d/SDL_render_d3d.c +++ b/src/render/direct3d/SDL_render_d3d.c @@ -347,7 +347,8 @@ D3D_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event) } } -static D3DBLEND GetBlendFunc(SDL_BlendFactor factor) +static D3DBLEND +GetBlendFunc(SDL_BlendFactor factor) { switch (factor) { case SDL_BLENDFACTOR_ZERO: @@ -370,9 +371,28 @@ static D3DBLEND GetBlendFunc(SDL_BlendFactor factor) return D3DBLEND_DESTALPHA; case SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA: return D3DBLEND_INVDESTALPHA; - default: - return (D3DBLEND)0; + default: break; } + return (D3DBLEND) 0; +} + +static D3DBLENDOP +GetBlendEquation(SDL_BlendOperation operation) +{ + switch (operation) { + case SDL_BLENDOPERATION_ADD: + return D3DBLENDOP_ADD; + case SDL_BLENDOPERATION_SUBTRACT: + return D3DBLENDOP_SUBTRACT; + case SDL_BLENDOPERATION_REV_SUBTRACT: + return D3DBLENDOP_REVSUBTRACT; + case SDL_BLENDOPERATION_MINIMUM: + return D3DBLENDOP_MIN; + case SDL_BLENDOPERATION_MAXIMUM: + return D3DBLENDOP_MAX; + default: break; + } + return (D3DBLENDOP) 0; } static SDL_bool @@ -387,14 +407,16 @@ D3D_SupportsBlendMode(SDL_Renderer * renderer, SDL_BlendMode blendMode) SDL_BlendOperation alphaOperation = SDL_GetBlendModeAlphaOperation(blendMode); if (!GetBlendFunc(srcColorFactor) || !GetBlendFunc(srcAlphaFactor) || - !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor)) { + !GetBlendEquation(colorOperation) || + !GetBlendFunc(dstColorFactor) || !GetBlendFunc(dstAlphaFactor) || + !GetBlendEquation(alphaOperation)) { return SDL_FALSE; } - if ((srcColorFactor != srcAlphaFactor || dstColorFactor != dstAlphaFactor) && !data->enableSeparateAlphaBlend) { - return SDL_FALSE; - } - if (colorOperation != SDL_BLENDOPERATION_ADD || alphaOperation != SDL_BLENDOPERATION_ADD) { - return SDL_FALSE; + + if (!data->enableSeparateAlphaBlend) { + if ((srcColorFactor != srcAlphaFactor) || (dstColorFactor != dstAlphaFactor) || (colorOperation != alphaOperation)) { + return SDL_FALSE; + } } return SDL_TRUE; } @@ -1040,11 +1062,15 @@ SetDrawState(D3D_RenderData *data, const SDL_RenderCommand *cmd) GetBlendFunc(SDL_GetBlendModeSrcColorFactor(blend))); IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLEND, GetBlendFunc(SDL_GetBlendModeDstColorFactor(blend))); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOP, + GetBlendEquation(SDL_GetBlendModeColorOperation(blend))); if (data->enableSeparateAlphaBlend) { IDirect3DDevice9_SetRenderState(data->device, D3DRS_SRCBLENDALPHA, GetBlendFunc(SDL_GetBlendModeSrcAlphaFactor(blend))); IDirect3DDevice9_SetRenderState(data->device, D3DRS_DESTBLENDALPHA, GetBlendFunc(SDL_GetBlendModeDstAlphaFactor(blend))); + IDirect3DDevice9_SetRenderState(data->device, D3DRS_BLENDOPALPHA, + GetBlendEquation(SDL_GetBlendModeAlphaOperation(blend))); } }