wined3d: Fix a typo.
[wine] / dlls / wined3d / glsl_shader.c
1 /*
2  * GLSL pixel and vertex shader implementation
3  *
4  * Copyright 2006 Jason Green 
5  * Copyright 2006-2007 Henri Verbeet
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 /*
23  * D3D shader asm has swizzles on source parameters, and write masks for
24  * destination parameters. GLSL uses swizzles for both. The result of this is
25  * that for example "mov dst.xw, src.zyxw" becomes "dst.xw = src.zw" in GLSL.
26  * Ie, to generate a proper GLSL source swizzle, we need to take the D3D write
27  * mask for the destination parameter into account.
28  */
29
30 #include "config.h"
31 #include <stdio.h>
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
35
36 #define GLINFO_LOCATION      (*gl_info)
37
38 typedef struct {
39     char reg_name[50];
40     char mask_str[6];
41 } glsl_dst_param_t;
42
43 typedef struct {
44     char reg_name[50];
45     char param_str[100];
46 } glsl_src_param_t;
47
48 typedef struct {
49     const char *name;
50     DWORD coord_mask;
51 } glsl_sample_function_t;
52
53 /** Prints the GLSL info log which will contain error messages if they exist */
54 void print_glsl_info_log(WineD3D_GL_Info *gl_info, GLhandleARB obj) {
55     
56     int infologLength = 0;
57     char *infoLog;
58
59     GL_EXTCALL(glGetObjectParameterivARB(obj,
60                GL_OBJECT_INFO_LOG_LENGTH_ARB,
61                &infologLength));
62
63     /* A size of 1 is just a null-terminated string, so the log should be bigger than
64      * that if there are errors. */
65     if (infologLength > 1)
66     {
67         infoLog = (char *)HeapAlloc(GetProcessHeap(), 0, infologLength);
68         GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog));
69         FIXME("Error received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog));
70         HeapFree(GetProcessHeap(), 0, infoLog);
71     }
72 }
73
74 /**
75  * Loads (pixel shader) samplers
76  */
77 void shader_glsl_load_psamplers(
78     WineD3D_GL_Info *gl_info,
79     IWineD3DStateBlock* iface) {
80
81     IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
82     GLhandleARB programId = stateBlock->glsl_program->programId;
83     GLhandleARB name_loc;
84     int i;
85     char sampler_name[20];
86
87     for (i=0; i< GL_LIMITS(samplers); ++i) {
88         if (stateBlock->textures[i] != NULL) {
89            snprintf(sampler_name, sizeof(sampler_name), "Psampler%d", i);
90            name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
91            if (name_loc != -1) {
92                TRACE("Loading %s for texture %d\n", sampler_name, i);
93                GL_EXTCALL(glUniform1iARB(name_loc, i));
94                checkGLcall("glUniform1iARB");
95            }
96         }
97     }
98 }
99
100 /** 
101  * Loads floating point constants (aka uniforms) into the currently set GLSL program.
102  * When constant_list == NULL, it will load all the constants.
103  */
104 static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl* This, WineD3D_GL_Info *gl_info,
105         unsigned int max_constants, float* constants, GLhandleARB *constant_locations,
106         struct list *constant_list) {
107     local_constant* lconst;
108     GLhandleARB tmp_loc;
109     int i;
110
111     if (!constant_list) {
112         if (TRACE_ON(d3d_shader)) {
113             for (i = 0; i < max_constants; ++i) {
114                 tmp_loc = constant_locations[i];
115                 if (tmp_loc != -1) {
116                     TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
117                             constants[i * 4 + 0], constants[i * 4 + 1],
118                             constants[i * 4 + 2], constants[i * 4 + 3]);
119                 }
120             }
121         }
122         for (i = 0; i < max_constants; ++i) {
123             tmp_loc = constant_locations[i];
124             if (tmp_loc != -1) {
125                 /* We found this uniform name in the program - go ahead and send the data */
126                 GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, constants + (i * 4)));
127             }
128         }
129         checkGLcall("glUniform4fvARB()");
130     } else {
131         constant_entry *constant;
132         if (TRACE_ON(d3d_shader)) {
133             LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) {
134                 i = constant->idx;
135                 tmp_loc = constant_locations[i];
136                 if (tmp_loc != -1) {
137                     TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
138                             constants[i * 4 + 0], constants[i * 4 + 1],
139                             constants[i * 4 + 2], constants[i * 4 + 3]);
140                 }
141             }
142         }
143         LIST_FOR_EACH_ENTRY(constant, constant_list, constant_entry, entry) {
144             i = constant->idx;
145             tmp_loc = constant_locations[i];
146             if (tmp_loc != -1) {
147                 /* We found this uniform name in the program - go ahead and send the data */
148                 GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, constants + (i * 4)));
149             }
150         }
151         checkGLcall("glUniform4fvARB()");
152     }
153
154     /* Load immediate constants */
155     if (TRACE_ON(d3d_shader)) {
156         LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
157             tmp_loc = constant_locations[lconst->idx];
158             if (tmp_loc != -1) {
159                 GLfloat* values = (GLfloat*)lconst->value;
160                 TRACE("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
161                         values[0], values[1], values[2], values[3]);
162             }
163         }
164     }
165     LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
166         tmp_loc = constant_locations[lconst->idx];
167         if (tmp_loc != -1) {
168             /* We found this uniform name in the program - go ahead and send the data */
169             GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, (GLfloat*)lconst->value));
170         }
171     }
172     checkGLcall("glUniform4fvARB()");
173 }
174
175 /** 
176  * Loads integer constants (aka uniforms) into the currently set GLSL program.
177  * When @constants_set == NULL, it will load all the constants.
178  */
179 void shader_glsl_load_constantsI(
180     IWineD3DBaseShaderImpl* This,
181     WineD3D_GL_Info *gl_info,
182     GLhandleARB programId,
183     unsigned max_constants,
184     int* constants,
185     BOOL* constants_set) {
186     
187     GLhandleARB tmp_loc;
188     int i;
189     char tmp_name[8];
190     char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
191     const char* prefix = is_pshader? "PI":"VI";
192     struct list* ptr;
193
194     for (i=0; i<max_constants; ++i) {
195         if (NULL == constants_set || constants_set[i]) {
196
197             TRACE("Loading constants %i: %i, %i, %i, %i\n",
198                   i, constants[i*4], constants[i*4+1], constants[i*4+2], constants[i*4+3]);
199
200             /* TODO: Benchmark and see if it would be beneficial to store the 
201              * locations of the constants to avoid looking up each time */
202             snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
203             tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
204             if (tmp_loc != -1) {
205                 /* We found this uniform name in the program - go ahead and send the data */
206                 GL_EXTCALL(glUniform4ivARB(tmp_loc, 1, &constants[i*4]));
207                 checkGLcall("glUniform4ivARB");
208             }
209         }
210     }
211
212     /* Load immediate constants */
213     ptr = list_head(&This->baseShader.constantsI);
214     while (ptr) {
215         local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
216         unsigned int idx = lconst->idx;
217         GLint* values = (GLint*) lconst->value;
218
219         TRACE("Loading local constants %i: %i, %i, %i, %i\n", idx,
220             values[0], values[1], values[2], values[3]);
221
222         snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
223         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
224         if (tmp_loc != -1) {
225             /* We found this uniform name in the program - go ahead and send the data */
226             GL_EXTCALL(glUniform4ivARB(tmp_loc, 1, values));
227             checkGLcall("glUniform4ivARB");
228         }
229         ptr = list_next(&This->baseShader.constantsI, ptr);
230     }
231 }
232
233 /** 
234  * Loads boolean constants (aka uniforms) into the currently set GLSL program.
235  * When @constants_set == NULL, it will load all the constants.
236  */
237 void shader_glsl_load_constantsB(
238     IWineD3DBaseShaderImpl* This,
239     WineD3D_GL_Info *gl_info,
240     GLhandleARB programId,
241     unsigned max_constants,
242     BOOL* constants,
243     BOOL* constants_set) {
244     
245     GLhandleARB tmp_loc;
246     int i;
247     char tmp_name[8];
248     char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
249     const char* prefix = is_pshader? "PB":"VB";
250     struct list* ptr;
251
252     for (i=0; i<max_constants; ++i) {
253         if (NULL == constants_set || constants_set[i]) {
254
255             TRACE("Loading constants %i: %i;\n", i, constants[i*4]);
256
257             /* TODO: Benchmark and see if it would be beneficial to store the 
258              * locations of the constants to avoid looking up each time */
259             snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
260             tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
261             if (tmp_loc != -1) {
262                 /* We found this uniform name in the program - go ahead and send the data */
263                 GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, &constants[i*4]));
264                 checkGLcall("glUniform1ivARB");
265             }
266         }
267     }
268
269     /* Load immediate constants */
270     ptr = list_head(&This->baseShader.constantsB);
271     while (ptr) {
272         local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
273         unsigned int idx = lconst->idx;
274         GLint* values = (GLint*) lconst->value;
275
276         TRACE("Loading local constants %i: %i\n", idx, values[0]);
277
278         snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
279         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
280         if (tmp_loc != -1) {
281             /* We found this uniform name in the program - go ahead and send the data */
282             GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values));
283             checkGLcall("glUniform1ivARB");
284         }
285         ptr = list_next(&This->baseShader.constantsB, ptr);
286     }
287 }
288
289
290
291 /**
292  * Loads the app-supplied constants into the currently set GLSL program.
293  */
294 void shader_glsl_load_constants(
295     IWineD3DDevice* device,
296     char usePixelShader,
297     char useVertexShader) {
298    
299     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device;
300     IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
301     WineD3D_GL_Info *gl_info = &((IWineD3DImpl*) deviceImpl->wineD3D)->gl_info;
302
303     GLhandleARB *constant_locations;
304     struct list *constant_list;
305     GLhandleARB programId;
306     
307     if (!stateBlock->glsl_program) {
308         /* No GLSL program set - nothing to do. */
309         return;
310     }
311     programId = stateBlock->glsl_program->programId;
312
313     if (useVertexShader) {
314         IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
315         IWineD3DVertexShaderImpl* vshader_impl = (IWineD3DVertexShaderImpl*) vshader;
316         GLint pos;
317
318         IWineD3DVertexDeclarationImpl* vertexDeclaration =
319             (IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
320
321         constant_locations = stateBlock->glsl_program->vuniformF_locations;
322         constant_list = &stateBlock->set_vconstantsF;
323
324         if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
325             /* Load DirectX 8 float constants/uniforms for vertex shader */
326             shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
327                     vertexDeclaration->constants, constant_locations, NULL);
328         }
329
330         /* Load DirectX 9 float constants/uniforms for vertex shader */
331         shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
332                 stateBlock->vertexShaderConstantF, constant_locations, constant_list);
333
334         /* Load DirectX 9 integer constants/uniforms for vertex shader */
335         shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I,
336                                     stateBlock->vertexShaderConstantI,
337                                     stateBlock->set.vertexShaderConstantsI);
338
339         /* Load DirectX 9 boolean constants/uniforms for vertex shader */
340         shader_glsl_load_constantsB(vshader, gl_info, programId, MAX_CONST_B,
341                                     stateBlock->vertexShaderConstantB,
342                                     stateBlock->set.vertexShaderConstantsB);
343
344         /* Upload the position fixup params */
345         pos = GL_EXTCALL(glGetUniformLocationARB(programId, "posFixup"));
346         checkGLcall("glGetUniformLocationARB");
347         GL_EXTCALL(glUniform4fvARB(pos, 1, &deviceImpl->posFixup[0]));
348         checkGLcall("glUniform4fvARB");
349     }
350
351     if (usePixelShader) {
352
353         IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
354
355         constant_locations = stateBlock->glsl_program->puniformF_locations;
356         constant_list = &stateBlock->set_pconstantsF;
357
358         /* Load pixel shader samplers */
359         shader_glsl_load_psamplers(gl_info, (IWineD3DStateBlock*) stateBlock);
360
361         /* Load DirectX 9 float constants/uniforms for pixel shader */
362         shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
363                 stateBlock->pixelShaderConstantF, constant_locations, constant_list);
364
365         /* Load DirectX 9 integer constants/uniforms for pixel shader */
366         shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
367                                     stateBlock->pixelShaderConstantI, 
368                                     stateBlock->set.pixelShaderConstantsI);
369         
370         /* Load DirectX 9 boolean constants/uniforms for pixel shader */
371         shader_glsl_load_constantsB(pshader, gl_info, programId, MAX_CONST_B,
372                                     stateBlock->pixelShaderConstantB, 
373                                     stateBlock->set.pixelShaderConstantsB);
374     }
375 }
376
377 /** Generate the variable & register declarations for the GLSL output target */
378 void shader_generate_glsl_declarations(
379     IWineD3DBaseShader *iface,
380     shader_reg_maps* reg_maps,
381     SHADER_BUFFER* buffer,
382     WineD3D_GL_Info* gl_info) {
383
384     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
385     int i;
386
387     /* There are some minor differences between pixel and vertex shaders */
388     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
389     char prefix = pshader ? 'P' : 'V';
390
391     /* Prototype the subroutines */
392     for (i = 0; i < This->baseShader.limits.label; i++) {
393         if (reg_maps->labels[i])
394             shader_addline(buffer, "void subroutine%lu();\n", i);
395     }
396
397     /* Declare the constants (aka uniforms) */
398     if (This->baseShader.limits.constant_float > 0) {
399         unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
400                 (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
401         shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF);
402     }
403
404     if (This->baseShader.limits.constant_int > 0)
405         shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
406
407     if (This->baseShader.limits.constant_bool > 0)
408         shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool);
409
410     if(!pshader)
411         shader_addline(buffer, "uniform vec4 posFixup;\n");
412
413     /* Declare texture samplers */ 
414     for (i = 0; i < This->baseShader.limits.sampler; i++) {
415         if (reg_maps->samplers[i]) {
416
417             DWORD stype = reg_maps->samplers[i] & WINED3DSP_TEXTURETYPE_MASK;
418             switch (stype) {
419
420                 case WINED3DSTT_1D:
421                     shader_addline(buffer, "uniform sampler1D %csampler%lu;\n", prefix, i);
422                     break;
423                 case WINED3DSTT_2D:
424                     shader_addline(buffer, "uniform sampler2D %csampler%lu;\n", prefix, i);
425                     break;
426                 case WINED3DSTT_CUBE:
427                     shader_addline(buffer, "uniform samplerCube %csampler%lu;\n", prefix, i);
428                     break;
429                 case WINED3DSTT_VOLUME:
430                     shader_addline(buffer, "uniform sampler3D %csampler%lu;\n", prefix, i);
431                     break;
432                 default:
433                     shader_addline(buffer, "uniform unsupported_sampler %csampler%lu;\n", prefix, i);
434                     FIXME("Unrecognized sampler type: %#x\n", stype);
435                     break;
436             }
437         }
438     }
439     
440     /* Declare address variables */
441     for (i = 0; i < This->baseShader.limits.address; i++) {
442         if (reg_maps->address[i])
443             shader_addline(buffer, "ivec4 A%d;\n", i);
444     }
445
446     /* Declare texture coordinate temporaries and initialize them */
447     for (i = 0; i < This->baseShader.limits.texcoord; i++) {
448         if (reg_maps->texcoord[i]) 
449             shader_addline(buffer, "vec4 T%lu = gl_TexCoord[%lu];\n", i, i);
450     }
451
452     /* Declare input register temporaries */
453     for (i=0; i < This->baseShader.limits.packed_input; i++) {
454         if (reg_maps->packed_input[i])
455             shader_addline(buffer, "vec4 IN%lu;\n", i);
456     }
457
458     /* Declare output register temporaries */
459     for (i = 0; i < This->baseShader.limits.packed_output; i++) {
460         if (reg_maps->packed_output[i])
461             shader_addline(buffer, "vec4 OUT%lu;\n", i);
462     }
463
464     /* Declare temporary variables */
465     for(i = 0; i < This->baseShader.limits.temporary; i++) {
466         if (reg_maps->temporary[i])
467             shader_addline(buffer, "vec4 R%lu;\n", i);
468     }
469
470     /* Declare attributes */
471     for (i = 0; i < This->baseShader.limits.attributes; i++) {
472         if (reg_maps->attributes[i])
473             shader_addline(buffer, "attribute vec4 attrib%i;\n", i);
474     }
475
476     /* Declare loop register aL */
477     if (reg_maps->loop) {
478         shader_addline(buffer, "int aL;\n");
479         shader_addline(buffer, "int tmpInt;\n");
480     }
481     
482     /* Temporary variables for matrix operations */
483     shader_addline(buffer, "vec4 tmp0;\n");
484     shader_addline(buffer, "vec4 tmp1;\n");
485
486     /* Start the main program */
487     shader_addline(buffer, "void main() {\n");
488 }
489
490 /*****************************************************************************
491  * Functions to generate GLSL strings from DirectX Shader bytecode begin here.
492  *
493  * For more information, see http://wiki.winehq.org/DirectX-Shaders
494  ****************************************************************************/
495
496 /* Prototypes */
497 static void shader_glsl_add_src_param(SHADER_OPCODE_ARG* arg, const DWORD param,
498         const DWORD addr_token, DWORD mask, glsl_src_param_t *src_param);
499
500 /** Used for opcode modifiers - They multiply the result by the specified amount */
501 static const char * const shift_glsl_tab[] = {
502     "",           /*  0 (none) */ 
503     "2.0 * ",     /*  1 (x2)   */ 
504     "4.0 * ",     /*  2 (x4)   */ 
505     "8.0 * ",     /*  3 (x8)   */ 
506     "16.0 * ",    /*  4 (x16)  */ 
507     "32.0 * ",    /*  5 (x32)  */ 
508     "",           /*  6 (x64)  */ 
509     "",           /*  7 (x128) */ 
510     "",           /*  8 (d256) */ 
511     "",           /*  9 (d128) */ 
512     "",           /* 10 (d64)  */ 
513     "",           /* 11 (d32)  */ 
514     "0.0625 * ",  /* 12 (d16)  */ 
515     "0.125 * ",   /* 13 (d8)   */ 
516     "0.25 * ",    /* 14 (d4)   */ 
517     "0.5 * "      /* 15 (d2)   */ 
518 };
519
520 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */
521 static void shader_glsl_gen_modifier (
522     const DWORD instr,
523     const char *in_reg,
524     const char *in_regswizzle,
525     char *out_str) {
526
527     out_str[0] = 0;
528     
529     if (instr == WINED3DSIO_TEXKILL)
530         return;
531
532     switch (instr & WINED3DSP_SRCMOD_MASK) {
533     case WINED3DSPSM_DZ: /* Need to handle this in the instructions itself (texld & texcrd). */
534     case WINED3DSPSM_DW:
535     case WINED3DSPSM_NONE:
536         sprintf(out_str, "%s%s", in_reg, in_regswizzle);
537         break;
538     case WINED3DSPSM_NEG:
539         sprintf(out_str, "-%s%s", in_reg, in_regswizzle);
540         break;
541     case WINED3DSPSM_NOT:
542         sprintf(out_str, "!%s%s", in_reg, in_regswizzle);
543         break;
544     case WINED3DSPSM_BIAS:
545         sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
546         break;
547     case WINED3DSPSM_BIASNEG:
548         sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
549         break;
550     case WINED3DSPSM_SIGN:
551         sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
552         break;
553     case WINED3DSPSM_SIGNNEG:
554         sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
555         break;
556     case WINED3DSPSM_COMP:
557         sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle);
558         break;
559     case WINED3DSPSM_X2:
560         sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle);
561         break;
562     case WINED3DSPSM_X2NEG:
563         sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle);
564         break;
565     case WINED3DSPSM_ABS:
566         sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle);
567         break;
568     case WINED3DSPSM_ABSNEG:
569         sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle);
570         break;
571     default:
572         FIXME("Unhandled modifier %u\n", (instr & WINED3DSP_SRCMOD_MASK));
573         sprintf(out_str, "%s%s", in_reg, in_regswizzle);
574     }
575 }
576
577 /** Writes the GLSL variable name that corresponds to the register that the
578  * DX opcode parameter is trying to access */
579 static void shader_glsl_get_register_name(
580     const DWORD param,
581     const DWORD addr_token,
582     char* regstr,
583     BOOL* is_color,
584     SHADER_OPCODE_ARG* arg) {
585
586     /* oPos, oFog and oPts in D3D */
587     static const char * const hwrastout_reg_names[] = { "gl_Position", "gl_FogFragCoord", "gl_PointSize" };
588
589     DWORD reg = param & WINED3DSP_REGNUM_MASK;
590     DWORD regtype = shader_get_regtype(param);
591     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader;
592     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
593     WineD3D_GL_Info* gl_info = &((IWineD3DImpl*)deviceImpl->wineD3D)->gl_info;
594
595     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
596     char tmpStr[50];
597
598     *is_color = FALSE;   
599  
600     switch (regtype) {
601     case WINED3DSPR_TEMP:
602         sprintf(tmpStr, "R%u", reg);
603     break;
604     case WINED3DSPR_INPUT:
605         if (pshader) {
606             /* Pixel shaders >= 3.0 */
607             if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3)
608                 sprintf(tmpStr, "IN%u", reg);
609              else {
610                 if (reg==0)
611                     strcpy(tmpStr, "gl_Color");
612                 else
613                     strcpy(tmpStr, "gl_SecondaryColor");
614             }
615         } else {
616             if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
617                *is_color = TRUE;
618             sprintf(tmpStr, "attrib%u", reg);
619         } 
620         break;
621     case WINED3DSPR_CONST:
622     {
623         const char* prefix = pshader? "PC":"VC";
624
625         /* Relative addressing */
626         if (param & WINED3DSHADER_ADDRMODE_RELATIVE) {
627
628            /* Relative addressing on shaders 2.0+ have a relative address token, 
629             * prior to that, it was hard-coded as "A0.x" because there's only 1 register */
630            if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)  {
631                glsl_src_param_t rel_param;
632                shader_glsl_add_src_param(arg, addr_token, 0, WINED3DSP_WRITEMASK_0, &rel_param);
633                sprintf(tmpStr, "%s[%s + %u]", prefix, rel_param.param_str, reg);
634            } else
635                sprintf(tmpStr, "%s[A0.x + %u]", prefix, reg);
636
637         } else
638              sprintf(tmpStr, "%s[%u]", prefix, reg);
639
640         break;
641     }
642     case WINED3DSPR_CONSTINT:
643         if (pshader)
644             sprintf(tmpStr, "PI[%u]", reg);
645         else
646             sprintf(tmpStr, "VI[%u]", reg);
647         break;
648     case WINED3DSPR_CONSTBOOL:
649         if (pshader)
650             sprintf(tmpStr, "PB[%u]", reg);
651         else
652             sprintf(tmpStr, "VB[%u]", reg);
653         break;
654     case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
655         if (pshader) {
656             sprintf(tmpStr, "T%u", reg);
657         } else {
658             sprintf(tmpStr, "A%u", reg);
659         }
660     break;
661     case WINED3DSPR_LOOP:
662         sprintf(tmpStr, "aL");
663     break;
664     case WINED3DSPR_SAMPLER:
665         if (pshader)
666             sprintf(tmpStr, "Psampler%u", reg);
667         else
668             sprintf(tmpStr, "Vsampler%u", reg);
669     break;
670     case WINED3DSPR_COLOROUT:
671         if (reg >= GL_LIMITS(buffers)) {
672             WARN("Write to render target %u, only %d supported\n", reg, 4);
673         }
674         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
675             sprintf(tmpStr, "gl_FragData[%u]", reg);
676         } else { /* On older cards with GLSL support like the GeforceFX there's only one buffer. */
677             sprintf(tmpStr, "gl_FragColor");
678         }
679     break;
680     case WINED3DSPR_RASTOUT:
681         sprintf(tmpStr, "%s", hwrastout_reg_names[reg]);
682     break;
683     case WINED3DSPR_DEPTHOUT:
684         sprintf(tmpStr, "gl_FragDepth");
685     break;
686     case WINED3DSPR_ATTROUT:
687         if (reg == 0) {
688             sprintf(tmpStr, "gl_FrontColor");
689         } else {
690             sprintf(tmpStr, "gl_FrontSecondaryColor");
691         }
692     break;
693     case WINED3DSPR_TEXCRDOUT:
694         /* Vertex shaders >= 3.0: WINED3DSPR_OUTPUT */
695         if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3)
696             sprintf(tmpStr, "OUT%u", reg);
697         else
698             sprintf(tmpStr, "gl_TexCoord[%u]", reg);
699     break;
700     default:
701         FIXME("Unhandled register name Type(%d)\n", regtype);
702         sprintf(tmpStr, "unrecognized_register");
703     break;
704     }
705
706     strcat(regstr, tmpStr);
707 }
708
709 /* Get the GLSL write mask for the destination register */
710 static DWORD shader_glsl_get_write_mask(const DWORD param, char *write_mask) {
711     char *ptr = write_mask;
712     DWORD mask = param & WINED3DSP_WRITEMASK_ALL;
713
714     /* gl_FogFragCoord and glPointSize are floats, fixup the write mask. */
715     if ((shader_get_regtype(param) == WINED3DSPR_RASTOUT) && ((param & WINED3DSP_REGNUM_MASK) != 0)) {
716         mask = WINED3DSP_WRITEMASK_0;
717     } else {
718         *ptr++ = '.';
719         if (param & WINED3DSP_WRITEMASK_0) *ptr++ = 'x';
720         if (param & WINED3DSP_WRITEMASK_1) *ptr++ = 'y';
721         if (param & WINED3DSP_WRITEMASK_2) *ptr++ = 'z';
722         if (param & WINED3DSP_WRITEMASK_3) *ptr++ = 'w';
723     }
724
725     *ptr = '\0';
726
727     return mask;
728 }
729
730 static size_t shader_glsl_get_write_mask_size(DWORD write_mask) {
731     size_t size = 0;
732
733     if (write_mask & WINED3DSP_WRITEMASK_0) ++size;
734     if (write_mask & WINED3DSP_WRITEMASK_1) ++size;
735     if (write_mask & WINED3DSP_WRITEMASK_2) ++size;
736     if (write_mask & WINED3DSP_WRITEMASK_3) ++size;
737
738     return size;
739 }
740
741 static void shader_glsl_get_swizzle(const DWORD param, BOOL fixup, DWORD mask, char *swizzle_str) {
742     /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
743      * but addressed as "rgba". To fix this we need to swap the register's x
744      * and z components. */
745     DWORD swizzle = (param & WINED3DSP_SWIZZLE_MASK) >> WINED3DSP_SWIZZLE_SHIFT;
746     const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
747     char *ptr = swizzle_str;
748
749     *ptr++ = '.';
750     /* swizzle bits fields: wwzzyyxx */
751     if (mask & WINED3DSP_WRITEMASK_0) *ptr++ = swizzle_chars[swizzle & 0x03];
752     if (mask & WINED3DSP_WRITEMASK_1) *ptr++ = swizzle_chars[(swizzle >> 2) & 0x03];
753     if (mask & WINED3DSP_WRITEMASK_2) *ptr++ = swizzle_chars[(swizzle >> 4) & 0x03];
754     if (mask & WINED3DSP_WRITEMASK_3) *ptr++ = swizzle_chars[(swizzle >> 6) & 0x03];
755
756     *ptr = '\0';
757 }
758
759 /* From a given parameter token, generate the corresponding GLSL string.
760  * Also, return the actual register name and swizzle in case the
761  * caller needs this information as well. */
762 static void shader_glsl_add_src_param(SHADER_OPCODE_ARG* arg, const DWORD param,
763         const DWORD addr_token, DWORD mask, glsl_src_param_t *src_param) {
764     BOOL is_color = FALSE;
765     char swizzle_str[6];
766
767     src_param->reg_name[0] = '\0';
768     src_param->param_str[0] = '\0';
769     swizzle_str[0] = '\0';
770
771     shader_glsl_get_register_name(param, addr_token, src_param->reg_name, &is_color, arg);
772
773     shader_glsl_get_swizzle(param, is_color, mask, swizzle_str);
774     shader_glsl_gen_modifier(param, src_param->reg_name, swizzle_str, src_param->param_str);
775 }
776
777 /* From a given parameter token, generate the corresponding GLSL string.
778  * Also, return the actual register name and swizzle in case the
779  * caller needs this information as well. */
780 static DWORD shader_glsl_add_dst_param(SHADER_OPCODE_ARG* arg, const DWORD param,
781         const DWORD addr_token, glsl_dst_param_t *dst_param) {
782     BOOL is_color = FALSE;
783
784     dst_param->mask_str[0] = '\0';
785     dst_param->reg_name[0] = '\0';
786
787     shader_glsl_get_register_name(param, addr_token, dst_param->reg_name, &is_color, arg);
788     return shader_glsl_get_write_mask(param, dst_param->mask_str);
789 }
790
791 /* Append the destination part of the instruction to the buffer, return the effective write mask */
792 static DWORD shader_glsl_append_dst(SHADER_BUFFER *buffer, SHADER_OPCODE_ARG *arg) {
793     glsl_dst_param_t dst_param;
794     DWORD mask;
795     int shift;
796
797     shift = (arg->dst & WINED3DSP_DSTSHIFT_MASK) >> WINED3DSP_DSTSHIFT_SHIFT;
798     mask = shader_glsl_add_dst_param(arg, arg->dst, arg->dst_addr, &dst_param);
799     shader_addline(buffer, "%s%s = %s(", dst_param.reg_name, dst_param.mask_str, shift_glsl_tab[shift]);
800
801     return mask;
802 }
803
804 /** Process GLSL instruction modifiers */
805 void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG* arg) {
806     
807     DWORD mask = arg->dst & WINED3DSP_DSTMOD_MASK;
808  
809     if (arg->opcode->dst_token && mask != 0) {
810         glsl_dst_param_t dst_param;
811
812         shader_glsl_add_dst_param(arg, arg->dst, 0, &dst_param);
813
814         if (mask & WINED3DSPDM_SATURATE) {
815             /* _SAT means to clamp the value of the register to between 0 and 1 */
816             shader_addline(arg->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_param.reg_name,
817                     dst_param.mask_str, dst_param.reg_name, dst_param.mask_str);
818         }
819         if (mask & WINED3DSPDM_MSAMPCENTROID) {
820             FIXME("_centroid modifier not handled\n");
821         }
822         if (mask & WINED3DSPDM_PARTIALPRECISION) {
823             /* MSDN says this modifier can be safely ignored, so that's what we'll do. */
824         }
825     }
826 }
827
828 static inline const char* shader_get_comp_op(
829     const DWORD opcode) {
830
831     DWORD op = (opcode & INST_CONTROLS_MASK) >> INST_CONTROLS_SHIFT;
832     switch (op) {
833         case COMPARISON_GT: return ">";
834         case COMPARISON_EQ: return "==";
835         case COMPARISON_GE: return ">=";
836         case COMPARISON_LT: return "<";
837         case COMPARISON_NE: return "!=";
838         case COMPARISON_LE: return "<=";
839         default:
840             FIXME("Unrecognized comparison value: %u\n", op);
841             return "(\?\?)";
842     }
843 }
844
845 static void shader_glsl_get_sample_function(DWORD sampler_type, BOOL projected, glsl_sample_function_t *sample_function) {
846     /* Note that there's no such thing as a projected cube texture. */
847     switch(sampler_type) {
848         case WINED3DSTT_1D:
849             sample_function->name = projected ? "texture1DProj" : "texture1D";
850             sample_function->coord_mask = WINED3DSP_WRITEMASK_0;
851             break;
852         case WINED3DSTT_2D:
853             sample_function->name = projected ? "texture2DProj" : "texture2D";
854             sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1;
855             break;
856         case WINED3DSTT_CUBE:
857             sample_function->name = "textureCube";
858             sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
859             break;
860         case WINED3DSTT_VOLUME:
861             sample_function->name = projected ? "texture3DProj" : "texture3D";
862             sample_function->coord_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
863             break;
864         default:
865             sample_function->name = "";
866             FIXME("Unrecognized sampler type: %#x;\n", sampler_type);
867             break;
868     }
869 }
870
871
872 /*****************************************************************************
873  * 
874  * Begin processing individual instruction opcodes
875  * 
876  ****************************************************************************/
877
878 /* Generate GLSL arithmetic functions (dst = src1 + src2) */
879 void shader_glsl_arith(SHADER_OPCODE_ARG* arg) {
880     CONST SHADER_OPCODE* curOpcode = arg->opcode;
881     SHADER_BUFFER* buffer = arg->buffer;
882     glsl_src_param_t src0_param;
883     glsl_src_param_t src1_param;
884     DWORD write_mask;
885     char op;
886
887     /* Determine the GLSL operator to use based on the opcode */
888     switch (curOpcode->opcode) {
889         case WINED3DSIO_MUL: op = '*'; break;
890         case WINED3DSIO_ADD: op = '+'; break;
891         case WINED3DSIO_SUB: op = '-'; break;
892         default:
893             op = ' ';
894             FIXME("Opcode %s not yet handled in GLSL\n", curOpcode->name);
895             break;
896     }
897
898     write_mask = shader_glsl_append_dst(buffer, arg);
899     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
900     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
901     shader_addline(buffer, "%s %c %s);\n", src0_param.param_str, op, src1_param.param_str);
902 }
903
904 /* Process the WINED3DSIO_MOV opcode using GLSL (dst = src) */
905 void shader_glsl_mov(SHADER_OPCODE_ARG* arg) {
906     IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
907     SHADER_BUFFER* buffer = arg->buffer;
908     glsl_src_param_t src0_param;
909     DWORD write_mask;
910
911     write_mask = shader_glsl_append_dst(buffer, arg);
912     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
913
914     /* In vs_1_1 WINED3DSIO_MOV can write to the adress register. In later
915      * shader versions WINED3DSIO_MOVA is used for this. */
916     if ((WINED3DSHADER_VERSION_MAJOR(shader->baseShader.hex_version) == 1 &&
917             !shader_is_pshader_version(shader->baseShader.hex_version) &&
918             shader_get_regtype(arg->dst) == WINED3DSPR_ADDR) ||
919             arg->opcode->opcode == WINED3DSIO_MOVA) {
920         /* We need to *round* to the nearest int here. */
921         size_t mask_size = shader_glsl_get_write_mask_size(write_mask);
922         if (mask_size > 1) {
923             shader_addline(buffer, "ivec%d(floor(%s + vec%d(0.5))));\n", mask_size, src0_param.param_str, mask_size);
924         } else {
925             shader_addline(buffer, "int(floor(%s + 0.5)));\n", src0_param.param_str);
926         }
927     } else {
928         shader_addline(buffer, "%s);\n", src0_param.param_str);
929     }
930 }
931
932 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */
933 void shader_glsl_dot(SHADER_OPCODE_ARG* arg) {
934     CONST SHADER_OPCODE* curOpcode = arg->opcode;
935     SHADER_BUFFER* buffer = arg->buffer;
936     glsl_src_param_t src0_param;
937     glsl_src_param_t src1_param;
938     DWORD dst_write_mask, src_write_mask;
939     size_t dst_size = 0;
940
941     dst_write_mask = shader_glsl_append_dst(buffer, arg);
942     dst_size = shader_glsl_get_write_mask_size(dst_write_mask);
943
944     /* dp3 works on vec3, dp4 on vec4 */
945     if (curOpcode->opcode == WINED3DSIO_DP4) {
946         src_write_mask = WINED3DSP_WRITEMASK_ALL;
947     } else {
948         src_write_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
949     }
950
951     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_write_mask, &src0_param);
952     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], src_write_mask, &src1_param);
953
954     if (dst_size > 1) {
955         shader_addline(buffer, "vec%d(dot(%s, %s)));\n", dst_size, src0_param.param_str, src1_param.param_str);
956     } else {
957         shader_addline(buffer, "dot(%s, %s));\n", src0_param.param_str, src1_param.param_str);
958     }
959 }
960
961 /* Note that this instruction has some restrictions. The destination write mask
962  * can't contain the w component, and the source swizzles have to be .xyzw */
963 void shader_glsl_cross(SHADER_OPCODE_ARG *arg) {
964     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
965     glsl_src_param_t src0_param;
966     glsl_src_param_t src1_param;
967     char dst_mask[6];
968
969     shader_glsl_get_write_mask(arg->dst, dst_mask);
970     shader_glsl_append_dst(arg->buffer, arg);
971     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
972     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], src_mask, &src1_param);
973     shader_addline(arg->buffer, "cross(%s, %s).%s);\n", src0_param.param_str, src1_param.param_str, dst_mask);
974 }
975
976 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */
977 void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) {
978     CONST SHADER_OPCODE* curOpcode = arg->opcode;
979     SHADER_BUFFER* buffer = arg->buffer;
980     glsl_src_param_t src_param;
981     const char *instruction;
982     char arguments[256];
983     DWORD write_mask;
984     unsigned i;
985
986     /* Determine the GLSL function to use based on the opcode */
987     /* TODO: Possibly make this a table for faster lookups */
988     switch (curOpcode->opcode) {
989         case WINED3DSIO_MIN: instruction = "min"; break;
990         case WINED3DSIO_MAX: instruction = "max"; break;
991         case WINED3DSIO_RSQ: instruction = "inversesqrt"; break;
992         case WINED3DSIO_ABS: instruction = "abs"; break;
993         case WINED3DSIO_FRC: instruction = "fract"; break;
994         case WINED3DSIO_POW: instruction = "pow"; break;
995         case WINED3DSIO_NRM: instruction = "normalize"; break;
996         case WINED3DSIO_LOGP:
997         case WINED3DSIO_LOG: instruction = "log2"; break;
998         case WINED3DSIO_EXP: instruction = "exp2"; break;
999         case WINED3DSIO_SGN: instruction = "sign"; break;
1000         default: instruction = "";
1001             FIXME("Opcode %s not yet handled in GLSL\n", curOpcode->name);
1002             break;
1003     }
1004
1005     write_mask = shader_glsl_append_dst(buffer, arg);
1006
1007     arguments[0] = '\0';
1008     if (curOpcode->num_params > 0) {
1009         shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src_param);
1010         strcat(arguments, src_param.param_str);
1011         for (i = 2; i < curOpcode->num_params; ++i) {
1012             strcat(arguments, ", ");
1013             shader_glsl_add_src_param(arg, arg->src[i-1], arg->src_addr[i-1], write_mask, &src_param);
1014             strcat(arguments, src_param.param_str);
1015         }
1016     }
1017
1018     shader_addline(buffer, "%s(%s));\n", instruction, arguments);
1019 }
1020
1021 /** Process the WINED3DSIO_EXPP instruction in GLSL:
1022  * For shader model 1.x, do the following (and honor the writemask, so use a temporary variable):
1023  *   dst.x = 2^(floor(src))
1024  *   dst.y = src - floor(src)
1025  *   dst.z = 2^src   (partial precision is allowed, but optional)
1026  *   dst.w = 1.0;
1027  * For 2.0 shaders, just do this (honoring writemask and swizzle):
1028  *   dst = 2^src;    (partial precision is allowed, but optional)
1029  */
1030 void shader_glsl_expp(SHADER_OPCODE_ARG* arg) {
1031     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)arg->shader;
1032     glsl_src_param_t src_param;
1033
1034     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param);
1035
1036     if (shader->baseShader.hex_version < WINED3DPS_VERSION(2,0)) {
1037         char dst_mask[6];
1038
1039         shader_addline(arg->buffer, "tmp0.x = exp2(floor(%s));\n", src_param.param_str);
1040         shader_addline(arg->buffer, "tmp0.y = %s - floor(%s);\n", src_param.param_str, src_param.param_str);
1041         shader_addline(arg->buffer, "tmp0.z = exp2(%s);\n", src_param.param_str);
1042         shader_addline(arg->buffer, "tmp0.w = 1.0;\n");
1043
1044         shader_glsl_append_dst(arg->buffer, arg);
1045         shader_glsl_get_write_mask(arg->dst, dst_mask);
1046         shader_addline(arg->buffer, "tmp0%s);\n", dst_mask);
1047     } else {
1048         DWORD write_mask;
1049         size_t mask_size;
1050
1051         write_mask = shader_glsl_append_dst(arg->buffer, arg);
1052         mask_size = shader_glsl_get_write_mask_size(write_mask);
1053
1054         if (mask_size > 1) {
1055             shader_addline(arg->buffer, "vec%d(exp2(%s)));\n", mask_size, src_param.param_str);
1056         } else {
1057             shader_addline(arg->buffer, "exp2(%s));\n", src_param.param_str);
1058         }
1059     }
1060 }
1061
1062 /** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */
1063 void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) {
1064     glsl_src_param_t src_param;
1065     DWORD write_mask;
1066     size_t mask_size;
1067
1068     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1069     mask_size = shader_glsl_get_write_mask_size(write_mask);
1070     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src_param);
1071
1072     if (mask_size > 1) {
1073         shader_addline(arg->buffer, "vec%d(1.0 / %s));\n", mask_size, src_param.param_str);
1074     } else {
1075         shader_addline(arg->buffer, "1.0 / %s);\n", src_param.param_str);
1076     }
1077 }
1078
1079 /** Process signed comparison opcodes in GLSL. */
1080 void shader_glsl_compare(SHADER_OPCODE_ARG* arg) {
1081     glsl_src_param_t src0_param;
1082     glsl_src_param_t src1_param;
1083     DWORD write_mask;
1084     size_t mask_size;
1085
1086     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1087     mask_size = shader_glsl_get_write_mask_size(write_mask);
1088     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
1089     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
1090
1091     if (mask_size > 1) {
1092         const char *compare;
1093
1094         switch(arg->opcode->opcode) {
1095             case WINED3DSIO_SLT: compare = "lessThan"; break;
1096             case WINED3DSIO_SGE: compare = "greaterThanEqual"; break;
1097             default: compare = "";
1098                 FIXME("Can't handle opcode %s\n", arg->opcode->name);
1099         }
1100
1101         shader_addline(arg->buffer, "vec%d(%s(%s, %s)));\n", mask_size, compare,
1102                 src0_param.param_str, src1_param.param_str);
1103     } else {
1104         const char *compare;
1105
1106         switch(arg->opcode->opcode) {
1107             case WINED3DSIO_SLT: compare = "<"; break;
1108             case WINED3DSIO_SGE: compare = ">="; break;
1109             default: compare = "";
1110                 FIXME("Can't handle opcode %s\n", arg->opcode->name);
1111         }
1112
1113         shader_addline(arg->buffer, "(%s %s %s) ? 1.0 : 0.0);\n",
1114                 src0_param.param_str, compare, src1_param.param_str);
1115     }
1116 }
1117
1118 /** Process CMP instruction in GLSL (dst = src0 >= 0.0 ? src1 : src2), per channel */
1119 void shader_glsl_cmp(SHADER_OPCODE_ARG* arg) {
1120     glsl_src_param_t src0_param;
1121     glsl_src_param_t src1_param;
1122     glsl_src_param_t src2_param;
1123     DWORD write_mask;
1124     size_t mask_size;
1125
1126     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1127     mask_size = shader_glsl_get_write_mask_size(write_mask);
1128
1129     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
1130     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
1131     shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param);
1132
1133     if (mask_size > 1) {
1134         shader_addline(arg->buffer, "mix(%s, %s, vec%d(lessThan(%s, vec%d(0.0)))));\n",
1135                 src1_param.param_str, src2_param.param_str, mask_size, src0_param.param_str, mask_size);
1136     } else {
1137         shader_addline(arg->buffer, "%s >= 0.0 ? %s : %s);\n",
1138                 src0_param.param_str, src1_param.param_str, src2_param.param_str);
1139     }
1140 }
1141
1142 /** Process the CND opcode in GLSL (dst = (src0 < 0.5) ? src1 : src2) */
1143 /* For ps 1.1-1.3, only a single component of src0 is used. For ps 1.4
1144  * the compare is done per component of src0. */
1145 void shader_glsl_cnd(SHADER_OPCODE_ARG* arg) {
1146     IWineD3DBaseShaderImpl* shader = (IWineD3DBaseShaderImpl*) arg->shader;
1147     glsl_src_param_t src0_param;
1148     glsl_src_param_t src1_param;
1149     glsl_src_param_t src2_param;
1150     DWORD write_mask;
1151     size_t mask_size;
1152
1153     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1154
1155     if (shader->baseShader.hex_version < WINED3DPS_VERSION(1, 4)) {
1156         mask_size = 1;
1157         shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1158     } else {
1159         mask_size = shader_glsl_get_write_mask_size(write_mask);
1160         shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
1161     }
1162
1163     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
1164     shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param);
1165
1166     if (mask_size > 1) {
1167         shader_addline(arg->buffer, "mix(%s, %s, vec%d(lessThan(%s, vec%d(0.5)))));\n",
1168                 src2_param.param_str, src1_param.param_str, mask_size, src0_param.param_str, mask_size);
1169     } else {
1170         shader_addline(arg->buffer, "%s < 0.5 ? %s : %s);\n",
1171                 src0_param.param_str, src1_param.param_str, src2_param.param_str);
1172     }
1173 }
1174
1175 /** GLSL code generation for WINED3DSIO_MAD: Multiply the first 2 opcodes, then add the last */
1176 void shader_glsl_mad(SHADER_OPCODE_ARG* arg) {
1177     glsl_src_param_t src0_param;
1178     glsl_src_param_t src1_param;
1179     glsl_src_param_t src2_param;
1180     DWORD write_mask;
1181
1182     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1183     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
1184     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
1185     shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param);
1186     shader_addline(arg->buffer, "(%s * %s) + %s);\n",
1187             src0_param.param_str, src1_param.param_str, src2_param.param_str);
1188 }
1189
1190 /** Handles transforming all WINED3DSIO_M?x? opcodes for 
1191     Vertex shaders to GLSL codes */
1192 void shader_glsl_mnxn(SHADER_OPCODE_ARG* arg) {
1193     int i;
1194     int nComponents = 0;
1195     SHADER_OPCODE_ARG tmpArg;
1196    
1197     memset(&tmpArg, 0, sizeof(SHADER_OPCODE_ARG));
1198
1199     /* Set constants for the temporary argument */
1200     tmpArg.shader      = arg->shader;
1201     tmpArg.buffer      = arg->buffer;
1202     tmpArg.src[0]      = arg->src[0];
1203     tmpArg.src_addr[0] = arg->src_addr[0];
1204     tmpArg.src_addr[1] = arg->src_addr[1];
1205     tmpArg.reg_maps = arg->reg_maps; 
1206     
1207     switch(arg->opcode->opcode) {
1208         case WINED3DSIO_M4x4:
1209             nComponents = 4;
1210             tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP4);
1211             break;
1212         case WINED3DSIO_M4x3:
1213             nComponents = 3;
1214             tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP4);
1215             break;
1216         case WINED3DSIO_M3x4:
1217             nComponents = 4;
1218             tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP3);
1219             break;
1220         case WINED3DSIO_M3x3:
1221             nComponents = 3;
1222             tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP3);
1223             break;
1224         case WINED3DSIO_M3x2:
1225             nComponents = 2;
1226             tmpArg.opcode = shader_get_opcode(arg->shader, WINED3DSIO_DP3);
1227             break;
1228         default:
1229             break;
1230     }
1231
1232     for (i = 0; i < nComponents; i++) {
1233         tmpArg.dst = ((arg->dst) & ~WINED3DSP_WRITEMASK_ALL)|(WINED3DSP_WRITEMASK_0<<i);
1234         tmpArg.src[1]      = arg->src[1]+i;
1235         shader_glsl_dot(&tmpArg);
1236     }
1237 }
1238
1239 /**
1240     The LRP instruction performs a component-wise linear interpolation 
1241     between the second and third operands using the first operand as the
1242     blend factor.  Equation:  (dst = src2 + src0 * (src1 - src2))
1243     This is equivalent to mix(src2, src1, src0);
1244 */
1245 void shader_glsl_lrp(SHADER_OPCODE_ARG* arg) {
1246     glsl_src_param_t src0_param;
1247     glsl_src_param_t src1_param;
1248     glsl_src_param_t src2_param;
1249     DWORD write_mask;
1250
1251     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1252
1253     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], write_mask, &src0_param);
1254     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], write_mask, &src1_param);
1255     shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], write_mask, &src2_param);
1256
1257     shader_addline(arg->buffer, "mix(%s, %s, %s));\n",
1258             src2_param.param_str, src1_param.param_str, src0_param.param_str);
1259 }
1260
1261 /** Process the WINED3DSIO_LIT instruction in GLSL:
1262  * dst.x = dst.w = 1.0
1263  * dst.y = (src0.x > 0) ? src0.x
1264  * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0
1265  *                                        where src.w is clamped at +- 128
1266  */
1267 void shader_glsl_lit(SHADER_OPCODE_ARG* arg) {
1268     glsl_src_param_t src0_param;
1269     glsl_src_param_t src1_param;
1270     glsl_src_param_t src3_param;
1271     char dst_mask[6];
1272
1273     shader_glsl_append_dst(arg->buffer, arg);
1274     shader_glsl_get_write_mask(arg->dst, dst_mask);
1275
1276     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1277     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_1, &src1_param);
1278     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &src3_param);
1279
1280     shader_addline(arg->buffer, "vec4(1.0, (%s > 0.0 ? %s : 0.0), (%s > 0.0 ? ((%s > 0.0) ? pow(%s, clamp(%s, -128.0, 128.0)) : 0.0) : 0.0), 1.0)%s);\n",
1281         src0_param.param_str, src0_param.param_str, src0_param.param_str, src1_param.param_str, src1_param.param_str, src3_param.param_str, dst_mask);
1282 }
1283
1284 /** Process the WINED3DSIO_DST instruction in GLSL:
1285  * dst.x = 1.0
1286  * dst.y = src0.x * src0.y
1287  * dst.z = src0.z
1288  * dst.w = src1.w
1289  */
1290 void shader_glsl_dst(SHADER_OPCODE_ARG* arg) {
1291     glsl_src_param_t src0y_param;
1292     glsl_src_param_t src0z_param;
1293     glsl_src_param_t src1y_param;
1294     glsl_src_param_t src1w_param;
1295     char dst_mask[6];
1296
1297     shader_glsl_append_dst(arg->buffer, arg);
1298     shader_glsl_get_write_mask(arg->dst, dst_mask);
1299
1300     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_1, &src0y_param);
1301     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &src0z_param);
1302     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_1, &src1y_param);
1303     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_3, &src1w_param);
1304
1305     shader_addline(arg->buffer, "vec4(1.0, %s * %s, %s, %s))%s;\n",
1306             src0y_param.param_str, src1y_param.param_str, src0z_param.param_str, src1w_param.param_str, dst_mask);
1307 }
1308
1309 /** Process the WINED3DSIO_SINCOS instruction in GLSL:
1310  * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware
1311  * can handle it.  But, these functions are built-in for GLSL, so we can just ignore the last 2 params.
1312  * 
1313  * dst.x = cos(src0.?)
1314  * dst.y = sin(src0.?)
1315  * dst.z = dst.z
1316  * dst.w = dst.w
1317  */
1318 void shader_glsl_sincos(SHADER_OPCODE_ARG* arg) {
1319     glsl_src_param_t src0_param;
1320     DWORD write_mask;
1321
1322     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1323     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1324
1325     switch (write_mask) {
1326         case WINED3DSP_WRITEMASK_0:
1327             shader_addline(arg->buffer, "cos(%s));\n", src0_param.param_str);
1328             break;
1329
1330         case WINED3DSP_WRITEMASK_1:
1331             shader_addline(arg->buffer, "sin(%s));\n", src0_param.param_str);
1332             break;
1333
1334         case (WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1):
1335             shader_addline(arg->buffer, "vec2(cos(%s), sin(%s)));\n", src0_param.param_str, src0_param.param_str);
1336             break;
1337
1338         default:
1339             ERR("Write mask should be .x, .y or .xy\n");
1340             break;
1341     }
1342 }
1343
1344 /** Process the WINED3DSIO_LOOP instruction in GLSL:
1345  * Start a for() loop where src1.y is the initial value of aL,
1346  *  increment aL by src1.z for a total of src1.x iterations.
1347  *  Need to use a temporary variable for this operation.
1348  */
1349 /* FIXME: I don't think nested loops will work correctly this way. */
1350 void shader_glsl_loop(SHADER_OPCODE_ARG* arg) {
1351     glsl_src_param_t src1_param;
1352
1353     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_ALL, &src1_param);
1354   
1355     shader_addline(arg->buffer, "for (tmpInt = 0, aL = %s.y; tmpInt < %s.x; tmpInt++, aL += %s.z) {\n",
1356             src1_param.reg_name, src1_param.reg_name, src1_param.reg_name);
1357 }
1358
1359 void shader_glsl_end(SHADER_OPCODE_ARG* arg) {
1360     shader_addline(arg->buffer, "}\n");
1361 }
1362
1363 void shader_glsl_rep(SHADER_OPCODE_ARG* arg) {
1364     glsl_src_param_t src0_param;
1365
1366     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1367     shader_addline(arg->buffer, "for (tmpInt = 0; tmpInt < %s; tmpInt++) {\n", src0_param.param_str);
1368 }
1369
1370 void shader_glsl_if(SHADER_OPCODE_ARG* arg) {
1371     glsl_src_param_t src0_param;
1372
1373     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1374     shader_addline(arg->buffer, "if (%s) {\n", src0_param.param_str);
1375 }
1376
1377 void shader_glsl_ifc(SHADER_OPCODE_ARG* arg) {
1378     glsl_src_param_t src0_param;
1379     glsl_src_param_t src1_param;
1380
1381     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1382     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
1383
1384     shader_addline(arg->buffer, "if (%s %s %s) {\n",
1385             src0_param.param_str, shader_get_comp_op(arg->opcode_token), src1_param.param_str);
1386 }
1387
1388 void shader_glsl_else(SHADER_OPCODE_ARG* arg) {
1389     shader_addline(arg->buffer, "} else {\n");
1390 }
1391
1392 void shader_glsl_break(SHADER_OPCODE_ARG* arg) {
1393     shader_addline(arg->buffer, "break;\n");
1394 }
1395
1396 /* FIXME: According to MSDN the compare is done per component. */
1397 void shader_glsl_breakc(SHADER_OPCODE_ARG* arg) {
1398     glsl_src_param_t src0_param;
1399     glsl_src_param_t src1_param;
1400
1401     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0, &src0_param);
1402     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
1403
1404     shader_addline(arg->buffer, "if (%s %s %s) break;\n",
1405             src0_param.param_str, shader_get_comp_op(arg->opcode_token), src1_param.param_str);
1406 }
1407
1408 void shader_glsl_label(SHADER_OPCODE_ARG* arg) {
1409
1410     DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK;
1411     shader_addline(arg->buffer, "}\n");
1412     shader_addline(arg->buffer, "void subroutine%lu () {\n",  snum);
1413 }
1414
1415 void shader_glsl_call(SHADER_OPCODE_ARG* arg) {
1416     DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK;
1417     shader_addline(arg->buffer, "subroutine%lu();\n", snum);
1418 }
1419
1420 void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) {
1421     glsl_src_param_t src1_param;
1422
1423     DWORD snum = (arg->src[0]) & WINED3DSP_REGNUM_MASK;
1424     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0, &src1_param);
1425     shader_addline(arg->buffer, "if (%s) subroutine%lu();\n", src1_param.param_str, snum);
1426 }
1427
1428 /*********************************************
1429  * Pixel Shader Specific Code begins here
1430  ********************************************/
1431 void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
1432     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1433     DWORD hex_version = This->baseShader.hex_version;
1434     char dst_swizzle[6];
1435     glsl_sample_function_t sample_function;
1436     DWORD sampler_type;
1437     DWORD sampler_idx;
1438     BOOL projected;
1439     DWORD mask = 0;
1440
1441     /* All versions have a destination register */
1442     shader_glsl_append_dst(arg->buffer, arg);
1443
1444     /* 1.0-1.4: Use destination register as sampler source.
1445      * 2.0+: Use provided sampler source. */
1446     if (hex_version < WINED3DPS_VERSION(1,4)) {
1447         IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) This->baseShader.device;
1448         DWORD flags;
1449
1450         sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
1451         flags = deviceImpl->stateBlock->textureState[sampler_idx][WINED3DTSS_TEXTURETRANSFORMFLAGS];
1452
1453         if (flags & WINED3DTTFF_PROJECTED) {
1454             projected = TRUE;
1455             switch (flags & ~WINED3DTTFF_PROJECTED) {
1456                 case WINED3DTTFF_COUNT1: FIXME("WINED3DTTFF_PROJECTED with WINED3DTTFF_COUNT1?\n"); break;
1457                 case WINED3DTTFF_COUNT2: mask = WINED3DSP_WRITEMASK_1; break;
1458                 case WINED3DTTFF_COUNT3: mask = WINED3DSP_WRITEMASK_2; break;
1459                 case WINED3DTTFF_COUNT4:
1460                 case WINED3DTTFF_DISABLE: mask = WINED3DSP_WRITEMASK_3; break;
1461             }
1462         } else {
1463             projected = FALSE;
1464         }
1465     } else if (hex_version < WINED3DPS_VERSION(2,0)) {
1466         DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
1467         sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
1468
1469         if (src_mod == WINED3DSPSM_DZ) {
1470             projected = TRUE;
1471             mask = WINED3DSP_WRITEMASK_2;
1472         } else if (src_mod == WINED3DSPSM_DW) {
1473             projected = TRUE;
1474             mask = WINED3DSP_WRITEMASK_3;
1475         } else {
1476             projected = FALSE;
1477         }
1478     } else {
1479         sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
1480         /* TODO: Handle D3DSI_TEXLD_PROJECTED... */
1481         projected = FALSE;
1482     }
1483
1484     sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
1485     shader_glsl_get_sample_function(sampler_type, projected, &sample_function);
1486     mask |= sample_function.coord_mask;
1487
1488     if (hex_version < WINED3DPS_VERSION(2,0)) {
1489         shader_glsl_get_write_mask(arg->dst, dst_swizzle);
1490     } else {
1491         shader_glsl_get_swizzle(arg->src[1], FALSE, arg->dst, dst_swizzle);
1492     }
1493
1494     /* 1.0-1.3: Use destination register as coordinate source.
1495        1.4+: Use provided coordinate source register. */
1496     if (hex_version < WINED3DPS_VERSION(1,4)) {
1497         char coord_mask[6];
1498         shader_glsl_get_write_mask(mask, coord_mask);
1499         shader_addline(arg->buffer, "%s(Psampler%u, T%u%s)%s);\n",
1500                 sample_function.name, sampler_idx, sampler_idx, coord_mask, dst_swizzle);
1501     } else {
1502         glsl_src_param_t coord_param;
1503         shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], mask, &coord_param);
1504         shader_addline(arg->buffer, "%s(Psampler%u, %s)%s);\n",
1505                 sample_function.name, sampler_idx, coord_param.param_str, dst_swizzle);
1506     }
1507 }
1508
1509 void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) {
1510
1511     /* FIXME: Make this work for more than just 2D textures */
1512     
1513     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1514     SHADER_BUFFER* buffer = arg->buffer;
1515     DWORD hex_version = This->baseShader.hex_version;
1516     DWORD write_mask;
1517     char dst_mask[6];
1518
1519     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1520     shader_glsl_get_write_mask(write_mask, dst_mask);
1521
1522     if (hex_version != WINED3DPS_VERSION(1,4)) {
1523         DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1524         shader_addline(buffer, "clamp(gl_TexCoord[%u], 0.0, 1.0)%s);\n", reg, dst_mask);
1525     } else {
1526         DWORD reg = arg->src[0] & WINED3DSP_REGNUM_MASK;
1527         DWORD src_mod = arg->src[0] & WINED3DSP_SRCMOD_MASK;
1528         char dst_swizzle[6];
1529
1530         shader_glsl_get_swizzle(arg->src[0], FALSE, write_mask, dst_swizzle);
1531
1532         if (src_mod == WINED3DSPSM_DZ) {
1533             glsl_src_param_t div_param;
1534             size_t mask_size = shader_glsl_get_write_mask_size(write_mask);
1535             shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &div_param);
1536
1537             if (mask_size > 1) {
1538                 shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
1539             } else {
1540                 shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
1541             }
1542         } else if (src_mod == WINED3DSPSM_DW) {
1543             glsl_src_param_t div_param;
1544             size_t mask_size = shader_glsl_get_write_mask_size(write_mask);
1545             shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_3, &div_param);
1546
1547             if (mask_size > 1) {
1548                 shader_addline(buffer, "gl_TexCoord[%u]%s / vec%d(%s));\n", reg, dst_swizzle, mask_size, div_param.param_str);
1549             } else {
1550                 shader_addline(buffer, "gl_TexCoord[%u]%s / %s);\n", reg, dst_swizzle, div_param.param_str);
1551             }
1552         } else {
1553             shader_addline(buffer, "gl_TexCoord[%u]%s);\n", reg, dst_swizzle);
1554         }
1555     }
1556 }
1557
1558 /** Process the WINED3DSIO_TEXDP3TEX instruction in GLSL:
1559  * Take a 3-component dot product of the TexCoord[dstreg] and src,
1560  * then perform a 1D texture lookup from stage dstregnum, place into dst. */
1561 void pshader_glsl_texdp3tex(SHADER_OPCODE_ARG* arg) {
1562     glsl_src_param_t src0_param;
1563     char dst_mask[6];
1564     DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
1565     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1566
1567     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1568
1569     shader_glsl_append_dst(arg->buffer, arg);
1570     shader_glsl_get_write_mask(arg->dst, dst_mask);
1571     shader_addline(arg->buffer, "texture1D(Psampler%u, dot(gl_TexCoord[%u].xyz, %s))%s);\n",
1572             sampler_idx, sampler_idx, src0_param.param_str, dst_mask);
1573 }
1574
1575 /** Process the WINED3DSIO_TEXDP3 instruction in GLSL:
1576  * Take a 3-component dot product of the TexCoord[dstreg] and src. */
1577 void pshader_glsl_texdp3(SHADER_OPCODE_ARG* arg) {
1578     glsl_src_param_t src0_param;
1579     DWORD dstreg = arg->dst & WINED3DSP_REGNUM_MASK;
1580     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1581     DWORD dst_mask;
1582     size_t mask_size;
1583
1584     dst_mask = shader_glsl_append_dst(arg->buffer, arg);
1585     mask_size = shader_glsl_get_write_mask_size(dst_mask);
1586     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1587
1588     if (mask_size > 1) {
1589         shader_addline(arg->buffer, "vec%d(dot(T%u.xyz, %s)));\n", mask_size, dstreg, src0_param.param_str);
1590     } else {
1591         shader_addline(arg->buffer, "dot(T%u.xyz, %s));\n", dstreg, src0_param.param_str);
1592     }
1593 }
1594
1595 /** Process the WINED3DSIO_TEXDEPTH instruction in GLSL:
1596  * Calculate the depth as dst.x / dst.y   */
1597 void pshader_glsl_texdepth(SHADER_OPCODE_ARG* arg) {
1598     glsl_dst_param_t dst_param;
1599
1600     shader_glsl_add_dst_param(arg, arg->dst, 0, &dst_param);
1601
1602     shader_addline(arg->buffer, "gl_FragDepth = %s.x / %s.y;\n", dst_param.reg_name, dst_param.reg_name);
1603 }
1604
1605 /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in GLSL:
1606  * Last row of a 3x2 matrix multiply, use the result to calculate the depth:
1607  * Calculate tmp0.y = TexCoord[dstreg] . src.xyz;  (tmp0.x has already been calculated)
1608  * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
1609  */
1610 void pshader_glsl_texm3x2depth(SHADER_OPCODE_ARG* arg) {
1611     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1612     DWORD dstreg = arg->dst & WINED3DSP_REGNUM_MASK;
1613     glsl_src_param_t src0_param;
1614
1615     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1616
1617     shader_addline(arg->buffer, "tmp0.y = dot(T%u.xyz, %s);\n", dstreg, src0_param.param_str);
1618     shader_addline(arg->buffer, "gl_FragDepth = (tmp0.y == 0.0) ? 1.0 : clamp(tmp0.x / tmp0.y, 0.0, 1.0);\n");
1619 }
1620
1621 /** Process the WINED3DSIO_TEXM3X2PAD instruction in GLSL
1622  * Calculate the 1st of a 2-row matrix multiplication. */
1623 void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1624     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1625     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1626     SHADER_BUFFER* buffer = arg->buffer;
1627     glsl_src_param_t src0_param;
1628
1629     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1630     shader_addline(buffer, "tmp0.x = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
1631 }
1632
1633 /** Process the WINED3DSIO_TEXM3X3PAD instruction in GLSL
1634  * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */
1635 void pshader_glsl_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1636
1637     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1638     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1639     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1640     SHADER_BUFFER* buffer = arg->buffer;
1641     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
1642     glsl_src_param_t src0_param;
1643
1644     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1645     shader_addline(buffer, "tmp0.%c = dot(T%u.xyz, %s);\n", 'x' + current_state->current_row, reg, src0_param.param_str);
1646     current_state->texcoord_w[current_state->current_row++] = reg;
1647 }
1648
1649 void pshader_glsl_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1650     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1651     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1652     SHADER_BUFFER* buffer = arg->buffer;
1653     glsl_src_param_t src0_param;
1654     char dst_mask[6];
1655
1656     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1657     shader_addline(buffer, "tmp0.y = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
1658
1659     shader_glsl_append_dst(buffer, arg);
1660     shader_glsl_get_write_mask(arg->dst, dst_mask);
1661
1662     /* Sample the texture using the calculated coordinates */
1663     shader_addline(buffer, "texture2D(Psampler%u, tmp0.xy)%s);\n", reg, dst_mask);
1664 }
1665
1666 /** Process the WINED3DSIO_TEXM3X3TEX instruction in GLSL
1667  * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculated coordinates */
1668 void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1669     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1670     glsl_src_param_t src0_param;
1671     char dst_mask[6];
1672     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1673     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1674     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
1675     DWORD sampler_type = arg->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
1676     glsl_sample_function_t sample_function;
1677
1678     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1679     shader_addline(arg->buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
1680
1681     shader_glsl_append_dst(arg->buffer, arg);
1682     shader_glsl_get_write_mask(arg->dst, dst_mask);
1683     shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function);
1684
1685     /* Sample the texture using the calculated coordinates */
1686     shader_addline(arg->buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
1687
1688     current_state->current_row = 0;
1689 }
1690
1691 /** Process the WINED3DSIO_TEXM3X3 instruction in GLSL
1692  * Perform the 3rd row of a 3x3 matrix multiply */
1693 void pshader_glsl_texm3x3(SHADER_OPCODE_ARG* arg) {
1694     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1695     glsl_src_param_t src0_param;
1696     char dst_mask[6];
1697     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1698     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1699     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
1700
1701     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1702
1703     shader_glsl_append_dst(arg->buffer, arg);
1704     shader_glsl_get_write_mask(arg->dst, dst_mask);
1705     shader_addline(arg->buffer, "vec4(tmp.xy, dot(T%u.xyz, %s), 1.0)%s);\n", reg, src0_param.param_str, dst_mask);
1706
1707     current_state->current_row = 0;
1708 }
1709
1710 /** Process the WINED3DSIO_TEXM3X3SPEC instruction in GLSL 
1711  * Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */
1712 void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1713
1714     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1715     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1716     glsl_src_param_t src0_param;
1717     glsl_src_param_t src1_param;
1718     char dst_mask[6];
1719     SHADER_BUFFER* buffer = arg->buffer;
1720     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
1721     DWORD stype = arg->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
1722     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1723     glsl_sample_function_t sample_function;
1724
1725     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1726     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], src_mask, &src1_param);
1727
1728     /* Perform the last matrix multiply operation */
1729     shader_addline(buffer, "tmp0.z = dot(T%u.xyz, %s);\n", reg, src0_param.param_str);
1730
1731     /* Calculate reflection vector, 2*(tmp0.src1)*tmp0-src1
1732      * This is equivalent to reflect(-src1, tmp0); */
1733     shader_addline(buffer, "tmp0.xyz = reflect(-(%s), tmp0.xyz);\n", src1_param.param_str);
1734
1735     shader_glsl_append_dst(buffer, arg);
1736     shader_glsl_get_write_mask(arg->dst, dst_mask);
1737     shader_glsl_get_sample_function(stype, FALSE, &sample_function);
1738
1739     /* Sample the texture */
1740     shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
1741
1742     current_state->current_row = 0;
1743 }
1744
1745 /** Process the WINED3DSIO_TEXM3X3VSPEC instruction in GLSL 
1746  * Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */
1747 void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1748
1749     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1750     DWORD reg = arg->dst & WINED3DSP_REGNUM_MASK;
1751     SHADER_BUFFER* buffer = arg->buffer;
1752     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
1753     glsl_src_param_t src0_param;
1754     char dst_mask[6];
1755     DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
1756     DWORD sampler_type = arg->reg_maps->samplers[reg] & WINED3DSP_TEXTURETYPE_MASK;
1757     glsl_sample_function_t sample_function;
1758
1759     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
1760
1761     /* Perform the last matrix multiply operation */
1762     shader_addline(buffer, "tmp0.z = dot(vec3(T%u), vec3(%s));\n", reg, src0_param.param_str);
1763
1764     /* Construct the eye-ray vector from w coordinates */
1765     shader_addline(buffer, "tmp1.xyz = normalize(vec3(gl_TexCoord[%u].w, gl_TexCoord[%u].w, gl_TexCoord[%u].w));\n",
1766             current_state->texcoord_w[0], current_state->texcoord_w[1], reg);
1767
1768     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(tmp0.tmp1)*tmp0-tmp1
1769      * This is equivalent to reflect(-tmp1, tmp0); */
1770     shader_addline(buffer, "tmp0.xyz = reflect(-tmp1.xyz, tmp0.xyz);\n");
1771
1772     shader_glsl_append_dst(buffer, arg);
1773     shader_glsl_get_write_mask(arg->dst, dst_mask);
1774     shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function);
1775
1776     /* Sample the texture using the calculated coordinates */
1777     shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
1778
1779     current_state->current_row = 0;
1780 }
1781
1782 /** Process the WINED3DSIO_TEXBEM instruction in GLSL.
1783  * Apply a fake bump map transform.
1784  * FIXME: Should apply the BUMPMAPENV matrix.  For now, just sample the texture */
1785 void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
1786
1787     DWORD reg1 = arg->dst & WINED3DSP_REGNUM_MASK;
1788     DWORD reg2 = arg->src[0] & WINED3DSP_REGNUM_MASK;
1789
1790     FIXME("Not applying the BUMPMAPENV matrix for pixel shader instruction texbem.\n");
1791     shader_addline(arg->buffer, "T%u = texture2D(Psampler%u, gl_TexCoord[%u].xy + T%u.xy);\n",
1792             reg1, reg1, reg1, reg2);
1793 }
1794
1795 /** Process the WINED3DSIO_TEXREG2AR instruction in GLSL
1796  * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
1797 void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) {
1798     glsl_src_param_t src0_param;
1799     DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
1800     char dst_mask[6];
1801
1802     shader_glsl_append_dst(arg->buffer, arg);
1803     shader_glsl_get_write_mask(arg->dst, dst_mask);
1804     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
1805
1806     shader_addline(arg->buffer, "texture2D(Psampler%u, %s.wx)%s);\n", sampler_idx, src0_param.reg_name, dst_mask);
1807 }
1808
1809 /** Process the WINED3DSIO_TEXREG2GB instruction in GLSL
1810  * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */
1811 void pshader_glsl_texreg2gb(SHADER_OPCODE_ARG* arg) {
1812     glsl_src_param_t src0_param;
1813     DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
1814     char dst_mask[6];
1815
1816     shader_glsl_append_dst(arg->buffer, arg);
1817     shader_glsl_get_write_mask(arg->dst, dst_mask);
1818     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_ALL, &src0_param);
1819
1820     shader_addline(arg->buffer, "texture2D(Psampler%u, %s.yz)%s);\n", sampler_idx, src0_param.reg_name, dst_mask);
1821 }
1822
1823 /** Process the WINED3DSIO_TEXREG2RGB instruction in GLSL
1824  * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */
1825 void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg) {
1826     glsl_src_param_t src0_param;
1827     char dst_mask[6];
1828     DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
1829     DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
1830     glsl_sample_function_t sample_function;
1831
1832     shader_glsl_append_dst(arg->buffer, arg);
1833     shader_glsl_get_write_mask(arg->dst, dst_mask);
1834     shader_glsl_get_sample_function(sampler_type, FALSE, &sample_function);
1835     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &src0_param);
1836
1837     shader_addline(arg->buffer, "%s(Psampler%u, %s)%s);\n", sample_function.name, sampler_idx, src0_param.param_str, dst_mask);
1838 }
1839
1840 /** Process the WINED3DSIO_TEXKILL instruction in GLSL.
1841  * If any of the first 3 components are < 0, discard this pixel */
1842 void pshader_glsl_texkill(SHADER_OPCODE_ARG* arg) {
1843     glsl_dst_param_t dst_param;
1844
1845     shader_glsl_add_dst_param(arg, arg->dst, 0, &dst_param);
1846     shader_addline(arg->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_param.reg_name);
1847 }
1848
1849 /** Process the WINED3DSIO_DP2ADD instruction in GLSL.
1850  * dst = dot2(src0, src1) + src2 */
1851 void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg) {
1852     glsl_src_param_t src0_param;
1853     glsl_src_param_t src1_param;
1854     glsl_src_param_t src2_param;
1855     DWORD write_mask;
1856     size_t mask_size;
1857
1858     write_mask = shader_glsl_append_dst(arg->buffer, arg);
1859     mask_size = shader_glsl_get_write_mask_size(write_mask);
1860
1861     shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src0_param);
1862     shader_glsl_add_src_param(arg, arg->src[1], arg->src_addr[1], WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1, &src1_param);
1863     shader_glsl_add_src_param(arg, arg->src[2], arg->src_addr[2], WINED3DSP_WRITEMASK_0, &src2_param);
1864
1865     shader_addline(arg->buffer, "dot(%s, %s) + %s);\n", src0_param.param_str, src1_param.param_str, src2_param.param_str);
1866 }
1867
1868 void pshader_glsl_input_pack(
1869    SHADER_BUFFER* buffer,
1870    semantic* semantics_in) {
1871
1872    unsigned int i;
1873
1874    for (i = 0; i < MAX_REG_INPUT; i++) {
1875
1876        DWORD usage_token = semantics_in[i].usage;
1877        DWORD register_token = semantics_in[i].reg;
1878        DWORD usage, usage_idx;
1879        char reg_mask[6];
1880
1881        /* Uninitialized */
1882        if (!usage_token) continue;
1883        usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
1884        usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
1885        shader_glsl_get_write_mask(register_token, reg_mask);
1886
1887        switch(usage) {
1888
1889            case D3DDECLUSAGE_COLOR:
1890                if (usage_idx == 0)
1891                    shader_addline(buffer, "IN%u%s = vec4(gl_Color)%s;\n",
1892                        i, reg_mask, reg_mask);
1893                else if (usage_idx == 1)
1894                    shader_addline(buffer, "IN%u%s = vec4(gl_SecondaryColor)%s;\n",
1895                        i, reg_mask, reg_mask);
1896                else
1897                    shader_addline(buffer, "IN%u%s = vec4(unsupported_color_input)%s;\n",
1898                        i, reg_mask, reg_mask);
1899                break;
1900
1901            case D3DDECLUSAGE_TEXCOORD:
1902                shader_addline(buffer, "IN%u%s = vec4(gl_TexCoord[%u])%s;\n",
1903                    i, reg_mask, usage_idx, reg_mask );
1904                break;
1905
1906            case D3DDECLUSAGE_FOG:
1907                shader_addline(buffer, "IN%u%s = vec4(gl_FogFragCoord)%s;\n",
1908                    i, reg_mask, reg_mask);
1909                break;
1910
1911            default:
1912                shader_addline(buffer, "IN%u%s = vec4(unsupported_input)%s;\n",
1913                    i, reg_mask, reg_mask);
1914         }
1915     }
1916 }
1917
1918 /*********************************************
1919  * Vertex Shader Specific Code begins here
1920  ********************************************/
1921
1922 void vshader_glsl_output_unpack(
1923    SHADER_BUFFER* buffer,
1924    semantic* semantics_out) {
1925
1926    unsigned int i;
1927
1928    for (i = 0; i < MAX_REG_OUTPUT; i++) {
1929
1930        DWORD usage_token = semantics_out[i].usage;
1931        DWORD register_token = semantics_out[i].reg;
1932        DWORD usage, usage_idx;
1933        char reg_mask[6];
1934
1935        /* Uninitialized */
1936        if (!usage_token) continue;
1937
1938        usage = (usage_token & WINED3DSP_DCL_USAGE_MASK) >> WINED3DSP_DCL_USAGE_SHIFT;
1939        usage_idx = (usage_token & WINED3DSP_DCL_USAGEINDEX_MASK) >> WINED3DSP_DCL_USAGEINDEX_SHIFT;
1940        shader_glsl_get_write_mask(register_token, reg_mask);
1941
1942        switch(usage) {
1943
1944            case D3DDECLUSAGE_COLOR:
1945                if (usage_idx == 0)
1946                    shader_addline(buffer, "gl_FrontColor%s = OUT%u%s;\n", reg_mask, i, reg_mask);
1947                else if (usage_idx == 1)
1948                    shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT%u%s;\n", reg_mask, i, reg_mask);
1949                else
1950                    shader_addline(buffer, "unsupported_color_output%s = OUT%u%s;\n", reg_mask, i, reg_mask);
1951                break;
1952
1953            case D3DDECLUSAGE_POSITION:
1954                shader_addline(buffer, "gl_Position%s = OUT%u%s;\n", reg_mask, i, reg_mask);
1955                break;
1956  
1957            case D3DDECLUSAGE_TEXCOORD:
1958                shader_addline(buffer, "gl_TexCoord[%u]%s = OUT%u%s;\n",
1959                    usage_idx, reg_mask, i, reg_mask);
1960                break;
1961
1962            case WINED3DSHADERDECLUSAGE_PSIZE:
1963                shader_addline(buffer, "gl_PointSize = OUT%u.x;\n", i);
1964                break;
1965
1966            case WINED3DSHADERDECLUSAGE_FOG:
1967                shader_addline(buffer, "gl_FogFragCoord%s = OUT%u%s;\n", reg_mask, i, reg_mask);
1968                break;
1969
1970            default:
1971                shader_addline(buffer, "unsupported_output%s = OUT%u%s;\n", reg_mask, i, reg_mask);
1972        }
1973     }
1974 }
1975
1976 /** Attach a GLSL pixel or vertex shader object to the shader program */
1977 static void attach_glsl_shader(IWineD3DDevice *iface, IWineD3DBaseShader* shader) {
1978     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1979     WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
1980     GLhandleARB shaderObj = ((IWineD3DBaseShaderImpl*)shader)->baseShader.prgId;
1981     if (This->stateBlock->glsl_program && shaderObj != 0) {
1982         TRACE("Attaching GLSL shader object %u to program %u\n", shaderObj, This->stateBlock->glsl_program->programId);
1983         GL_EXTCALL(glAttachObjectARB(This->stateBlock->glsl_program->programId, shaderObj));
1984         checkGLcall("glAttachObjectARB");
1985     }
1986 }
1987
1988 /** Sets the GLSL program ID for the given pixel and vertex shader combination.
1989  * It sets the programId on the current StateBlock (because it should be called
1990  * inside of the DrawPrimitive() part of the render loop).
1991  *
1992  * If a program for the given combination does not exist, create one, and store
1993  * the program in the list.  If it creates a program, it will link the given
1994  * objects, too.
1995  *
1996  * We keep the shader programs around on a list because linking
1997  * shader objects together is an expensive operation.  It's much
1998  * faster to loop through a list of pre-compiled & linked programs
1999  * each time that the application sets a new pixel or vertex shader
2000  * than it is to re-link them together at that time.
2001  *
2002  * The list will be deleted in IWineD3DDevice::Release().
2003  */
2004 static void set_glsl_shader_program(IWineD3DDevice *iface) {
2005     IWineD3DDeviceImpl *This               = (IWineD3DDeviceImpl *)iface;
2006     WineD3D_GL_Info *gl_info               = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
2007     IWineD3DPixelShader  *pshader          = This->stateBlock->pixelShader;
2008     IWineD3DVertexShader *vshader          = This->stateBlock->vertexShader;
2009     struct glsl_shader_prog_link *curLink  = NULL;
2010     struct glsl_shader_prog_link *newLink  = NULL;
2011     struct list *ptr                       = NULL;
2012     GLhandleARB programId                  = 0;
2013     int i;
2014     char glsl_name[8];
2015
2016     ptr = list_head( &This->glsl_shader_progs );
2017     while (ptr) {
2018         /* At least one program exists - see if it matches our ps/vs combination */
2019         curLink = LIST_ENTRY( ptr, struct glsl_shader_prog_link, entry );
2020         if (vshader == curLink->vertexShader && pshader == curLink->pixelShader) {
2021             /* Existing Program found, use it */
2022             TRACE("Found existing program (%u) for this vertex/pixel shader combination\n",
2023                    curLink->programId);
2024             This->stateBlock->glsl_program = curLink;
2025             return;
2026         }
2027         /* This isn't the entry we need - try the next one */
2028         ptr = list_next( &This->glsl_shader_progs, ptr );
2029     }
2030
2031     /* If we get to this point, then no matching program exists, so we create one */
2032     programId = GL_EXTCALL(glCreateProgramObjectARB());
2033     TRACE("Created new GLSL shader program %u\n", programId);
2034
2035     /* Allocate a new link for the list of programs */
2036     newLink = HeapAlloc(GetProcessHeap(), 0, sizeof(struct glsl_shader_prog_link));
2037     newLink->programId    = programId;
2038     This->stateBlock->glsl_program = newLink;
2039
2040     /* Attach GLSL vshader */
2041     if (NULL != vshader && This->vs_selected_mode == SHADER_GLSL) {
2042         int i;
2043         int max_attribs = 16;   /* TODO: Will this always be the case? It is at the moment... */
2044         char tmp_name[10];
2045
2046         TRACE("Attaching vertex shader to GLSL program\n");
2047         attach_glsl_shader(iface, (IWineD3DBaseShader*)vshader);
2048
2049         /* Bind vertex attributes to a corresponding index number to match
2050          * the same index numbers as ARB_vertex_programs (makes loading
2051          * vertex attributes simpler).  With this method, we can use the
2052          * exact same code to load the attributes later for both ARB and
2053          * GLSL shaders.
2054          *
2055          * We have to do this here because we need to know the Program ID
2056          * in order to make the bindings work, and it has to be done prior
2057          * to linking the GLSL program. */
2058         for (i = 0; i < max_attribs; ++i) {
2059              snprintf(tmp_name, sizeof(tmp_name), "attrib%i", i);
2060              GL_EXTCALL(glBindAttribLocationARB(programId, i, tmp_name));
2061         }
2062         checkGLcall("glBindAttribLocationARB");
2063         newLink->vertexShader = vshader;
2064     }
2065
2066     /* Attach GLSL pshader */
2067     if (NULL != pshader && This->ps_selected_mode == SHADER_GLSL) {
2068         TRACE("Attaching pixel shader to GLSL program\n");
2069         attach_glsl_shader(iface, (IWineD3DBaseShader*)pshader);
2070         newLink->pixelShader = pshader;
2071     }
2072
2073     /* Link the program */
2074     TRACE("Linking GLSL shader program %u\n", programId);
2075     GL_EXTCALL(glLinkProgramARB(programId));
2076     print_glsl_info_log(&GLINFO_LOCATION, programId);
2077     list_add_head( &This->glsl_shader_progs, &newLink->entry);
2078
2079     newLink->vuniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(vshader_constantsF));
2080     for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i) {
2081         snprintf(glsl_name, sizeof(glsl_name), "VC[%i]", i);
2082         newLink->vuniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
2083     }
2084     newLink->puniformF_locations = HeapAlloc(GetProcessHeap(), 0, sizeof(GLhandleARB) * GL_LIMITS(pshader_constantsF));
2085     for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i) {
2086         snprintf(glsl_name, sizeof(glsl_name), "PC[%i]", i);
2087         newLink->puniformF_locations[i] = GL_EXTCALL(glGetUniformLocationARB(programId, glsl_name));
2088     }
2089
2090     return;
2091 }
2092
2093 static GLhandleARB create_glsl_blt_shader(WineD3D_GL_Info *gl_info) {
2094     GLhandleARB program_id;
2095     GLhandleARB vshader_id, pshader_id;
2096     const char *blt_vshader[] = {
2097         "void main(void)\n"
2098         "{\n"
2099         "    gl_Position = gl_Vertex;\n"
2100         "    gl_FrontColor = vec4(1.0);\n"
2101         "    gl_TexCoord[0].x = (gl_Vertex.x * 0.5) + 0.5;\n"
2102         "    gl_TexCoord[0].y = (-gl_Vertex.y * 0.5) + 0.5;\n"
2103         "}\n"
2104     };
2105
2106     const char *blt_pshader[] = {
2107         "uniform sampler2D sampler;\n"
2108         "void main(void)\n"
2109         "{\n"
2110         "    gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n"
2111         "}\n"
2112     };
2113
2114     vshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
2115     GL_EXTCALL(glShaderSourceARB(vshader_id, 1, blt_vshader, NULL));
2116     GL_EXTCALL(glCompileShaderARB(vshader_id));
2117
2118     pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
2119     GL_EXTCALL(glShaderSourceARB(pshader_id, 1, blt_pshader, NULL));
2120     GL_EXTCALL(glCompileShaderARB(pshader_id));
2121
2122     program_id = GL_EXTCALL(glCreateProgramObjectARB());
2123     GL_EXTCALL(glAttachObjectARB(program_id, vshader_id));
2124     GL_EXTCALL(glAttachObjectARB(program_id, pshader_id));
2125     GL_EXTCALL(glLinkProgramARB(program_id));
2126
2127     print_glsl_info_log(&GLINFO_LOCATION, program_id);
2128
2129     return program_id;
2130 }
2131
2132 static void shader_glsl_select(IWineD3DDevice *iface, BOOL usePS, BOOL useVS) {
2133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2134     WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
2135     GLhandleARB program_id = 0;
2136
2137     if (useVS || usePS) set_glsl_shader_program(iface);
2138     else This->stateBlock->glsl_program = NULL;
2139
2140     program_id = This->stateBlock->glsl_program ? This->stateBlock->glsl_program->programId : 0;
2141     if (program_id) TRACE("Using GLSL program %u\n", program_id);
2142     GL_EXTCALL(glUseProgramObjectARB(program_id));
2143     checkGLcall("glUseProgramObjectARB");
2144 }
2145
2146 static void shader_glsl_select_depth_blt(IWineD3DDevice *iface) {
2147     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2148     WineD3D_GL_Info *gl_info = &((IWineD3DImpl *)(This->wineD3D))->gl_info;
2149     static GLhandleARB program_id = 0;
2150     static GLhandleARB loc = -1;
2151
2152     if (!program_id) {
2153         program_id = create_glsl_blt_shader(gl_info);
2154         loc = GL_EXTCALL(glGetUniformLocationARB(program_id, "sampler"));
2155     }
2156
2157     GL_EXTCALL(glUseProgramObjectARB(program_id));
2158     GL_EXTCALL(glUniform1iARB(loc, 0));
2159 }
2160
2161 static void shader_glsl_cleanup(BOOL usePS, BOOL useVS) {
2162     /* Nothing to do */
2163 }
2164
2165 const shader_backend_t glsl_shader_backend = {
2166     &shader_glsl_select,
2167     &shader_glsl_select_depth_blt,
2168     &shader_glsl_load_constants,
2169     &shader_glsl_cleanup
2170 };