[PATCH] Add separate alpha blend support.

Roderick Colenbrander thunderbird2k at gmx.net
Sat Feb 16 09:42:11 CST 2008


---
 dlls/wined3d/directx.c    |    6 +-
 dlls/wined3d/state.c      |  134 +++++++++++++++++++++++++++++++++++++-------
 include/wine/wined3d_gl.h |   16 +++++
 3 files changed, 132 insertions(+), 24 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 3c9ea69..5218cf5 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -85,6 +85,8 @@ static const struct {
     /* EXT */
     {"GL_EXT_blend_color",                  EXT_BLEND_COLOR,                0                           },
     {"GL_EXT_blend_minmax",                 EXT_BLEND_MINMAX,               0                           },
+    {"GL_EXT_blend_equation_separate",      EXT_BLEND_EQUATION_SEPARATE,    0                           },
+    {"GL_EXT_blend_func_separate",          EXT_BLEND_FUNC_SEPARATE,        0                           },
     {"GL_EXT_fog_coord",                    EXT_FOG_COORD,                  0                           },
     {"GL_EXT_framebuffer_blit",             EXT_FRAMEBUFFER_BLIT,           0                           },
     {"GL_EXT_framebuffer_object",           EXT_FRAMEBUFFER_OBJECT,         0                           },
@@ -2195,12 +2197,12 @@ static HRESULT WINAPI IWineD3DImpl_GetDeviceCaps(IWineD3D *iface, UINT Adapter,
                                       WINED3DPMISCCAPS_CLIPTLVERTS           |
                                       WINED3DPMISCCAPS_CLIPPLANESCALEDPOINTS |
                                       WINED3DPMISCCAPS_MASKZ                 |
-                                      WINED3DPMISCCAPS_BLENDOP;
+                                      WINED3DPMISCCAPS_BLENDOP               |
+                                      WINED3DPMISCCAPS_SEPARATEALPHABLEND;
                                     /* TODO:
                                         WINED3DPMISCCAPS_NULLREFERENCE
                                         WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
                                         WINED3DPMISCCAPS_FOGANDSPECULARALPHA
-                                        WINED3DPMISCCAPS_SEPARATEALPHABLEND
                                         WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
                                         WINED3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
                                         WINED3DPMISCCAPS_FOGVERTEXCLAMPED */
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index bcb1559..36d7d85 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -233,12 +233,21 @@ static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD
 
 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
     int srcBlend = GL_ZERO;
+    int srcBlendAlpha = GL_ZERO;
     int dstBlend = GL_ZERO;
+    int dstBlendAlpha = GL_ZERO;
     const StaticPixelFormatDesc *rtFormat;
     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
 
+    /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
+    if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE] && !GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
+        WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
+        return;
+    }
+
     /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
     if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]      ||
+        stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE] ||
         stateblock->renderState[WINED3DRS_EDGEANTIALIAS]         ||
         stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
         glEnable(GL_BLEND);
@@ -298,6 +307,40 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
             FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
     }
 
+    switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
+        case WINED3DBLEND_ZERO               : dstBlendAlpha = GL_ZERO;  break;
+        case WINED3DBLEND_ONE                : dstBlendAlpha = GL_ONE;  break;
+        case WINED3DBLEND_SRCCOLOR           : dstBlendAlpha = GL_SRC_COLOR;  break;
+        case WINED3DBLEND_INVSRCCOLOR        : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR;  break;
+        case WINED3DBLEND_SRCALPHA           : dstBlendAlpha = GL_SRC_ALPHA;  break;
+        case WINED3DBLEND_INVSRCALPHA        : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;  break;
+        case WINED3DBLEND_DESTCOLOR          : dstBlendAlpha = GL_DST_COLOR;  break;
+        case WINED3DBLEND_INVDESTCOLOR       : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR;  break;
+        case WINED3DBLEND_DESTALPHA          : dstBlendAlpha = GL_DST_ALPHA;  break;
+        case WINED3DBLEND_INVDESTALPHA       : dstBlendAlpha = GL_DST_ALPHA;  break;
+        case WINED3DBLEND_SRCALPHASAT        :
+            dstBlend = GL_SRC_ALPHA_SATURATE;
+            WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
+            break;
+        /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
+         * values which are still valid up to d3d9. They should not occur as dest blend values
+         */
+        case WINED3DBLEND_BOTHSRCALPHA       :
+            dstBlendAlpha = GL_SRC_ALPHA;
+            srcBlendAlpha = GL_SRC_ALPHA;
+            FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
+            break;
+        case WINED3DBLEND_BOTHINVSRCALPHA    :
+            dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
+            srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
+            FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
+            break;
+        case WINED3DBLEND_BLENDFACTOR        : dstBlendAlpha = GL_CONSTANT_COLOR;   break;
+        case WINED3DBLEND_INVBLENDFACTOR     : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR;  break;
+        default:
+            FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
+    }
+
     switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
         case WINED3DBLEND_ZERO               : srcBlend = GL_ZERO;  break;
         case WINED3DBLEND_ONE                : srcBlend = GL_ONE;  break;
