/* * Pixel and vertex shaders implementation using ARB_vertex_program * and ARB_fragment_program GL extensions. * * Copyright 2002-2003 Jason Edmeades * Copyright 2002-2003 Raphael Junqueira * Copyright 2005 Oliver Stieber * Copyright 2006 Ivan Gyurdiev * Copyright 2006 Jason Green * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include "config.h" #include #include #include "wined3d_private.h" WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader); #define GLINFO_LOCATION (*gl_info) /******************************************************** * ARB_[vertex/fragment]_program helper functions follow ********************************************************/ /** * Loads floating point constants into the currently set ARB_vertex/fragment_program. * When @constants_set == NULL, it will load all the constants. * * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders) * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders) */ void shader_arb_load_constantsF( WineD3D_GL_Info *gl_info, GLuint target_type, unsigned max_constants, float* constants, BOOL* constants_set) { int i; for (i=0; iwineD3DDevice->wineD3D)->gl_info; if (useVertexShader) { IWineD3DVertexShaderImpl* vshader = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader; IWineD3DVertexDeclarationImpl* vertexDeclaration = (IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration; if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) { /* Load DirectX 8 float constants for vertex shader */ shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB, WINED3D_VSHADER_MAX_CONSTANTS, vertexDeclaration->constants, NULL); } /* Load DirectX 9 float constants for vertex shader */ shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB, WINED3D_VSHADER_MAX_CONSTANTS, stateBlock->vertexShaderConstantF, stateBlock->set.vertexShaderConstantsF); } if (usePixelShader) { /* Load DirectX 9 float constants for pixel shader */ shader_arb_load_constantsF(gl_info, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS, stateBlock->pixelShaderConstantF, stateBlock->set.pixelShaderConstantsF); } } /* Generate the variable & register declarations for the ARB_vertex_program output target */ void shader_generate_arb_declarations( IWineD3DBaseShader *iface, shader_reg_maps* reg_maps, SHADER_BUFFER* buffer) { IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface; DWORD i; for(i = 0; i < This->baseShader.limits.temporary; i++) { if (reg_maps->temporary[i]) shader_addline(buffer, "TEMP R%lu;\n", i); } for (i = 0; i < This->baseShader.limits.address; i++) { if (reg_maps->address[i]) shader_addline(buffer, "ADDRESS A%ld;\n", i); } for(i = 0; i < This->baseShader.limits.texcoord; i++) { if (reg_maps->texcoord[i]) shader_addline(buffer,"TEMP T%lu;\n", i); } /* Texture coordinate registers must be pre-loaded */ for (i = 0; i < This->baseShader.limits.texcoord; i++) { if (reg_maps->texcoord[i]) shader_addline(buffer, "MOV T%lu, fragment.texcoord[%lu];\n", i, i); } /* Need to PARAM the environment parameters (constants) so we can use relative addressing */ shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n", This->baseShader.limits.constant_float, This->baseShader.limits.constant_float - 1); } /** Process the D3DSIO_DEF opcode into an ARB string - creates a local vec4 * float constant, and stores it's usage on the regmaps. */ void shader_hw_def(SHADER_OPCODE_ARG* arg) { DWORD reg = arg->dst & D3DSP_REGNUM_MASK; shader_addline(arg->buffer, "PARAM C%lu = { %f, %f, %f, %f };\n", reg, *((const float *)(arg->src + 0)), *((const float *)(arg->src + 1)), *((const float *)(arg->src + 2)), *((const float *)(arg->src + 3)) ); arg->reg_maps->constantsF[reg] = 1; } /* TODO: Add more ARB_[vertex/fragment]_program specific code here */