>From nobody Mon Sep 17 00:00:00 2001 From: Jason Green Date: Fri, 26 May 2006 01:22:53 -0400 To: wine-patches Subject: [PATCH 3/5] Add ability to draw primitives with GLSL shaders. - If wined3d_settings.shader_mode == SHADER_GLSL, then Wine will now attempt to generate a GLSL shader program. - Breaks out constant/uniform loading into a separate function - Fixed up a little bit of whitespace for readability. --- dlls/wined3d/drawprim.c | 249 +++++++++++++++++++++++++++-------------------- 1 files changed, 145 insertions(+), 104 deletions(-) ae930222ec5ac9d6a02ef866779859de49284c79 diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c index 9f5994a..27f0e51 100644 --- a/dlls/wined3d/drawprim.c +++ b/dlls/wined3d/drawprim.c @@ -28,9 +28,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d_draw); WINE_DECLARE_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info -#ifdef SHOW_FRAME_MAKEUP #include -#endif #if 0 /* TODO */ extern IWineD3DVertexShaderImpl* VertexShaders[64]; @@ -1694,10 +1692,67 @@ void drawStridedSoftwareVS(IWineD3DDevic #endif -void inline drawPrimitiveDrawStrided(IWineD3DDevice *iface, BOOL useVertexShaderFunction, BOOL usePixelShaderFunction, int useHW, WineDirect3DVertexStridedData *dataLocations, -UINT numberOfvertices, UINT numberOfIndicies, GLenum glPrimType, const void *idxData, short idxSize, int minIndex, long StartIdx) { +/* Load the given constants into either GLSL or ARB shader programs. + * TODO: Add support for ints & bools, too. */ +void loadConstants(IWineD3DDevice *iface, + GLenum target_type, + float* constants, + WINESHADERCNST* constant_types, + unsigned max_constants, + GLhandleARB programId, + BOOL skip_type_compare) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface; + int i; + char tmp_name[7]; + GLuint tmp_loc; + + if (wined3d_settings.shader_mode == SHADER_GLSL) { + /* TODO: Benchmark and see if it would be beneficial to store the + * locations of the constants to avoid looking up each time */ + for (i=0; istateBlock->shaderPrgId; + /* Now draw the graphics to the screen */ if (FALSE /* disable software vs for now */ && useVertexShaderFunction && !useHW) { FIXME("drawing using software vertex shaders (line %d)\n", __LINE__); @@ -1768,131 +1823,110 @@ #if 0/* TODO: Vertex fixups (diffuse and fixupVertices(This, dataLocations, &transformedDataLocations, 1 + endStride - startStride, startStride); #endif - /* vertex shaders */ - - /* If the only vertex data used by the shader is supported by OpenGL then*/ - if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL - && dataLocations->u.s.diffuse.lpData == NULL && dataLocations->u.s.specular.lpData == NULL) - || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) { - - /* Load the vertex data using named arrays */ - TRACE("(%p) Loading vertex data\n", This); - loadVertexData(iface, dataLocations); + /* vertex shaders */ + if ((!useVertexShaderFunction && dataLocations->u.s.pSize.lpData == NULL + && dataLocations->u.s.diffuse.lpData == NULL + && dataLocations->u.s.specular.lpData == NULL) + || (useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->namedArrays + && !((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays)) { + /* The only vertex data used by the shader is supported by OpenGL */ + + /* Load the vertex data using named arrays */ + TRACE("(%p) Loading vertex data\n", This); + loadVertexData(iface, dataLocations); + + } else if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) { + /* load the array data using ordinal mapping */ + loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap); - } else /* Otherwise */ - if(useVertexShaderFunction && ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) { - - /* load the array data using ordinal mapping */ - loadNumberedArrays(iface, dataLocations, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->arrayUsageMap); - - } else { /* If this happens we must drawStridedSlow later on */ - TRACE("Not loading vertex data\n"); - } + } else { + /* If this happens we must drawStridedSlow later on */ + TRACE("Not loading vertex data\n"); + } - TRACE("Loaded arrays\n"); + TRACE("Loaded arrays\n"); - if (useVertexShaderFunction) { - IWineD3DVertexDeclarationImpl *vertexDeclaration; - int i; + /* We need to use a single shader program if we are using GLSL and either pixel or vertex shaders */ + if (wined3d_settings.shader_mode == SHADER_GLSL && + (useVertexShaderFunction || usePixelShaderFunction)) { + GL_EXTCALL(glUseProgramObjectARB(programId)); + checkGLcall("glUseProgramObjectARB"); + } + + if (useVertexShaderFunction) { + IWineD3DVertexDeclarationImpl *vertexDeclaration; - TRACE("Using vertex shader\n"); + TRACE("Using vertex shader\n"); + if (wined3d_settings.shader_mode == SHADER_ARB) { /* Bind the vertex program */ GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, - ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.prgId)); + ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.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)->baseShader.prgId); - - /* Vertex Shader 8 constants */ - vertexDeclaration = (IWineD3DVertexDeclarationImpl *) + This, ((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->baseShader.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 (vertexDeclaration != NULL && vertexDeclaration->constants != NULL) { + float *constants = vertexDeclaration->constants; + loadConstants(iface, GL_VERTEX_PROGRAM_ARB, constants, NULL, WINED3D_VSHADER_MAX_CONSTANTS, programId, TRUE); + } - /* 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]) { + /* Update the constants */ + loadConstants(iface, GL_VERTEX_PROGRAM_ARB, This->stateBlock->vertexShaderConstantF, + This->stateBlock->vertexShaderConstantT, WINED3D_VSHADER_MAX_CONSTANTS, programId, FALSE); + } - GL_EXTCALL(glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, i, - &This->stateBlock->vertexShaderConstantF[i * 4])); + if (usePixelShaderFunction) { - 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"); - } - } - } + TRACE("Using pixel shader\n"); - if (usePixelShaderFunction) { - int i; - - TRACE("Using pixel shader\n"); - - /* Bind the fragment program */ - GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, - ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.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)->baseShader.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"); - } - } + if (wined3d_settings.shader_mode == SHADER_ARB) { + /* Bind the fragment program */ + GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, + ((IWineD3DPixelShaderImpl *)This->stateBlock->pixelShader)->baseShader.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)->baseShader.prgId); } - /* DirectX colours are in a different format to opengl colours - * so if diffuse or specular are used then we need to use drawStridedSlow - * to correct the colours */ - if (!useVertexShaderFunction && - ((dataLocations->u.s.pSize.lpData != NULL) - || (dataLocations->u.s.diffuse.lpData != NULL) - || (dataLocations->u.s.specular.lpData != NULL))) { - /* TODO: replace drawStridedSlow with veretx fixups */ + /* Update the constants */ + loadConstants(iface, GL_FRAGMENT_PROGRAM_ARB, This->stateBlock->pixelShaderConstantF, + This->stateBlock->pixelShaderConstantT, WINED3D_PSHADER_MAX_CONSTANTS, programId, FALSE); + } - drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, - idxData, idxSize, minIndex, StartIdx); + /* DirectX colours are in a different format to opengl colours + * so if diffuse or specular are used then we need to use drawStridedSlow + * to correct the colours */ + if (!useVertexShaderFunction && + ((dataLocations->u.s.pSize.lpData != NULL) + || (dataLocations->u.s.diffuse.lpData != NULL) + || (dataLocations->u.s.specular.lpData != NULL))) { + /* TODO: replace drawStridedSlow with vertex fixups */ + + drawStridedSlow(iface, dataLocations, numberOfIndicies, glPrimType, + idxData, idxSize, minIndex, StartIdx); } else { /* OpenGL can manage everything in hardware so we can use drawStridedFast */ drawStridedFast(iface, numberOfIndicies, glPrimType, - idxData, idxSize, minIndex, StartIdx); + idxData, idxSize, minIndex, StartIdx); } /* Cleanup vertex program */ - if (useVertexShaderFunction) { - /* disable any attribs */ + if (useVertexShaderFunction && wined3d_settings.shader_mode != SHADER_SW) { + /* disable any attribs (Since we bind "attribN" to index #N for GLSL, this works in GLSL & ARB */ if(((IWineD3DVertexShaderImpl *)This->stateBlock->vertexShader)->declaredArrays) { GLint maxAttribs; int i; @@ -1900,20 +1934,27 @@ #endif glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs); /* MESA does not support it right not */ if (glGetError() != GL_NO_ERROR) - maxAttribs = 16; + maxAttribs = 16; for (i = 0; i < maxAttribs; ++i) { GL_EXTCALL(glDisableVertexAttribArrayARB(i)); checkGLcall("glDisableVertexAttribArrayARB(reg);"); } } - glDisable(GL_VERTEX_PROGRAM_ARB); + if (wined3d_settings.shader_mode == SHADER_ARB) + glDisable(GL_VERTEX_PROGRAM_ARB); } /* Cleanup fragment program */ - if (usePixelShaderFunction) { + if (usePixelShaderFunction && wined3d_settings.shader_mode == SHADER_ARB) { glDisable(GL_FRAGMENT_PROGRAM_ARB); } + + /* Cleanup GLSL program */ + if (wined3d_settings.shader_mode == SHADER_GLSL && + (usePixelShaderFunction || useVertexShaderFunction)) { + GL_EXTCALL(glUseProgramObjectARB(0)); + } } } -- 1.3.3