@@ -332,6 +375,31 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
             FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
     }
 
+    switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
+        case WINED3DBLEND_ZERO               : srcBlendAlpha = GL_ZERO;  break;
+        case WINED3DBLEND_ONE                : srcBlendAlpha = GL_ONE;  break;
+        case WINED3DBLEND_SRCCOLOR           : srcBlendAlpha = GL_SRC_COLOR;  break;
+        case WINED3DBLEND_INVSRCCOLOR        : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR;  break;
+        case WINED3DBLEND_SRCALPHA           : srcBlendAlpha = GL_SRC_ALPHA;  break;
+        case WINED3DBLEND_INVSRCALPHA        : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;  break;
+        case WINED3DBLEND_DESTCOLOR          : srcBlendAlpha = GL_DST_COLOR;  break;
+        case WINED3DBLEND_INVDESTCOLOR       : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR;  break;
+        case WINED3DBLEND_SRCALPHASAT        : srcBlendAlpha = GL_SRC_ALPHA_SATURATE;  break;
+        case WINED3DBLEND_DESTALPHA          : srcBlendAlpha = GL_DST_ALPHA;  break;
+        case WINED3DBLEND_INVDESTALPHA       : srcBlendAlpha = GL_DST_ALPHA;  break;
+        case WINED3DBLEND_BOTHSRCALPHA       :
+            srcBlendAlpha = GL_SRC_ALPHA;
+            dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
+            break;
+        case WINED3DBLEND_BOTHINVSRCALPHA    :
+            srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
+            dstBlendAlpha = GL_SRC_ALPHA;
+            break;
+        case WINED3DBLEND_BLENDFACTOR        : srcBlendAlpha = GL_CONSTANT_COLOR;   break;
+        case WINED3DBLEND_INVBLENDFACTOR     : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR;  break;
+        default:
+            FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
+    }
 
     if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
        stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
@@ -348,9 +416,14 @@ static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
         checkGLcall("glDisable(GL_LINE_SMOOTH)");
     }
 
-    TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
-    glBlendFunc(srcBlend, dstBlend);
-    checkGLcall("glBlendFunc");
+    if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
+        GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
+        checkGLcall("glBlendFuncSeparateEXT");
+    } else {
+        TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
+        glBlendFunc(srcBlend, dstBlend);
+        checkGLcall("glBlendFunc");
+    }
 
     /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
         so it may need updating */
@@ -502,26 +575,49 @@ static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, Wine
 }
 
 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
-    int glParm = GL_FUNC_ADD;
+    int blendEquation = GL_FUNC_ADD;
+    int blendEquationAlpha = GL_FUNC_ADD;
 
     if(!GL_SUPPORT(EXT_BLEND_MINMAX)) {
         WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
         return;
     }
 
+    /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
+    if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
+        WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
+        return;
+    }
+
     switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
-        case WINED3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
-        case WINED3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
-        case WINED3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
-        case WINED3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
-        case WINED3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
+        case WINED3DBLENDOP_ADD              : blendEquation = GL_FUNC_ADD;              break;
+        case WINED3DBLENDOP_SUBTRACT         : blendEquation = GL_FUNC_SUBTRACT;         break;
+        case WINED3DBLENDOP_REVSUBTRACT      : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
+        case WINED3DBLENDOP_MIN              : blendEquation = GL_MIN;                   break;
+        case WINED3DBLENDOP_MAX              : blendEquation = GL_MAX;                   break;
         default:
             FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
     }
 
-    TRACE("glBlendEquation(%x)\n", glParm);
-    GL_EXTCALL(glBlendEquationEXT(glParm));
-    checkGLcall("glBlendEquation");
+    switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
+        case WINED3DBLENDOP_ADD              : blendEquationAlpha = GL_FUNC_ADD;              break;
+        case WINED3DBLENDOP_SUBTRACT         : blendEquationAlpha = GL_FUNC_SUBTRACT;         break;
+        case WINED3DBLENDOP_REVSUBTRACT      : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
+        case WINED3DBLENDOP_MIN              : blendEquationAlpha = GL_MIN;                   break;
+        case WINED3DBLENDOP_MAX              : blendEquationAlpha = GL_MAX;                   break;
+        default:
+            FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
+    }
+
+    if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
+        TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
+        GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
+        checkGLcall("glBlendEquationSeparateEXT");
+    } else {
+        TRACE("glBlendEquation(%x)\n", blendEquation);
+        GL_EXTCALL(glBlendEquationEXT(blendEquation));
+        checkGLcall("glBlendEquation");
+    }
 }
 
 static void
