WINED3D: Use OpenGL fragment programs when available

H. Verbeet hverbeet at gmail.com
Wed Mar 8 17:52:45 CST 2006


Currently pixel shaders get created, but not used. This patch enables
OpenGL fragment programs if pixel shaders are enabled and the harware
supports it. Makes fonts readable in the menu for the BF2 demo. This
patch should be applied after the one that removes the FIXME in
drawPrimitiveDrawStrided.

Changelog:
  - Use OpenGL fragment programs when available
-------------- next part --------------
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 6d0c282..aff1f6c 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -1678,7 +1678,7 @@ void drawStridedSoftwareVS(IWineD3DDevic
 
 #endif
 
-void inline  drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
+void inline  drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, BOOL usePixelShaderFunction, int useHW, Direct3DVertexStridedData *dataLocations,
 UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) {
     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
 
@@ -1775,41 +1775,67 @@ UINT numberOfvertices, UINT numberOfIndi
 
         TRACE("Loaded arrays\n");
 
-        if (useVertexShaderFunction) {
-            int i;
-            GLint errPos;
-            IWineD3DVertexDeclarationImpl *vertexDeclaration;
-
-            TRACE("Using vertex shader\n");
-
-            /* Bind the vertex program */
-            GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
-            checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
-
-            /* and enable gl vertex shaders */
-            glEnable(GL_VERTEX_PROGRAM_ARB);
-            checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
-            TRACE_(d3d_shader)("(%p) bound program %u and enabled vertex program ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
-
-            /* Vertex Shader 8 constants */
-            vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
-            if (vertexDeclaration != NULL) {
-                float *constants = vertexDeclaration->constants;
-                if (constants != NULL) {
-                    for (i = 0; i <=  WINED3D_VSHADER_MAX_CONSTANTS; i++) {
-                        TRACE_(d3d_shader)("Not Loading constants %u = %f %f %f %f\n", i, constants[i * 4], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]);
-                        GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
+        if (useVertexShaderFunction || usePixelShaderFunction) {
+            if (useVertexShaderFunction) {
+                IWineD3DVertexDeclarationImpl *vertexDeclaration;
+                int i;
+
+                TRACE("Using vertex shader\n");
+
+                /* Bind the vertex program */
+                GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId));
+                checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
+
+                /* Enable OpenGL vertex programs */
+                glEnable(GL_VERTEX_PROGRAM_ARB);
+                checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
+                TRACE_(d3d_shader)("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->prgId);
+
+                /* Vertex Shader 8 constants */
+                vertexDeclaration = (IWineD3DVertexDeclarationImpl *)((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->vertexDeclaration;
+                if (vertexDeclaration != NULL) {
+                    float *constants = vertexDeclaration->constants;
+                    if (constants != NULL) {
+                        for (i = 0; i <=  WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
+                            TRACE_(d3d_shader)("Not loading constants %u = %f %f %f %f\n", i, constants[i * 4], constants[i * 4 + 1], constants[i * 4 + 2], constants[i * 4 + 3]);
+                            GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &constants[i * 4]));
+                        }
+                    }
+                }
+
+                /* Update the constants */
+                for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; ++i) {
+                    /* TODO: add support for Integer and Boolean constants */
+                    if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
+                        GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
+                        TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->vertexShaderConstantF[i *4 ], This->stateBlock->vertexShaderConstantF[i * 4 + 1], This->stateBlock->vertexShaderConstantF[i *4 + 2], This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
+                        checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
                     }
                 }
             }
 
-            /* Update the constants */
-            for (i = 0; i < WINED3D_VSHADER_MAX_CONSTANTS; i++) {
-                /* TODO: add support for Integer and Boolean constants */
-                if (WINESHADERCNST_FLOAT == This->stateBlock->vertexShaderConstantT[i]) {
-                    GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, &This->stateBlock->vertexShaderConstantF[i * 4]));
-                    TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->vertexShaderConstantF[i *4 ], This->stateBlock->vertexShaderConstantF[i * 4 + 1], This->stateBlock->vertexShaderConstantF[i *4 + 2], This->stateBlock->vertexShaderConstantF[i * 4 + 3]);
-                    checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
+            if (usePixelShaderFunction) {
+                int i;
+
+                TRACE("Using pixel shader\n");
+
+                /* Bind the fragment program */
+                GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->prgId));
+                checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
+
+                /* Enable OpenGL fragment programs */
+                glEnable(GL_FRAGMENT_PROGRAM_ARB);
+                checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
+                TRACE_(d3d_shader)("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->prgId);
+
+                /* Update the constants */
+                for (i = 0; i < WINED3D_PSHADER_MAX_CONSTANTS; ++i) {
+                    /* TODO: add support for Integer and Boolean constants */
+                    if (WINESHADERCNST_FLOAT == This->stateBlock->pixelShaderConstantT[i]) {
+                        GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, i, &This->stateBlock->pixelShaderConstantF[i * 4]));
+                        TRACE_(d3d_shader)("Loading constants %u = %f %f %f %f\n",i, This->stateBlock->pixelShaderConstantF[i *4 ], This->stateBlock->pixelShaderConstantF[i * 4 + 1], This->stateBlock->pixelShaderConstantF[i *4 + 2], This->stateBlock->pixelShaderConstantF[i * 4 + 3]);
+                        checkGLcall("glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB");
+                    }
                 }
             }
 
