2 * Pixel and vertex shaders implementation using ARB_vertex_program
3 * and ARB_fragment_program GL extensions.
5 * Copyright 2002-2003 Jason Edmeades
6 * Copyright 2002-2003 Raphael Junqueira
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2006 Ivan Gyurdiev
9 * Copyright 2006 Jason Green
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #include "wined3d_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
35 #define GLINFO_LOCATION (*gl_info)
37 /********************************************************
38 * ARB_[vertex/fragment]_program helper functions follow
39 ********************************************************/
42 * Loads floating point constants into the currently set ARB_vertex/fragment_program.
43 * When @constants_set == NULL, it will load all the constants.
45 * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
46 * or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
48 void shader_arb_load_constantsF(
49 WineD3D_GL_Info *gl_info,
51 unsigned max_constants,
53 BOOL* constants_set) {
57 for (i=0; i<max_constants; ++i) {
58 if (NULL == constants_set || constants_set[i]) {
59 TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
60 constants[i * sizeof(float) + 0], constants[i * sizeof(float) + 1],
61 constants[i * sizeof(float) + 2], constants[i * sizeof(float) + 3]);
63 GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, &constants[i * sizeof(float)]));
64 checkGLcall("glProgramEnvParameter4fvARB");
70 * Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs.
72 * We only support float constants in ARB at the moment, so don't
73 * worry about the Integers or Booleans
75 void shader_arb_load_constants(
76 IWineD3DStateBlock* iface,
78 char useVertexShader) {
80 IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
81 WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
83 if (useVertexShader) {
84 IWineD3DVertexShaderImpl* vshader = (IWineD3DVertexShaderImpl*) stateBlock->vertexShader;
85 IWineD3DVertexDeclarationImpl* vertexDeclaration =
86 (IWineD3DVertexDeclarationImpl*) vshader->vertexDeclaration;
88 if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
89 /* Load DirectX 8 float constants for vertex shader */
90 shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
91 WINED3D_VSHADER_MAX_CONSTANTS,
92 vertexDeclaration->constants, NULL);
95 /* Load DirectX 9 float constants for vertex shader */
96 shader_arb_load_constantsF(gl_info, GL_VERTEX_PROGRAM_ARB,
97 WINED3D_VSHADER_MAX_CONSTANTS,
98 stateBlock->vertexShaderConstantF,
99 stateBlock->set.vertexShaderConstantsF);
102 if (usePixelShader) {
104 /* Load DirectX 9 float constants for pixel shader */
105 shader_arb_load_constantsF(gl_info, GL_FRAGMENT_PROGRAM_ARB, WINED3D_PSHADER_MAX_CONSTANTS,
106 stateBlock->pixelShaderConstantF,
107 stateBlock->set.pixelShaderConstantsF);
111 /* Generate the variable & register declarations for the ARB_vertex_program output target */
112 void shader_generate_arb_declarations(
113 IWineD3DBaseShader *iface,
114 shader_reg_maps* reg_maps,
115 SHADER_BUFFER* buffer) {
117 IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
120 for(i = 0; i < This->baseShader.limits.temporary; i++) {
121 if (reg_maps->temporary[i])
122 shader_addline(buffer, "TEMP R%lu;\n", i);
125 for (i = 0; i < This->baseShader.limits.address; i++) {
126 if (reg_maps->address[i])
127 shader_addline(buffer, "ADDRESS A%ld;\n", i);
130 for(i = 0; i < This->baseShader.limits.texcoord; i++) {
131 if (reg_maps->texcoord[i])
132 shader_addline(buffer,"TEMP T%lu;\n", i);
135 /* Texture coordinate registers must be pre-loaded */
136 for (i = 0; i < This->baseShader.limits.texcoord; i++) {
137 if (reg_maps->texcoord[i])
138 shader_addline(buffer, "MOV T%lu, fragment.texcoord[%lu];\n", i, i);
141 /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
142 shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
143 This->baseShader.limits.constant_float,
144 This->baseShader.limits.constant_float - 1);
147 /** Process the D3DSIO_DEF opcode into an ARB string - creates a local vec4
148 * float constant, and stores it's usage on the regmaps. */
149 void shader_hw_def(SHADER_OPCODE_ARG* arg) {
151 DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
153 shader_addline(arg->buffer,
154 "PARAM C%lu = { %f, %f, %f, %f };\n", reg,
155 *((const float *)(arg->src + 0)),
156 *((const float *)(arg->src + 1)),
157 *((const float *)(arg->src + 2)),
158 *((const float *)(arg->src + 3)) );
160 arg->reg_maps->constantsF[reg] = 1;
164 /* TODO: Add more ARB_[vertex/fragment]_program specific code here */