@@ -1606,12 +1702,6 @@ static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock,
         FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
 }
 
-static void state_separateblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
-    TRACE("Stub\n");
-    if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE])
-        FIXME("(WINED3DRS_SEPARATEALPHABLENDENABLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]);
-}
-
 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
     if(stateblock->renderState[WINED3DRS_WRAPU]) {
         FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
@@ -4024,10 +4114,10 @@ const struct StateEntry StateTable[] =
     { /*203, WINED3DRS_WRAP13                       */      STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          },
     { /*204, WINED3DRS_WRAP14                       */      STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          },
     { /*205, WINED3DRS_WRAP15                       */      STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          },
-    { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE     */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_separateblend },
-    { /*207, WINED3DRS_SRCBLENDALPHA                */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_separateblend },
-    { /*208, WINED3DRS_DESTBLENDALPHA               */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_separateblend },
-    { /*209, WINED3DRS_BLENDOPALPHA                 */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_separateblend },
+    { /*206, WINED3DRS_SEPARATEALPHABLENDENABLE     */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_blend },
+    { /*207, WINED3DRS_SRCBLENDALPHA                */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_blend },
+    { /*208, WINED3DRS_DESTBLENDALPHA               */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_blend },
+    { /*209, WINED3DRS_BLENDOPALPHA                 */      STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   state_blendop },
     /* Texture stage states */
     { /*0, 01, WINED3DTSS_COLOROP                   */      STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         },
     { /*0, 02, WINED3DTSS_COLORARG1                 */      STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         },
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index b6913fb..bb46124 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -2237,6 +2237,16 @@ typedef GLvoid* (WINE_GLAPI * PGLFNMAPBUFFERARBPROC) (GLenum target, GLenum acce
 typedef GLboolean (WINE_GLAPI * PGLFNUNMAPBUFFERARBPROC) (GLenum target);
 typedef void (WINE_GLAPI * PGLFNGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
 typedef void (WINE_GLAPI * PGLFNGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);
+/* GL_EXT_blend_equation_separate */
+typedef void (WINE_GLAPI * PGLFNBLENDFUNCSEPARATEEXTPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
+/* GL_EXT_blend_func_separate */
+#ifndef GL_EXT_blend_func_separate
+#define GL_BLEND_DST_RGB_EXT              0x80C8
+#define GL_BLEND_SRC_RGB_EXT              0x80C9
+#define GL_BLEND_DST_ALPHA_EXT            0x80CA
+#define GL_BLEND_SRC_ALPHA_EXT            0x80CB
+#endif
+typedef void (WINE_GLAPI * PGLFNBLENDEQUATIONSEPARATEEXTPROC) (GLenum modeRGB, GLenum modeAlpha);
 /* GL_EXT_fog_coord */
 #ifndef GL_EXT_fog_coord
 #define GL_EXT_fog_coord 1
@@ -3190,6 +3200,8 @@ typedef enum _GL_SupportedExt {
   /* EXT */
   EXT_BLEND_COLOR,
   EXT_BLEND_MINMAX,
+  EXT_BLEND_EQUATION_SEPARATE,
+  EXT_BLEND_FUNC_SEPARATE,
   EXT_FOG_COORD,
   EXT_FRAMEBUFFER_OBJECT,
   EXT_FRAMEBUFFER_BLIT,
@@ -3309,6 +3321,10 @@ typedef enum _GL_SupportedExt {
     USE_GL_FUNC(PGLFNGETBUFFERPARAMETERIVARBPROC,                   glGetBufferParameterivARB,                  ARB_VERTEX_BUFFER_OBJECT,NULL);\
     USE_GL_FUNC(PGLFNGETBUFFERPOINTERVARBPROC,                      glGetBufferPointervARB,                     ARB_VERTEX_BUFFER_OBJECT,NULL);\
     /** EXT Extensions **/ \
+    /* GL_EXT_blend_equation_separate */ \
+    USE_GL_FUNC(PGLFNBLENDFUNCSEPARATEEXTPROC,                      glBlendFuncSeparateEXT,                     EXT_BLEND_FUNC_SEPARATE, NULL);\
+    /* GL_EXT_blend_func_separate */ \
+    USE_GL_FUNC(PGLFNBLENDEQUATIONSEPARATEEXTPROC,                  glBlendEquationSeparateEXT,                 EXT_BLEND_EQUATION_SEPARATE, NULL);\
     /* GL_EXT_fog_coord */ \
     USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC,                            glFogCoordfEXT,                             EXT_FOG_COORD,          NULL );\
     USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC,                           glFogCoordfvEXT,                            EXT_FOG_COORD,          NULL );\
-- 
1.5.3.8


--========GMX6058120317937120656--



More information about the wine-patches mailing list