@@ -1817,23 +1843,30 @@ UINT numberOfvertices, UINT numberOfIndi
             drawStridedFast(iface, numberOfIndicies, glPrimType,
                         idxData, idxSize, minIndex, StartIdx);
 
-            /* disable any attribs */
-            if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
-                GLint maxAttribs;
-                int i;
-                /* Leave all the attribs disabled */
-                glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
-                /* MESA does not support it right not */
-                if (glGetError() != GL_NO_ERROR)
-                maxAttribs = 16;
-                for (i = 0; i < maxAttribs; i++) {
-                    GL_EXTCALL(glDisableVertexAttribArrayARB(i));
-                    checkGLcall("glDisableVertexAttribArrayARB(reg);");
+            /* Cleanup vertex program */
+            if (useVertexShaderFunction) {
+                /* disable any attribs */
+                if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) {
+                    GLint maxAttribs;
+                    int i;
+                    /* Leave all the attribs disabled */
+                    glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
+                    /* MESA does not support it right not */
+                    if (glGetError() != GL_NO_ERROR)
+                    maxAttribs = 16;
+                    for (i = 0; i < maxAttribs; ++i) {
+                        GL_EXTCALL(glDisableVertexAttribArrayARB(i));
+                        checkGLcall("glDisableVertexAttribArrayARB(reg);");
+                    }
                 }
+
+                glDisable(GL_VERTEX_PROGRAM_ARB);
             }
 
-            /* Done */
-            glDisable(GL_VERTEX_PROGRAM_ARB);
+            /* Cleanup fragment program */
+            if (usePixelShaderFunction) {
+                glDisable(GL_FRAGMENT_PROGRAM_ARB);
+            }
         } else {
 
             /* DirectX colours are in a different format to opengl colours
@@ -2009,6 +2042,7 @@ void drawPrimitive(IWineD3DDevice *iface
     DWORD                         fvf = 0;
     IWineD3DDeviceImpl           *This = (IWineD3DDeviceImpl *)iface;
     BOOL                          useVertexShaderFunction = FALSE;
+    BOOL                          usePixelShaderFunction = FALSE;
     BOOL                          isLightingOn = FALSE;
     Direct3DVertexStridedData     dataLocations;
     int                           useHW = FALSE;
@@ -2021,6 +2055,12 @@ void drawPrimitive(IWineD3DDevice *iface
         useVertexShaderFunction = FALSE;
     }
 
+    if (wined3d_settings.ps_mode != PS_NONE && GL_SUPPORT(ARB_FRAGMENT_PROGRAM)
+            && This->stateBlock->pixelShader
+            && ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->function) {
+        usePixelShaderFunction = TRUE;
+    }
+
     if (This->stateBlock->vertexDecl == NULL) {
         /* Work out what the FVF should look like */
         rc = initializeFVF(iface, &fvf);
@@ -2107,7 +2147,7 @@ void drawPrimitive(IWineD3DDevice *iface
 #endif
         if (numberOfVertices == 0 )
             numberOfVertices = calculatedNumberOfindices;
-        drawPrimitiveDrawStrided(iface, useVertexShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
+        drawPrimitiveDrawStrided(iface, useVertexShaderFunction, usePixelShaderFunction, useHW, &dataLocations, numberOfVertices, calculatedNumberOfindices, glPrimType, idxData, idxSize, minIndex, StartIdx);
     }
 
     /* If vertex shaders or no normals, restore previous lighting state */





More information about the wine-patches mailing list