crypt32: Implement file stores.
[wine] / dlls / wined3d / glsl_shader.c
1 /*
2  * GLSL pixel and vertex shader implementation
3  *
4  * Copyright 2006 Jason Green 
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22 #include <stdio.h>
23 #include "wined3d_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
26
27 #define GLINFO_LOCATION      (*gl_info)
28
29 /** Prints the GLSL info log which will contain error messages if they exist */
30 void print_glsl_info_log(WineD3D_GL_Info *gl_info, GLhandleARB obj) {
31     
32     int infologLength = 0;
33     char *infoLog;
34
35     GL_EXTCALL(glGetObjectParameterivARB(obj,
36                GL_OBJECT_INFO_LOG_LENGTH_ARB,
37                &infologLength));
38
39     /* A size of 1 is just a null-terminated string, so the log should be bigger than
40      * that if there are errors. */
41     if (infologLength > 1)
42     {
43         infoLog = (char *)HeapAlloc(GetProcessHeap(), 0, infologLength);
44         GL_EXTCALL(glGetInfoLogARB(obj, infologLength, NULL, infoLog));
45         FIXME("Error received from GLSL shader #%u: %s\n", obj, debugstr_a(infoLog));
46         HeapFree(GetProcessHeap(), 0, infoLog);
47     }
48 }
49
50 /**
51  * Loads (pixel shader) samplers
52  */
53 void shader_glsl_load_psamplers(
54     WineD3D_GL_Info *gl_info,
55     IWineD3DStateBlock* iface) {
56
57     IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
58     GLhandleARB programId = stateBlock->shaderPrgId;
59     GLhandleARB name_loc;
60     int i;
61     char sampler_name[20];
62
63     for (i=0; i< GL_LIMITS(samplers); ++i) {
64         if (stateBlock->textures[i] != NULL) {
65            snprintf(sampler_name, sizeof(sampler_name), "Psampler%d", i);
66            name_loc = GL_EXTCALL(glGetUniformLocationARB(programId, sampler_name));
67            if (name_loc != -1) {
68                TRACE_(d3d_shader)("Loading %s for texture %d\n", sampler_name, i);
69                GL_EXTCALL(glUniform1iARB(name_loc, i));
70                checkGLcall("glUniform1iARB");
71            }
72         }
73     }
74 }
75
76 /** 
77  * Loads floating point constants (aka uniforms) into the currently set GLSL program.
78  * When @constants_set == NULL, it will load all the constants.
79  */
80 void shader_glsl_load_constantsF(
81     IWineD3DBaseShaderImpl* This,
82     WineD3D_GL_Info *gl_info,
83     GLhandleARB programId,
84     unsigned max_constants,
85     float* constants,
86     BOOL* constants_set) {
87         
88     GLhandleARB tmp_loc;
89     int i;
90     char tmp_name[7];
91     char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
92     const char* prefix = is_pshader? "PC":"VC";
93     struct list* ptr;
94
95     for (i=0; i<max_constants; ++i) {
96         if (NULL == constants_set || constants_set[i]) {
97
98             TRACE("Loading constants %i: %f, %f, %f, %f\n", i,
99                   constants[i * sizeof(float) + 0], constants[i * sizeof(float) + 1],
100                   constants[i * sizeof(float) + 2], constants[i * sizeof(float) + 3]);
101
102             /* TODO: Benchmark and see if it would be beneficial to store the 
103              * locations of the constants to avoid looking up each time */
104             snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
105             tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
106             if (tmp_loc != -1) {
107                 /* We found this uniform name in the program - go ahead and send the data */
108                 GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, &constants[i * sizeof(float)]));
109                 checkGLcall("glUniform4fvARB");
110             }
111         }
112     }
113
114     /* Load immediate constants */
115     ptr = list_head(&This->baseShader.constantsF);
116     while (ptr) {
117         local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
118         unsigned int idx = lconst->idx;
119         GLfloat* values = (GLfloat*) lconst->value;
120
121         TRACE("Loading local constants %i: %f, %f, %f, %f\n", idx,
122             values[0], values[1], values[2], values[3]);
123
124         snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
125         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
126         if (tmp_loc != -1) {
127             /* We found this uniform name in the program - go ahead and send the data */
128             GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, values));
129             checkGLcall("glUniform4fvARB");
130         }
131         ptr = list_next(&This->baseShader.constantsF, ptr);
132     }
133 }
134
135 /** 
136  * Loads integer constants (aka uniforms) into the currently set GLSL program.
137  * When @constants_set == NULL, it will load all the constants.
138  */
139 void shader_glsl_load_constantsI(
140     IWineD3DBaseShaderImpl* This,
141     WineD3D_GL_Info *gl_info,
142     GLhandleARB programId,
143     unsigned max_constants,
144     int* constants,
145     BOOL* constants_set) {
146     
147     GLhandleARB tmp_loc;
148     int i;
149     char tmp_name[7];
150     char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
151     const char* prefix = is_pshader? "PI":"VI";
152     struct list* ptr;
153
154     for (i=0; i<max_constants; ++i) {
155         if (NULL == constants_set || constants_set[i]) {
156
157             TRACE("Loading constants %i: %i, %i, %i, %i\n",
158                   i, constants[i*4], constants[i*4+1], constants[i*4+2], constants[i*4+3]);
159
160             /* TODO: Benchmark and see if it would be beneficial to store the 
161              * locations of the constants to avoid looking up each time */
162             snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
163             tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
164             if (tmp_loc != -1) {
165                 /* We found this uniform name in the program - go ahead and send the data */
166                 GL_EXTCALL(glUniform4ivARB(tmp_loc, 1, &constants[i*4]));
167                 checkGLcall("glUniform4ivARB");
168             }
169         }
170     }
171
172     /* Load immediate constants */
173     ptr = list_head(&This->baseShader.constantsI);
174     while (ptr) {
175         local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
176         unsigned int idx = lconst->idx;
177         GLint* values = (GLint*) lconst->value;
178
179         TRACE("Loading local constants %i: %i, %i, %i, %i\n", idx,
180             values[0], values[1], values[2], values[3]);
181
182         snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
183         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
184         if (tmp_loc != -1) {
185             /* We found this uniform name in the program - go ahead and send the data */
186             GL_EXTCALL(glUniform4ivARB(tmp_loc, 1, values));
187             checkGLcall("glUniform4ivARB");
188         }
189         ptr = list_next(&This->baseShader.constantsI, ptr);
190     }
191 }
192
193 /** 
194  * Loads boolean constants (aka uniforms) into the currently set GLSL program.
195  * When @constants_set == NULL, it will load all the constants.
196  */
197 void shader_glsl_load_constantsB(
198     IWineD3DBaseShaderImpl* This,
199     WineD3D_GL_Info *gl_info,
200     GLhandleARB programId,
201     unsigned max_constants,
202     BOOL* constants,
203     BOOL* constants_set) {
204     
205     GLhandleARB tmp_loc;
206     int i;
207     char tmp_name[7];
208     char is_pshader = shader_is_pshader_version(This->baseShader.hex_version);
209     const char* prefix = is_pshader? "PB":"VB";
210     struct list* ptr;
211
212     for (i=0; i<max_constants; ++i) {
213         if (NULL == constants_set || constants_set[i]) {
214
215             TRACE("Loading constants %i: %i;\n", i, constants[i*4]);
216
217             /* TODO: Benchmark and see if it would be beneficial to store the 
218              * locations of the constants to avoid looking up each time */
219             snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, i);
220             tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
221             if (tmp_loc != -1) {
222                 /* We found this uniform name in the program - go ahead and send the data */
223                 GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, &constants[i*4]));
224                 checkGLcall("glUniform1ivARB");
225             }
226         }
227     }
228
229     /* Load immediate constants */
230     ptr = list_head(&This->baseShader.constantsB);
231     while (ptr) {
232         local_constant* lconst = LIST_ENTRY(ptr, struct local_constant, entry);
233         unsigned int idx = lconst->idx;
234         GLint* values = (GLint*) lconst->value;
235
236         TRACE("Loading local constants %i: %i\n", idx, values[0]);
237
238         snprintf(tmp_name, sizeof(tmp_name), "%s[%i]", prefix, idx);
239         tmp_loc = GL_EXTCALL(glGetUniformLocationARB(programId, tmp_name));
240         if (tmp_loc != -1) {
241             /* We found this uniform name in the program - go ahead and send the data */
242             GL_EXTCALL(glUniform1ivARB(tmp_loc, 1, values));
243             checkGLcall("glUniform1ivARB");
244         }
245         ptr = list_next(&This->baseShader.constantsB, ptr);
246     }
247 }
248
249
250
251 /**
252  * Loads the app-supplied constants into the currently set GLSL program.
253  */
254 void shader_glsl_load_constants(
255     IWineD3DStateBlock* iface,
256     char usePixelShader,
257     char useVertexShader) {
258     
259     IWineD3DStateBlockImpl* stateBlock = (IWineD3DStateBlockImpl*) iface;
260     WineD3D_GL_Info *gl_info = &((IWineD3DImpl*)stateBlock->wineD3DDevice->wineD3D)->gl_info;
261     GLhandleARB programId = stateBlock->shaderPrgId;
262     
263     if (programId == 0) {
264         /* No GLSL program set - nothing to do. */
265         return;
266     }
267
268     if (useVertexShader) {
269         IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
270         IWineD3DVertexShaderImpl* vshader_impl = (IWineD3DVertexShaderImpl*) vshader;
271
272         IWineD3DVertexDeclarationImpl* vertexDeclaration =
273             (IWineD3DVertexDeclarationImpl*) vshader_impl->vertexDeclaration;
274
275         if (NULL != vertexDeclaration && NULL != vertexDeclaration->constants) {
276             /* Load DirectX 8 float constants/uniforms for vertex shader */
277             shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
278                                         vertexDeclaration->constants, NULL);
279         }
280
281         /* Load DirectX 9 float constants/uniforms for vertex shader */
282         shader_glsl_load_constantsF(vshader, gl_info, programId, GL_LIMITS(vshader_constantsF),
283                                     stateBlock->vertexShaderConstantF, 
284                                     stateBlock->set.vertexShaderConstantsF);
285
286         /* Load DirectX 9 integer constants/uniforms for vertex shader */
287         shader_glsl_load_constantsI(vshader, gl_info, programId, MAX_CONST_I,
288                                     stateBlock->vertexShaderConstantI,
289                                     stateBlock->set.vertexShaderConstantsI);
290
291         /* Load DirectX 9 boolean constants/uniforms for vertex shader */
292         shader_glsl_load_constantsB(vshader, gl_info, programId, MAX_CONST_B,
293                                     stateBlock->vertexShaderConstantB,
294                                     stateBlock->set.vertexShaderConstantsB);
295     }
296
297     if (usePixelShader) {
298
299         IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
300
301         /* Load pixel shader samplers */
302         shader_glsl_load_psamplers(gl_info, iface);
303
304         /* Load DirectX 9 float constants/uniforms for pixel shader */
305         shader_glsl_load_constantsF(pshader, gl_info, programId, GL_LIMITS(pshader_constantsF),
306                                     stateBlock->pixelShaderConstantF,
307                                     stateBlock->set.pixelShaderConstantsF);
308
309         /* Load DirectX 9 integer constants/uniforms for pixel shader */
310         shader_glsl_load_constantsI(pshader, gl_info, programId, MAX_CONST_I,
311                                     stateBlock->pixelShaderConstantI, 
312                                     stateBlock->set.pixelShaderConstantsI);
313         
314         /* Load DirectX 9 boolean constants/uniforms for pixel shader */
315         shader_glsl_load_constantsB(pshader, gl_info, programId, MAX_CONST_B,
316                                     stateBlock->pixelShaderConstantB, 
317                                     stateBlock->set.pixelShaderConstantsB);
318     }
319 }
320
321 /** Generate the variable & register declarations for the GLSL output target */
322 void shader_generate_glsl_declarations(
323     IWineD3DBaseShader *iface,
324     shader_reg_maps* reg_maps,
325     SHADER_BUFFER* buffer,
326     WineD3D_GL_Info* gl_info) {
327
328     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
329     int i;
330
331     /* There are some minor differences between pixel and vertex shaders */
332     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
333     char prefix = pshader ? 'P' : 'V';
334
335     /* Prototype the subroutines */
336     for (i = 0; i < This->baseShader.limits.label; i++) {
337         if (reg_maps->labels[i])
338             shader_addline(buffer, "void subroutine%lu();\n", i);
339     }
340
341     /* Declare the constants (aka uniforms) */
342     if (This->baseShader.limits.constant_float > 0) {
343         unsigned max_constantsF = min(This->baseShader.limits.constant_float, 
344                 (pshader ? GL_LIMITS(pshader_constantsF) : GL_LIMITS(vshader_constantsF)));
345         shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, max_constantsF);
346     }
347
348     if (This->baseShader.limits.constant_int > 0)
349         shader_addline(buffer, "uniform ivec4 %cI[%u];\n", prefix, This->baseShader.limits.constant_int);
350
351     if (This->baseShader.limits.constant_bool > 0)
352         shader_addline(buffer, "uniform bool %cB[%u];\n", prefix, This->baseShader.limits.constant_bool);
353
354     /* Declare texture samplers */ 
355     for (i = 0; i < This->baseShader.limits.sampler; i++) {
356         if (reg_maps->samplers[i]) {
357
358             DWORD stype = reg_maps->samplers[i] & D3DSP_TEXTURETYPE_MASK;
359             switch (stype) {
360
361                 case D3DSTT_2D:
362                     shader_addline(buffer, "uniform sampler2D %csampler%lu;\n", prefix, i);
363                     break;
364                 case D3DSTT_CUBE:
365                     shader_addline(buffer, "uniform samplerCube %csampler%lu;\n", prefix, i);
366                     break;
367                 case D3DSTT_VOLUME:
368                     shader_addline(buffer, "uniform sampler3D %csampler%lu;\n", prefix, i);
369                     break;
370                 default:
371                     shader_addline(buffer, "uniform unsupported_sampler %csampler%lu;\n", prefix, i);
372                     FIXME("Unrecognized sampler type: %#lx\n", stype);
373                     break;
374             }
375         }
376     }
377     
378     /* Declare address variables */
379     for (i = 0; i < This->baseShader.limits.address; i++) {
380         if (reg_maps->address[i])
381             shader_addline(buffer, "ivec4 A%ld;\n", i);
382     }
383
384     /* Declare texture coordinate temporaries and initialize them */
385     for (i = 0; i < This->baseShader.limits.texcoord; i++) {
386         if (reg_maps->texcoord[i]) 
387             shader_addline(buffer, "vec4 T%lu = gl_TexCoord[%lu];\n", i, i);
388     }
389
390     /* Declare input register temporaries */
391     for (i=0; i < This->baseShader.limits.packed_input; i++) {
392         if (reg_maps->packed_input[i])
393             shader_addline(buffer, "vec4 IN%lu;\n", i);
394     }
395
396     /* Declare output register temporaries */
397     for (i = 0; i < This->baseShader.limits.packed_output; i++) {
398         if (reg_maps->packed_output[i])
399             shader_addline(buffer, "vec4 OUT%lu;\n", i);
400     }
401
402     /* Declare temporary variables */
403     for(i = 0; i < This->baseShader.limits.temporary; i++) {
404         if (reg_maps->temporary[i])
405             shader_addline(buffer, "vec4 R%lu;\n", i);
406     }
407
408     /* Declare attributes */
409     for (i = 0; i < This->baseShader.limits.attributes; i++) {
410         if (reg_maps->attributes[i])
411             shader_addline(buffer, "attribute vec4 attrib%i;\n", i);
412     }
413
414     /* Declare loop register aL */
415     if (reg_maps->loop) {
416         shader_addline(buffer, "int aL;\n");
417         shader_addline(buffer, "int tmpInt;\n");
418     }
419     
420     /* Temporary variables for matrix operations */
421     shader_addline(buffer, "vec4 tmp0;\n");
422     shader_addline(buffer, "vec4 tmp1;\n");
423
424     /* Start the main program */
425     shader_addline(buffer, "void main() {\n");
426 }
427
428 /*****************************************************************************
429  * Functions to generate GLSL strings from DirectX Shader bytecode begin here.
430  *
431  * For more information, see http://wiki.winehq.org/DirectX-Shaders
432  ****************************************************************************/
433
434 /* Prototypes */
435 static void shader_glsl_add_param(
436     SHADER_OPCODE_ARG* arg,
437     const DWORD param,
438     const DWORD addr_token,
439     BOOL is_input,
440     char *reg_name,
441     char *reg_mask,
442     char *out_str);
443
444 /** Used for opcode modifiers - They multiply the result by the specified amount */
445 static const char* shift_glsl_tab[] = {
446     "",           /*  0 (none) */ 
447     "2.0 * ",     /*  1 (x2)   */ 
448     "4.0 * ",     /*  2 (x4)   */ 
449     "8.0 * ",     /*  3 (x8)   */ 
450     "16.0 * ",    /*  4 (x16)  */ 
451     "32.0 * ",    /*  5 (x32)  */ 
452     "",           /*  6 (x64)  */ 
453     "",           /*  7 (x128) */ 
454     "",           /*  8 (d256) */ 
455     "",           /*  9 (d128) */ 
456     "",           /* 10 (d64)  */ 
457     "",           /* 11 (d32)  */ 
458     "0.0625 * ",  /* 12 (d16)  */ 
459     "0.125 * ",   /* 13 (d8)   */ 
460     "0.25 * ",    /* 14 (d4)   */ 
461     "0.5 * "      /* 15 (d2)   */ 
462 };
463
464 /** Print the beginning of the generated GLSL string. example: "reg_name.xyzw = vec4("
465  * Will also change the reg_mask if necessary (not all register types are equal in DX vs GL)  */
466 static void shader_glsl_add_dst(DWORD param, const char* reg_name, char* reg_mask, char* outStr) {
467
468     int shift = (param & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
469     char cast[6];
470     
471     if ((shader_get_regtype(param) == D3DSPR_RASTOUT)
472          && ((param & D3DSP_REGNUM_MASK) != 0)) {
473         /* gl_FogFragCoord or glPointSize - both floats */
474         strcpy(cast, "float");
475         strcpy(reg_mask, "");
476
477     } else if (reg_name[0] == 'A') {
478         /* Address register for vertex shaders (ivec4) */
479         strcpy(cast, "ivec4");
480         
481     } else {
482         /* Everything else should be a 4 component float vector */
483         strcpy(cast, "vec4");
484     }
485     
486     sprintf(outStr, "%s%s = %s%s(", reg_name, reg_mask, shift_glsl_tab[shift], cast); 
487 }
488
489 /* Generate a GLSL parameter that does the input modifier computation and return the input register/mask to use */
490 static void shader_glsl_gen_modifier (
491     const DWORD instr,
492     const char *in_reg,
493     const char *in_regswizzle,
494     char *out_str) {
495
496     out_str[0] = 0;
497     
498     if (instr == D3DSIO_TEXKILL)
499         return;
500
501     switch (instr & D3DSP_SRCMOD_MASK) {
502     case D3DSPSM_NONE:
503         sprintf(out_str, "%s%s", in_reg, in_regswizzle);
504         break;
505     case D3DSPSM_NEG:
506         sprintf(out_str, "-%s%s", in_reg, in_regswizzle);
507         break;
508     case D3DSPSM_NOT:
509         sprintf(out_str, "!%s%s", in_reg, in_regswizzle);
510         break;
511     case D3DSPSM_BIAS:
512         sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
513         break;
514     case D3DSPSM_BIASNEG:
515         sprintf(out_str, "-(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
516         break;
517     case D3DSPSM_SIGN:
518         sprintf(out_str, "(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
519         break;
520     case D3DSPSM_SIGNNEG:
521         sprintf(out_str, "-(2.0 * (%s%s - 0.5))", in_reg, in_regswizzle);
522         break;
523     case D3DSPSM_COMP:
524         sprintf(out_str, "(1.0 - %s%s)", in_reg, in_regswizzle);
525         break;
526     case D3DSPSM_X2:
527         sprintf(out_str, "(2.0 * %s%s)", in_reg, in_regswizzle);
528         break;
529     case D3DSPSM_X2NEG:
530         sprintf(out_str, "-(2.0 * %s%s)", in_reg, in_regswizzle);
531         break;
532     case D3DSPSM_DZ:    /* reg1_db = { reg1.r/b, reg1.g/b, ...}  The g & a components are undefined, so we'll leave them alone */
533         sprintf(out_str, "vec4(%s.r / %s.b, %s.g / %s.b, %s.b, %s.a)", in_reg, in_reg, in_reg, in_reg, in_reg, in_reg);
534         break;
535     case D3DSPSM_DW:
536         sprintf(out_str, "vec4(%s.r / %s.a, %s.g / %s.a, %s.b, %s.a)", in_reg, in_reg, in_reg, in_reg, in_reg, in_reg);
537         break;
538     case D3DSPSM_ABS:
539         sprintf(out_str, "abs(%s%s)", in_reg, in_regswizzle);
540         break;
541     case D3DSPSM_ABSNEG:
542         sprintf(out_str, "-abs(%s%s)", in_reg, in_regswizzle);
543         break;
544     default:
545         FIXME("Unhandled modifier %lu\n", (instr & D3DSP_SRCMOD_MASK));
546         sprintf(out_str, "%s%s", in_reg, in_regswizzle);
547     }
548 }
549
550 /** Writes the GLSL variable name that corresponds to the register that the
551  * DX opcode parameter is trying to access */
552 static void shader_glsl_get_register_name(
553     const DWORD param,
554     const DWORD addr_token,
555     char* regstr,
556     BOOL* is_color,
557     SHADER_OPCODE_ARG* arg) {
558
559     /* oPos, oFog and oPts in D3D */
560     const char* hwrastout_reg_names[] = { "gl_Position", "gl_FogFragCoord", "gl_PointSize" };
561
562     DWORD reg = param & D3DSP_REGNUM_MASK;
563     DWORD regtype = shader_get_regtype(param);
564     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) arg->shader;
565     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
566     char tmpStr[50];
567
568     *is_color = FALSE;   
569  
570     switch (regtype) {
571     case D3DSPR_TEMP:
572         sprintf(tmpStr, "R%lu", reg);
573     break;
574     case D3DSPR_INPUT:
575         if (pshader) {
576             /* Pixel shaders >= 3.0 */
577             if (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3)
578                 sprintf(tmpStr, "IN%lu", reg);
579              else {
580                 if (reg==0)
581                     strcpy(tmpStr, "gl_Color");
582                 else
583                     strcpy(tmpStr, "gl_SecondaryColor");
584             }
585         } else {
586             if (vshader_input_is_color((IWineD3DVertexShader*) This, reg))
587                *is_color = TRUE;
588             sprintf(tmpStr, "attrib%lu", reg);
589         } 
590         break;
591     case D3DSPR_CONST:
592     {
593         const char* prefix = pshader? "PC":"VC";
594
595         /* Relative addressing */
596         if (param & D3DVS_ADDRMODE_RELATIVE) {
597
598            /* Relative addressing on shaders 2.0+ have a relative address token, 
599             * prior to that, it was hard-coded as "A0.x" because there's only 1 register */
600            if (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)  {
601                char relStr[100], relReg[50], relMask[6];
602                shader_glsl_add_param(arg, addr_token, 0, TRUE, relReg, relMask, relStr);
603                sprintf(tmpStr, "%s[%s + %lu]", prefix, relStr, reg);
604            } else
605                sprintf(tmpStr, "%s[A0.x + %lu]", prefix, reg);
606
607         } else
608              sprintf(tmpStr, "%s[%lu]", prefix, reg);
609
610         break;
611     }
612     case D3DSPR_CONSTINT:
613         if (pshader)
614             sprintf(tmpStr, "PI[%lu]", reg);
615         else
616             sprintf(tmpStr, "VI[%lu]", reg);
617         break;
618     case D3DSPR_CONSTBOOL:
619         if (pshader)
620             sprintf(tmpStr, "PB[%lu]", reg);
621         else
622             sprintf(tmpStr, "VB[%lu]", reg);
623         break;
624     case D3DSPR_TEXTURE: /* case D3DSPR_ADDR: */
625         if (pshader) {
626             sprintf(tmpStr, "T%lu", reg);
627         } else {
628             sprintf(tmpStr, "A%lu", reg);
629         }
630     break;
631     case D3DSPR_LOOP:
632         sprintf(tmpStr, "aL");
633     break;
634     case D3DSPR_SAMPLER:
635         if (pshader)
636             sprintf(tmpStr, "Psampler%lu", reg);
637         else
638             sprintf(tmpStr, "Vsampler%lu", reg);
639     break;
640     case D3DSPR_COLOROUT:
641         if (reg == 0)
642             sprintf(tmpStr, "gl_FragColor");
643         else {
644             /* TODO: See GL_ARB_draw_buffers */
645             FIXME("Unsupported write to render target %lu\n", reg);
646             sprintf(tmpStr, "unsupported_register");
647         }
648     break;
649     case D3DSPR_RASTOUT:
650         sprintf(tmpStr, "%s", hwrastout_reg_names[reg]);
651     break;
652     case D3DSPR_DEPTHOUT:
653         sprintf(tmpStr, "gl_FragDepth");
654     break;
655     case D3DSPR_ATTROUT:
656         if (reg == 0) {
657             sprintf(tmpStr, "gl_FrontColor");
658         } else {
659             sprintf(tmpStr, "gl_FrontSecondaryColor");
660         }
661     break;
662     case D3DSPR_TEXCRDOUT:
663         /* Vertex shaders >= 3.0: D3DSPR_OUTPUT */
664         if (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 3)
665             sprintf(tmpStr, "OUT%lu", reg);
666         else
667             sprintf(tmpStr, "gl_TexCoord[%lu]", reg);
668     break;
669     default:
670         FIXME("Unhandled register name Type(%ld)\n", regtype);
671         sprintf(tmpStr, "unrecognized_register");
672     break;
673     }
674
675     strcat(regstr, tmpStr);
676 }
677
678 /* Writes the GLSL writemask for the destination register */
679 static void shader_glsl_get_output_register_swizzle(
680     const DWORD param,
681     char *write_mask) {
682    
683     *write_mask = 0;
684     if ((param & D3DSP_WRITEMASK_ALL) != D3DSP_WRITEMASK_ALL) {
685         strcat(write_mask, ".");
686         if (param & D3DSP_WRITEMASK_0) strcat(write_mask, "x");
687         if (param & D3DSP_WRITEMASK_1) strcat(write_mask, "y");
688         if (param & D3DSP_WRITEMASK_2) strcat(write_mask, "z");
689         if (param & D3DSP_WRITEMASK_3) strcat(write_mask, "w");
690     }
691 }
692
693 static void shader_glsl_get_input_register_swizzle(
694     const DWORD param,
695     BOOL is_color,
696     char *reg_mask) {
697     
698     const char swizzle_reg_chars_color_fix[] = "zyxw";
699     const char swizzle_reg_chars[] = "xyzw";
700     const char* swizzle_regs = NULL;
701    
702     /** operand input */
703     DWORD swizzle = (param & D3DVS_SWIZZLE_MASK) >> D3DVS_SWIZZLE_SHIFT;
704     DWORD swizzle_x = swizzle & 0x03;
705     DWORD swizzle_y = (swizzle >> 2) & 0x03;
706     DWORD swizzle_z = (swizzle >> 4) & 0x03;
707     DWORD swizzle_w = (swizzle >> 6) & 0x03;
708
709     if (is_color) {
710       swizzle_regs = swizzle_reg_chars_color_fix;
711     } else {
712       swizzle_regs = swizzle_reg_chars;
713     }
714
715     /**
716      * swizzle bits fields:
717      *  WWZZYYXX
718      */
719     if ((D3DVS_NOSWIZZLE >> D3DVS_SWIZZLE_SHIFT) == swizzle) { /* D3DVS_NOSWIZZLE == 0xE4 << D3DVS_SWIZZLE_SHIFT */
720       if (is_color) {
721             sprintf(reg_mask, ".%c%c%c%c",
722                 swizzle_regs[swizzle_x],
723                 swizzle_regs[swizzle_y],
724                 swizzle_regs[swizzle_z],
725                 swizzle_regs[swizzle_w]);
726       }
727       return ;
728     }
729     if (swizzle_x == swizzle_y &&
730         swizzle_x == swizzle_z &&
731         swizzle_x == swizzle_w)
732     {
733       sprintf(reg_mask, ".%c", swizzle_regs[swizzle_x]);
734     } else {
735       sprintf(reg_mask, ".%c%c%c%c",
736               swizzle_regs[swizzle_x],
737               swizzle_regs[swizzle_y],
738               swizzle_regs[swizzle_z],
739               swizzle_regs[swizzle_w]);
740     }
741 }
742
743 /** From a given parameter token, generate the corresponding GLSL string.
744  * Also, return the actual register name and swizzle in case the 
745  * caller needs this information as well. */
746 static void shader_glsl_add_param(
747     SHADER_OPCODE_ARG* arg,
748     const DWORD param,
749     const DWORD addr_token,
750     BOOL is_input,
751     char *reg_name,
752     char *reg_mask,
753     char *out_str) {
754
755     BOOL is_color = FALSE;
756     reg_mask[0] = reg_name[0] = out_str[0] = 0;
757
758     shader_glsl_get_register_name(param, addr_token, reg_name, &is_color, arg);
759     
760     if (is_input) {
761         shader_glsl_get_input_register_swizzle(param, is_color, reg_mask);
762         shader_glsl_gen_modifier(param, reg_name, reg_mask, out_str);
763     } else {
764         shader_glsl_get_output_register_swizzle(param, reg_mask);
765         sprintf(out_str, "%s%s", reg_name, reg_mask);
766     }
767 }
768
769 /** Process GLSL instruction modifiers */
770 void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG* arg) {
771     
772     DWORD mask = arg->dst & D3DSP_DSTMOD_MASK;
773  
774     if (arg->opcode->dst_token && mask != 0) {
775         char dst_reg[50];
776         char dst_mask[6];
777         char dst_str[100];
778        
779         shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
780
781         if (mask & D3DSPDM_SATURATE) {
782             /* _SAT means to clamp the value of the register to between 0 and 1 */
783             shader_addline(arg->buffer, "%s%s = clamp(%s%s, 0.0, 1.0);\n", dst_reg, dst_mask, dst_reg, dst_mask);
784         }
785         if (mask & D3DSPDM_MSAMPCENTROID) {
786             FIXME("_centroid modifier not handled\n");
787         }
788         if (mask & D3DSPDM_PARTIALPRECISION) {
789             /* MSDN says this modifier can be safely ignored, so that's what we'll do. */
790         }
791     }
792 }
793
794 static inline const char* shader_get_comp_op(
795     const DWORD opcode) {
796
797     DWORD op = (opcode & INST_CONTROLS_MASK) >> INST_CONTROLS_SHIFT;
798     switch (op) {
799         case COMPARISON_GT: return ">";
800         case COMPARISON_EQ: return "==";
801         case COMPARISON_GE: return ">=";
802         case COMPARISON_LT: return "<";
803         case COMPARISON_NE: return "!=";
804         case COMPARISON_LE: return "<=";
805         default:
806             FIXME("Unrecognized comparison value: %lu\n", op);
807             return "(\?\?)";
808     }
809 }
810
811 /*****************************************************************************
812  * 
813  * Begin processing individual instruction opcodes
814  * 
815  ****************************************************************************/
816
817 /* Generate GLSL arithmetic functions (dst = src1 + src2) */
818 void shader_glsl_arith(SHADER_OPCODE_ARG* arg) {
819
820     CONST SHADER_OPCODE* curOpcode = arg->opcode;
821     SHADER_BUFFER* buffer = arg->buffer;
822     char tmpLine[256];
823     char dst_reg[50], src0_reg[50], src1_reg[50];
824     char dst_mask[6], src0_mask[6], src1_mask[6];
825     char dst_str[100], src0_str[100], src1_str[100];
826
827     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
828     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
829     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
830     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
831     strcat(tmpLine, "vec4(");
832     strcat(tmpLine, src0_str);
833     strcat(tmpLine, ")");
834
835     /* Determine the GLSL operator to use based on the opcode */
836     switch (curOpcode->opcode) {
837         case D3DSIO_MUL:    strcat(tmpLine, " * "); break;
838         case D3DSIO_ADD:    strcat(tmpLine, " + "); break;
839         case D3DSIO_SUB:    strcat(tmpLine, " - "); break;
840         default:
841             FIXME("Opcode %s not yet handled in GLSL\n", curOpcode->name);
842             break;
843     }
844     shader_addline(buffer, "%svec4(%s))%s;\n", tmpLine, src1_str, dst_mask);
845 }
846
847 /* Process the D3DSIO_MOV opcode using GLSL (dst = src) */
848 void shader_glsl_mov(SHADER_OPCODE_ARG* arg) {
849
850     SHADER_BUFFER* buffer = arg->buffer;
851     char tmpLine[256];
852     char dst_str[100], src0_str[100];
853     char dst_reg[50], src0_reg[50];
854     char dst_mask[6], src0_mask[6];
855
856     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
857     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
858     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
859     shader_addline(buffer, "%s%s)%s;\n", tmpLine, src0_str, dst_mask);
860 }
861
862 /* Process the dot product operators DP3 and DP4 in GLSL (dst = dot(src0, src1)) */
863 void shader_glsl_dot(SHADER_OPCODE_ARG* arg) {
864
865     CONST SHADER_OPCODE* curOpcode = arg->opcode;
866     SHADER_BUFFER* buffer = arg->buffer;
867     char tmpDest[100];
868     char dst_str[100], src0_str[100], src1_str[100];
869     char dst_reg[50], src0_reg[50], src1_reg[50];
870     char dst_mask[6], src0_mask[6], src1_mask[6];
871     char cast[6];
872
873     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
874     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
875     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
876
877     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpDest);
878  
879     /* Need to cast the src vectors to vec3 for dp3, and vec4 for dp4 */
880     if (curOpcode->opcode == D3DSIO_DP4)
881         strcpy(cast, "vec4(");
882     else
883         strcpy(cast, "vec3(");
884     
885     shader_addline(buffer, "%sdot(%s%s), %s%s)))%s;\n",
886                    tmpDest, cast, src0_str, cast, src1_str, dst_mask);
887 }
888
889 /* Map the opcode 1-to-1 to the GL code (arg->dst = instruction(src0, src1, ...) */
890 void shader_glsl_map2gl(SHADER_OPCODE_ARG* arg) {
891
892     CONST SHADER_OPCODE* curOpcode = arg->opcode;
893     SHADER_BUFFER* buffer = arg->buffer;
894     char tmpLine[256];
895     char dst_str[100], src_str[100];
896     char dst_reg[50], src_reg[50];
897     char dst_mask[6], src_mask[6];
898     unsigned i;
899     
900     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
901
902     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
903  
904     /* Determine the GLSL function to use based on the opcode */
905     /* TODO: Possibly make this a table for faster lookups */
906     switch (curOpcode->opcode) {
907             case D3DSIO_MIN:    strcat(tmpLine, "min"); break;
908             case D3DSIO_MAX:    strcat(tmpLine, "max"); break;
909             case D3DSIO_RSQ:    strcat(tmpLine, "inversesqrt"); break;
910             case D3DSIO_ABS:    strcat(tmpLine, "abs"); break;
911             case D3DSIO_FRC:    strcat(tmpLine, "fract"); break;
912             case D3DSIO_POW:    strcat(tmpLine, "pow"); break;
913             case D3DSIO_CRS:    strcat(tmpLine, "cross"); break;
914             case D3DSIO_NRM:    strcat(tmpLine, "normalize"); break;
915             case D3DSIO_LOGP:
916             case D3DSIO_LOG:    strcat(tmpLine, "log2"); break;
917             case D3DSIO_EXPP:
918             case D3DSIO_EXP:    strcat(tmpLine, "exp2"); break;
919             case D3DSIO_SGE:    strcat(tmpLine, "greaterThanEqual"); break;
920             case D3DSIO_SLT:    strcat(tmpLine, "lessThan"); break;
921             case D3DSIO_SGN:    strcat(tmpLine, "sign"); break;
922         default:
923             FIXME("Opcode %s not yet handled in GLSL\n", curOpcode->name);
924             break;
925     }
926
927     strcat(tmpLine, "(");
928
929     if (curOpcode->num_params > 0) {
930         strcat(tmpLine, "vec4(");
931         shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src_reg, src_mask, src_str);
932         strcat(tmpLine, src_str);
933         strcat(tmpLine, ")");
934         for (i = 2; i < curOpcode->num_params; ++i) {
935             strcat(tmpLine, ", vec4(");
936             shader_glsl_add_param(arg, arg->src[i-1], arg->src_addr[i-1], TRUE, src_reg, src_mask, src_str);
937             strcat(tmpLine, src_str);
938             strcat(tmpLine, ")");
939         }
940     }
941     shader_addline(buffer, "%s))%s;\n", tmpLine, dst_mask);
942
943 }
944
945 /** Process the RCP (reciprocal or inverse) opcode in GLSL (dst = 1 / src) */
946 void shader_glsl_rcp(SHADER_OPCODE_ARG* arg) {
947
948     char tmpLine[256];
949     char dst_str[100], src_str[100];
950     char dst_reg[50], src_reg[50];
951     char dst_mask[6], src_mask[6];
952     
953     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
954     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src_reg, src_mask, src_str);
955     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
956     strcat(tmpLine, "1.0 / ");
957     shader_addline(arg->buffer, "%s%s)%s;\n", tmpLine, src_str, dst_mask);
958 }
959
960 /** Process signed comparison opcodes in GLSL. */
961 void shader_glsl_compare(SHADER_OPCODE_ARG* arg) {
962
963     char tmpLine[256];
964     char dst_str[100], src0_str[100], src1_str[100];
965     char dst_reg[50], src0_reg[50], src1_reg[50];
966     char dst_mask[6], src0_mask[6], src1_mask[6];
967     
968     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
969     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
970     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
971
972     /* If we are comparing vectors and not scalars, we should process this through map2gl using the GLSL functions. */
973     if (strlen(src0_mask) != 2) {
974         shader_glsl_map2gl(arg);
975     } else {
976         char compareStr[3];
977         compareStr[0] = 0;
978         shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
979
980         switch (arg->opcode->opcode) {
981             case D3DSIO_SLT:    strcpy(compareStr, "<"); break;
982             case D3DSIO_SGE:    strcpy(compareStr, ">="); break;
983             default:
984                 FIXME("Can't handle opcode %s\n", arg->opcode->name);
985         }
986         shader_addline(arg->buffer, "%s(float(%s) %s float(%s)) ? 1.0 : 0.0)%s;\n",
987                        tmpLine, src0_str, compareStr, src1_str, dst_mask);
988     }
989 }
990
991 /** Process CMP instruction in GLSL (dst = src0.x > 0.0 ? src1.x : src2.x), per channel */
992 void shader_glsl_cmp(SHADER_OPCODE_ARG* arg) {
993
994     char tmpLine[256];
995     char dst_str[100], src0_str[100], src1_str[100], src2_str[100];
996     char dst_reg[50], src0_reg[50], src1_reg[50], src2_reg[50];
997     char dst_mask[6], src0_mask[6], src1_mask[6], src2_mask[6];
998    
999     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1000     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1001     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1002     shader_glsl_add_param(arg, arg->src[2], arg->src_addr[2], TRUE, src2_reg, src2_mask, src2_str);
1003
1004     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1005     shader_addline(arg->buffer, "%smix(vec4(%s), vec4(%s), vec4(lessThan(vec4(%s), vec4(0.0)))))%s;\n",
1006         tmpLine, src1_str, src2_str, src0_str, dst_mask);
1007 }
1008
1009 /** Process the CND opcode in GLSL (dst = (src0 < 0.5) ? src1 : src2) */
1010 void shader_glsl_cnd(SHADER_OPCODE_ARG* arg) {
1011
1012     char tmpLine[256];
1013     char dst_str[100], src0_str[100], src1_str[100], src2_str[100];
1014     char dst_reg[50], src0_reg[50], src1_reg[50], src2_reg[50];
1015     char dst_mask[6], src0_mask[6], src1_mask[6], src2_mask[6];
1016  
1017     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1018     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1019     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1020     shader_glsl_add_param(arg, arg->src[2], arg->src_addr[2], TRUE, src2_reg, src2_mask, src2_str);   
1021     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1022     shader_addline(arg->buffer, "%s(%s < 0.5) ? %s : %s)%s;\n", 
1023                    tmpLine, src0_str, src1_str, src2_str, dst_mask);
1024 }
1025
1026 /** GLSL code generation for D3DSIO_MAD: Multiply the first 2 opcodes, then add the last */
1027 void shader_glsl_mad(SHADER_OPCODE_ARG* arg) {
1028
1029     char tmpLine[256];
1030     char dst_str[100], src0_str[100], src1_str[100], src2_str[100];
1031     char dst_reg[50], src0_reg[50], src1_reg[50], src2_reg[50];
1032     char dst_mask[6], src0_mask[6], src1_mask[6], src2_mask[6];
1033     
1034     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1035     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1036     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1037     shader_glsl_add_param(arg, arg->src[2], arg->src_addr[2], TRUE, src2_reg, src2_mask, src2_str);     
1038     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1039
1040     shader_addline(arg->buffer, "%s(vec4(%s) * vec4(%s)) + vec4(%s))%s;\n",
1041                    tmpLine, src0_str, src1_str, src2_str, dst_mask);
1042 }
1043
1044 /** Handles transforming all D3DSIO_M?x? opcodes for 
1045     Vertex shaders to GLSL codes */
1046 void shader_glsl_mnxn(SHADER_OPCODE_ARG* arg) {
1047     int i;
1048     int nComponents = 0;
1049     SHADER_OPCODE_ARG tmpArg;
1050    
1051     memset(&tmpArg, 0, sizeof(SHADER_OPCODE_ARG));
1052
1053     /* Set constants for the temporary argument */
1054     tmpArg.shader      = arg->shader;
1055     tmpArg.buffer      = arg->buffer;
1056     tmpArg.src[0]      = arg->src[0];
1057     tmpArg.src_addr[0] = arg->src_addr[0];
1058     tmpArg.src_addr[1] = arg->src_addr[1];
1059     tmpArg.reg_maps = arg->reg_maps; 
1060     
1061     switch(arg->opcode->opcode) {
1062         case D3DSIO_M4x4:
1063             nComponents = 4;
1064             tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1065             break;
1066         case D3DSIO_M4x3:
1067             nComponents = 3;
1068             tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP4];
1069             break;
1070         case D3DSIO_M3x4:
1071             nComponents = 4;
1072             tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1073             break;
1074         case D3DSIO_M3x3:
1075             nComponents = 3;
1076             tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1077             break;
1078         case D3DSIO_M3x2:
1079             nComponents = 2;
1080             tmpArg.opcode = &IWineD3DVertexShaderImpl_shader_ins[D3DSIO_DP3];
1081             break;
1082         default:
1083             break;
1084     }
1085
1086     for (i = 0; i < nComponents; i++) {
1087         tmpArg.dst = ((arg->dst) & ~D3DSP_WRITEMASK_ALL)|(D3DSP_WRITEMASK_0<<i);
1088         tmpArg.src[1]      = arg->src[1]+i;
1089         shader_glsl_dot(&tmpArg);
1090     }
1091 }
1092
1093 /**
1094     The LRP instruction performs a component-wise linear interpolation 
1095     between the second and third operands using the first operand as the
1096     blend factor.  Equation:  (dst = src2 * (src1 - src0) + src0)
1097 */
1098 void shader_glsl_lrp(SHADER_OPCODE_ARG* arg) {
1099
1100     char tmpLine[256];
1101     char dst_str[100], src0_str[100], src1_str[100], src2_str[100];
1102     char dst_reg[50], src0_reg[50], src1_reg[50], src2_reg[50];
1103     char dst_mask[6], src0_mask[6], src1_mask[6], src2_mask[6];
1104    
1105     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1106     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1107     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1108     shader_glsl_add_param(arg, arg->src[2], arg->src_addr[2], TRUE, src2_reg, src2_mask, src2_str);     
1109
1110     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1111     
1112     shader_addline(arg->buffer, "%s%s + %s * (%s - %s))%s;\n",
1113                    tmpLine, src2_str, src0_str, src1_str, src2_str, dst_mask);
1114 }
1115
1116 /** Process the D3DSIO_LIT instruction in GLSL:
1117  * dst.x = dst.w = 1.0
1118  * dst.y = (src0.x > 0) ? src0.x
1119  * dst.z = (src0.x > 0) ? ((src0.y > 0) ? pow(src0.y, src.w) : 0) : 0
1120  *                                        where src.w is clamped at +- 128
1121  */
1122 void shader_glsl_lit(SHADER_OPCODE_ARG* arg) {
1123
1124     char dst_str[100], src0_str[100];
1125     char dst_reg[50], src0_reg[50];
1126     char dst_mask[6], src0_mask[6];
1127    
1128     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1129     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1130
1131     shader_addline(arg->buffer,
1132         "%s = vec4(1.0, (%s.x > 0.0 ? %s.x : 0.0), (%s.x > 0.0 ? ((%s.y > 0.0) ? pow(%s.y, clamp(%s.w, -128.0, 128.0)) : 0.0) : 0.0), 1.0)%s;\n",
1133         dst_str, src0_reg, src0_reg, src0_reg, src0_reg, src0_reg, src0_reg, dst_mask);
1134 }
1135
1136 /** Process the D3DSIO_DST instruction in GLSL:
1137  * dst.x = 1.0
1138  * dst.y = src0.x * src0.y
1139  * dst.z = src0.z
1140  * dst.w = src1.w
1141  */
1142 void shader_glsl_dst(SHADER_OPCODE_ARG* arg) {
1143
1144     char dst_str[100], src0_str[100], src1_str[100];
1145     char dst_reg[50], src0_reg[50], src1_reg[50];
1146     char dst_mask[6], src0_mask[6], src1_mask[6];
1147    
1148     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1149     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1150     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1151
1152     shader_addline(arg->buffer, "%s = vec4(1.0, %s.x * %s.y, %s.z, %s.w)%s;\n",
1153                    dst_str, src0_reg, src1_reg, src0_reg, src1_reg, dst_mask);
1154 }
1155
1156 /** Process the D3DSIO_SINCOS instruction in GLSL:
1157  * VS 2.0 requires that specific cosine and sine constants be passed to this instruction so the hardware
1158  * can handle it.  But, these functions are built-in for GLSL, so we can just ignore the last 2 params.
1159  * 
1160  * dst.x = cos(src0.?)
1161  * dst.y = sin(src0.?)
1162  * dst.z = dst.z
1163  * dst.w = dst.w
1164  */
1165 void shader_glsl_sincos(SHADER_OPCODE_ARG* arg) {
1166     
1167     char dst_str[100], src0_str[100];
1168     char dst_reg[50], src0_reg[50];
1169     char dst_mask[6], src0_mask[6];
1170    
1171     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1172     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1173
1174     shader_addline(arg->buffer, "%s = vec4(cos(%s), sin(%s), %s.z, %s.w)%s;\n",
1175                    dst_str, src0_str, src0_str, dst_reg, dst_reg, dst_mask);
1176 }
1177
1178 /** Process the D3DSIO_LOOP instruction in GLSL:
1179  * Start a for() loop where src0.y is the initial value of aL,
1180  *  increment aL by src0.z for a total of src0.x iterations.
1181  *  Need to use a temporary variable for this operation.
1182  */
1183 void shader_glsl_loop(SHADER_OPCODE_ARG* arg) {
1184     
1185     char src1_str[100];
1186     char src1_reg[50];
1187     char src1_mask[6];
1188     
1189     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1190   
1191     shader_addline(arg->buffer, "for (tmpInt = 0, aL = %s.y; tmpInt < %s.x; tmpInt++, aL += %s.z) {\n",
1192                    src1_reg, src1_reg, src1_reg);
1193 }
1194
1195 void shader_glsl_end(SHADER_OPCODE_ARG* arg) {
1196     shader_addline(arg->buffer, "}\n");
1197 }
1198
1199 void shader_glsl_rep(SHADER_OPCODE_ARG* arg) {
1200
1201     char src0_str[100];
1202     char src0_reg[50];
1203     char src0_mask[6];
1204
1205     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1206     shader_addline(arg->buffer, "for (tmpInt = 0; tmpInt < %s.x; tmpInt++) {\n", src0_reg);
1207 }
1208
1209 void shader_glsl_if(SHADER_OPCODE_ARG* arg) {
1210
1211     char src0_str[100];
1212     char src0_reg[50];
1213     char src0_mask[6];
1214
1215     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1216     shader_addline(arg->buffer, "if (%s) {\n", src0_str); 
1217 }
1218
1219 void shader_glsl_ifc(SHADER_OPCODE_ARG* arg) {
1220
1221     char src0_str[100], src1_str[100];
1222     char src0_reg[50], src1_reg[50];
1223     char src0_mask[6], src1_mask[6];
1224
1225     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1226     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1227
1228     shader_addline(arg->buffer, "if (%s %s %s) {\n",
1229         src0_str, shader_get_comp_op(arg->opcode_token), src1_str);
1230 }
1231
1232 void shader_glsl_else(SHADER_OPCODE_ARG* arg) {
1233     shader_addline(arg->buffer, "} else {\n");
1234 }
1235
1236 void shader_glsl_break(SHADER_OPCODE_ARG* arg) {
1237     shader_addline(arg->buffer, "break;\n");
1238 }
1239
1240 void shader_glsl_breakc(SHADER_OPCODE_ARG* arg) {
1241
1242     char src0_str[100], src1_str[100];
1243     char src0_reg[50], src1_reg[50];
1244     char src0_mask[6], src1_mask[6];
1245
1246     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1247     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1248
1249     shader_addline(arg->buffer, "if (%s %s %s) break;\n",
1250         src0_str, shader_get_comp_op(arg->opcode_token), src1_str);
1251 }
1252
1253 void shader_glsl_label(SHADER_OPCODE_ARG* arg) {
1254
1255     DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK;
1256     shader_addline(arg->buffer, "}\n");
1257     shader_addline(arg->buffer, "void subroutine%lu () {\n",  snum);
1258 }
1259
1260 void shader_glsl_call(SHADER_OPCODE_ARG* arg) {
1261     DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK;
1262     shader_addline(arg->buffer, "subroutine%lu();\n", snum);
1263 }
1264
1265 void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) {
1266
1267     char src1_str[100];
1268     char src1_reg[50];
1269     char src1_mask[6];
1270    
1271     DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK;
1272     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1273     shader_addline(arg->buffer, "if (%s) subroutine%lu();\n", src1_str, snum);
1274 }
1275
1276 /*********************************************
1277  * Pixel Shader Specific Code begins here
1278  ********************************************/
1279 void pshader_glsl_tex(SHADER_OPCODE_ARG* arg) {
1280
1281     /* FIXME: Make this work for more than just 2D textures */
1282     
1283     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1284     SHADER_BUFFER* buffer = arg->buffer;
1285     DWORD hex_version = This->baseShader.hex_version;
1286
1287     char dst_str[100],   dst_reg[50],  dst_mask[6];
1288     char coord_str[100], coord_reg[50], coord_mask[6];
1289     char sampler_str[100], sampler_reg[50], sampler_mask[6];
1290     DWORD reg_dest_code = arg->dst & D3DSP_REGNUM_MASK;
1291     DWORD sampler_code, sampler_type;
1292
1293     /* All versions have a destination register */
1294     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1295
1296     /* 1.0-1.3: Use destination register as coordinate source.
1297        1.4+: Use provided coordinate source register. */
1298     if (hex_version < D3DPS_VERSION(1,4))
1299        strcpy(coord_reg, dst_reg);
1300     else
1301        shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, coord_reg, coord_mask, coord_str);
1302
1303     /* 1.0-1.4: Use destination register as coordinate source.
1304      * 2.0+: Use provided coordinate source register. */
1305     if (hex_version < D3DPS_VERSION(2,0)) {
1306         sprintf(sampler_str, "Psampler%lu", reg_dest_code); 
1307         sampler_code = reg_dest_code;
1308     }       
1309     else {
1310         shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, sampler_reg, sampler_mask, sampler_str);
1311         sampler_code = arg->src[1] & D3DSP_REGNUM_MASK;
1312     }         
1313
1314     sampler_type = arg->reg_maps->samplers[sampler_code] & D3DSP_TEXTURETYPE_MASK;
1315     switch(sampler_type) {
1316
1317         case D3DSTT_2D:
1318             shader_addline(buffer, "%s = texture2D(%s, %s.st);\n", dst_str, sampler_str, coord_reg);
1319             break;
1320         case D3DSTT_CUBE:
1321             shader_addline(buffer, "%s = textureCube(%s, %s.stp);\n", dst_str, sampler_str, coord_reg);
1322             break;
1323         case D3DSTT_VOLUME:
1324             shader_addline(buffer, "%s = texture3D(%s, %s.stp);\n", dst_str, sampler_str, coord_reg);
1325             break;
1326         default:
1327             shader_addline(buffer, "%s = unrecognized_stype(%s, %s.stp);\n", dst_str, sampler_str, coord_reg);
1328             FIXME("Unrecognized sampler type: %#lx;\n", sampler_type);
1329             break;
1330     }
1331 }
1332
1333 void pshader_glsl_texcoord(SHADER_OPCODE_ARG* arg) {
1334
1335     /* FIXME: Make this work for more than just 2D textures */
1336     
1337     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1338     SHADER_BUFFER* buffer = arg->buffer;
1339     DWORD hex_version = This->baseShader.hex_version;
1340
1341     char tmpStr[100];
1342     char tmpReg[50];
1343     char tmpMask[6];
1344     tmpReg[0] = 0;
1345
1346     shader_glsl_add_param(arg, arg->dst, 0, FALSE, tmpReg, tmpMask, tmpStr);
1347
1348     if (hex_version != D3DPS_VERSION(1,4)) {
1349         DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1350         shader_addline(buffer, "%s = clamp(gl_TexCoord[%lu], 0.0, 1.0);\n", tmpReg, reg);
1351     } else {
1352         DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1353         shader_addline(buffer, "%s = gl_TexCoord[%lu]%s;\n", tmpStr, reg2, tmpMask);
1354    }
1355 }
1356
1357 void pshader_glsl_texm3x2pad(SHADER_OPCODE_ARG* arg) {
1358
1359     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1360     SHADER_BUFFER* buffer = arg->buffer;
1361     char src0_str[100];
1362     char src0_name[50];
1363     char src0_mask[6];
1364
1365     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
1366     shader_addline(buffer, "tmp0.x = dot(vec3(T%lu), vec3(%s));\n", reg, src0_name, src0_str);
1367 }
1368
1369 /** Process the D3DSIO_TEXM3X3PAD instruction in GLSL
1370  * Calculate the 1st or 2nd row of a 3-row matrix multiplication. */
1371 void pshader_glsl_texm3x3pad(SHADER_OPCODE_ARG* arg) {
1372
1373     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1374     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1375     SHADER_BUFFER* buffer = arg->buffer;
1376     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
1377     char src0_str[100];
1378     char src0_name[50];
1379     char src0_mask[6];
1380
1381     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
1382     shader_addline(buffer, "tmp0.%c = dot(vec3(T%lu), vec3(%s));\n", 'x' + current_state->current_row, reg, src0_str);
1383     current_state->texcoord_w[current_state->current_row++] = reg;
1384 }
1385
1386 void pshader_glsl_texm3x2tex(SHADER_OPCODE_ARG* arg) {
1387
1388     /* FIXME: Make this work for more than just 2D textures */
1389     
1390     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1391     SHADER_BUFFER* buffer = arg->buffer;
1392     char src0_str[100];
1393     char src0_name[50];
1394     char src0_mask[6];
1395
1396     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
1397     shader_addline(buffer, "tmp0.y = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
1398     shader_addline(buffer, "T%lu = texture2D(Psampler%lu, tmp0.st);\n", reg, reg);
1399 }
1400
1401 /** Process the D3DSIO_TEXM3X3TEX instruction in GLSL
1402  * Perform the 3rd row of a 3x3 matrix multiply, then sample the texture using the calculate coordinates */
1403 void pshader_glsl_texm3x3tex(SHADER_OPCODE_ARG* arg) {
1404
1405     char src0_str[100];
1406     char src0_name[50];
1407     char src0_mask[6];
1408     char dimensions[5];
1409     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1410     DWORD src0_regnum = arg->src[0] & D3DSP_REGNUM_MASK;
1411     DWORD stype = arg->reg_maps->samplers[src0_regnum] & D3DSP_TEXTURETYPE_MASK;
1412     IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
1413     SHADER_PARSE_STATE* current_state = &This->baseShader.parse_state;
1414     
1415     switch (stype) {
1416         case D3DSTT_2D:     strcpy(dimensions, "2D");   break;
1417         case D3DSTT_CUBE:   strcpy(dimensions, "Cube"); break;
1418         case D3DSTT_VOLUME: strcpy(dimensions, "3D");   break;
1419         default:
1420             strcpy(dimensions, "");
1421             FIXME("Unrecognized sampler type: %#lx\n", stype);
1422             break;
1423     }
1424
1425     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
1426     shader_addline(arg->buffer, "tmp0.z = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
1427     shader_addline(arg->buffer, "T%lu = texture%s(Psampler%lu, tmp0.%s);\n", 
1428             reg, dimensions, reg, (stype == D3DSTT_2D) ? "xy" : "xyz");
1429     current_state->current_row = 0;
1430 }
1431
1432 /** Process the D3DSIO_TEXM3X3SPEC instruction in GLSL 
1433  * Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */
1434 void pshader_glsl_texm3x3spec(SHADER_OPCODE_ARG* arg) {
1435
1436     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1437     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1438     char dimensions[5];
1439     char src0_str[100], src0_name[50], src0_mask[6];
1440     char src1_str[100], src1_name[50], src1_mask[6];
1441     SHADER_BUFFER* buffer = arg->buffer;
1442     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
1443     DWORD stype = arg->reg_maps->samplers[reg] & D3DSP_TEXTURETYPE_MASK;
1444
1445     switch (stype) {
1446         case D3DSTT_2D:     strcpy(dimensions, "2D");   break;
1447         case D3DSTT_CUBE:   strcpy(dimensions, "Cube"); break;
1448         case D3DSTT_VOLUME: strcpy(dimensions, "3D");   break;
1449         default:
1450             strcpy(dimensions, "");
1451             FIXME("Unrecognized sampler type: %#lx\n", stype);
1452             break;
1453     }
1454
1455     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
1456     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_name, src1_mask, src1_str);
1457
1458     /* Perform the last matrix multiply operation */
1459     shader_addline(buffer, "tmp0.z = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
1460
1461     /* Calculate reflection vector */
1462     shader_addline(buffer, "tmp0.xyz = reflect(-vec3(%s), vec3(tmp0));\n", src1_str);
1463
1464     /* Sample the texture */
1465     shader_addline(buffer, "T%lu = texture%s(Psampler%lu, tmp0.%s);\n", 
1466             reg, dimensions, reg, (stype == D3DSTT_2D) ? "xy" : "xyz");
1467     current_state->current_row = 0;
1468 }
1469
1470 /** Process the D3DSIO_TEXM3X3VSPEC instruction in GLSL 
1471  * Peform the final texture lookup based on the previous 2 3x3 matrix multiplies */
1472 void pshader_glsl_texm3x3vspec(SHADER_OPCODE_ARG* arg) {
1473
1474     IWineD3DPixelShaderImpl* shader = (IWineD3DPixelShaderImpl*) arg->shader;
1475     DWORD reg = arg->dst & D3DSP_REGNUM_MASK;
1476     SHADER_BUFFER* buffer = arg->buffer;
1477     SHADER_PARSE_STATE* current_state = &shader->baseShader.parse_state;
1478     char src0_str[100], src0_name[50], src0_mask[6];
1479
1480     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_name, src0_mask, src0_str);
1481
1482     /* Perform the last matrix multiply operation */
1483     shader_addline(buffer, "tmp0.z = dot(vec3(T%lu), vec3(%s));\n", reg, src0_str);
1484
1485     /* Construct the eye-ray vector from w coordinates */
1486     shader_addline(buffer, "tmp1.x = gl_TexCoord[%lu].w;\n", current_state->texcoord_w[0]);
1487     shader_addline(buffer, "tmp1.y = gl_TexCoord[%lu].w;\n", current_state->texcoord_w[1]);
1488     shader_addline(buffer, "tmp1.z = gl_TexCoord[%lu].w;\n", reg);
1489
1490     /* Calculate reflection vector (Assume normal is normalized): RF = 2*(N.E)*N -E */
1491     shader_addline(buffer, "tmp0.x = dot(vec3(tmp0), vec3(tmp1));\n");
1492     shader_addline(buffer, "tmp0 = tmp0.w * tmp0;\n");
1493     shader_addline(buffer, "tmp0 = (2.0 * tmp0) - tmp1;\n");
1494
1495     /* FIXME:
1496      * We don't really know if a Cube or a Volume texture is being sampled, but since Cube textures
1497      * are used more commonly, we'll default to that.
1498      * We probably need to push back the pixel shader generation code until drawPrimitive() for 
1499      * shader versions < 2.0, since that's the only time we can guarantee that we're sampling
1500      * the correct type of texture because we can lookup what textures are bound at that point.
1501      */
1502     shader_addline(buffer, "T%lu = textureCube(Psampler%lu, tmp0.xyz);\n", reg, reg);
1503     current_state->current_row = 0;
1504 }
1505
1506 /** Process the D3DSIO_TEXBEM instruction in GLSL.
1507  * Apply a fake bump map transform.
1508  * FIXME: Should apply the BUMPMAPENV matrix.  For now, just sample the texture */
1509 void pshader_glsl_texbem(SHADER_OPCODE_ARG* arg) {
1510
1511     DWORD reg1 = arg->dst & D3DSP_REGNUM_MASK;
1512     DWORD reg2 = arg->src[0] & D3DSP_REGNUM_MASK;
1513
1514     FIXME("Not applying the BUMPMAPENV matrix for pixel shader instruction texbem.\n");
1515     shader_addline(arg->buffer, "T%lu = texture2D(Psampler%lu, gl_TexCoord[%lu].xy + T%lu.xy);\n",
1516             reg1, reg1, reg1, reg2);
1517 }
1518
1519 /** Process the D3DSIO_TEXREG2AR instruction in GLSL
1520  * Sample 2D texture at dst using the alpha & red (wx) components of src as texture coordinates */
1521 void pshader_glsl_texreg2ar(SHADER_OPCODE_ARG* arg) {
1522     
1523     char tmpLine[255];
1524     char dst_str[100], src0_str[100];
1525     char dst_reg[50], src0_reg[50];
1526     char dst_mask[6], src0_mask[6];
1527     DWORD src0_regnum = arg->src[0] & D3DSP_REGNUM_MASK;
1528
1529     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1530     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1531
1532     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1533     shader_addline(arg->buffer, "%stexture2D(Psampler%lu, %s.yz))%s;\n",
1534             tmpLine, src0_regnum, dst_reg, dst_mask);
1535 }
1536
1537 /** Process the D3DSIO_TEXREG2GB instruction in GLSL
1538  * Sample 2D texture at dst using the green & blue (yz) components of src as texture coordinates */
1539 void pshader_glsl_texreg2gb(SHADER_OPCODE_ARG* arg) {
1540
1541     char tmpLine[255];
1542     char dst_str[100], src0_str[100];
1543     char dst_reg[50], src0_reg[50];
1544     char dst_mask[6], src0_mask[6];
1545     DWORD src0_regnum = arg->src[0] & D3DSP_REGNUM_MASK;
1546
1547     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1548     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1549
1550     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1551     shader_addline(arg->buffer, "%stexture2D(Psampler%lu, %s.yz))%s;\n",
1552             tmpLine, src0_regnum, dst_reg, dst_mask);
1553 }
1554
1555 /** Process the D3DSIO_TEXREG2RGB instruction in GLSL
1556  * Sample texture at dst using the rgb (xyz) components of src as texture coordinates */
1557 void pshader_glsl_texreg2rgb(SHADER_OPCODE_ARG* arg) {
1558
1559     char tmpLine[255];
1560     char dst_str[100], src0_str[100];
1561     char dst_reg[50], src0_reg[50];
1562     char dst_mask[6], src0_mask[6];
1563     char dimensions[5];
1564     DWORD src0_regnum = arg->src[0] & D3DSP_REGNUM_MASK;
1565     DWORD stype = arg->reg_maps->samplers[src0_regnum] & D3DSP_TEXTURETYPE_MASK;
1566     switch (stype) {
1567         case D3DSTT_2D:     strcpy(dimensions, "2D");   break;
1568         case D3DSTT_CUBE:   strcpy(dimensions, "Cube"); break;
1569         case D3DSTT_VOLUME: strcpy(dimensions, "3D");   break;
1570         default:
1571             strcpy(dimensions, "");
1572             FIXME("Unrecognized sampler type: %#lx\n", stype);
1573             break;
1574     }
1575
1576     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1577     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1578
1579     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1580     shader_addline(arg->buffer, "%stexture%s(Psampler%lu, %s.%s))%s;\n",
1581             tmpLine, dimensions, src0_regnum, dst_reg, (stype == D3DSTT_2D) ? "xy" : "xyz", dst_mask);
1582 }
1583
1584 /** Process the D3DSIO_TEXKILL instruction in GLSL.
1585  * If any of the first 3 components are < 0, discard this pixel */
1586 void pshader_glsl_texkill(SHADER_OPCODE_ARG* arg) {
1587
1588     char dst_str[100], dst_name[50], dst_mask[6];
1589
1590     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_name, dst_mask, dst_str);
1591     shader_addline(arg->buffer, "if (any(lessThan(%s.xyz, vec3(0.0)))) discard;\n", dst_name);
1592 }
1593
1594 /** Process the D3DSIO_DP2ADD instruction in GLSL.
1595  * dst = dot2(src0, src1) + src2 */
1596 void pshader_glsl_dp2add(SHADER_OPCODE_ARG* arg) {
1597
1598     char tmpLine[256];
1599     char dst_str[100], src0_str[100], src1_str[100], src2_str[100];
1600     char dst_reg[50], src0_reg[50], src1_reg[50], src2_reg[50];
1601     char dst_mask[6], src0_mask[6], src1_mask[6], src2_mask[6];
1602  
1603     shader_glsl_add_param(arg, arg->dst, 0, FALSE, dst_reg, dst_mask, dst_str);
1604     shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
1605     shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
1606     shader_glsl_add_param(arg, arg->src[2], arg->src_addr[2], TRUE, src2_reg, src2_mask, src2_str);   
1607     shader_glsl_add_dst(arg->dst, dst_reg, dst_mask, tmpLine);
1608     shader_addline(arg->buffer, "%sdot(vec2(%s), vec2(%s)) + %s)%s;\n",
1609                    tmpLine, src0_str, src1_str, src2_str, dst_mask);
1610 }
1611
1612 void pshader_glsl_input_pack(
1613    SHADER_BUFFER* buffer,
1614    semantic* semantics_in) {
1615
1616    unsigned int i;
1617
1618    for (i = 0; i < MAX_REG_INPUT; i++) {
1619
1620        DWORD usage_token = semantics_in[i].usage;
1621        DWORD register_token = semantics_in[i].reg;
1622        DWORD usage, usage_idx;
1623        char reg_mask[6];
1624
1625        /* Uninitialized */
1626        if (!usage_token) continue;
1627        usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
1628        usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
1629        shader_glsl_get_output_register_swizzle(register_token, reg_mask);
1630
1631        switch(usage) {
1632
1633            case D3DDECLUSAGE_COLOR:
1634                if (usage_idx == 0)
1635                    shader_addline(buffer, "IN%lu%s = vec4(gl_Color)%s;\n",
1636                        i, reg_mask, reg_mask);
1637                else if (usage_idx == 1)
1638                    shader_addline(buffer, "IN%lu%s = vec4(gl_SecondaryColor)%s;\n",
1639                        i, reg_mask, reg_mask);
1640                else
1641                    shader_addline(buffer, "IN%lu%s = vec4(unsupported_color_input)%s;\n",
1642                        i, reg_mask, reg_mask);
1643                break;
1644
1645            case D3DDECLUSAGE_TEXCOORD:
1646                shader_addline(buffer, "IN%lu%s = vec4(gl_TexCoord[%lu])%s;\n",
1647                    i, reg_mask, usage_idx, reg_mask );
1648                break;
1649
1650            case D3DDECLUSAGE_FOG:
1651                shader_addline(buffer, "IN%lu%s = vec4(gl_FogFragCoord)%s;\n",
1652                    i, reg_mask, reg_mask);
1653                break;
1654
1655            default:
1656                shader_addline(buffer, "IN%lu%s = vec4(unsupported_input)%s;\n",
1657                    i, reg_mask, reg_mask);
1658         }
1659     }
1660 }
1661
1662 /*********************************************
1663  * Vertex Shader Specific Code begins here
1664  ********************************************/
1665
1666 void vshader_glsl_output_unpack(
1667    SHADER_BUFFER* buffer,
1668    semantic* semantics_out) {
1669
1670    unsigned int i;
1671
1672    for (i = 0; i < MAX_REG_OUTPUT; i++) {
1673
1674        DWORD usage_token = semantics_out[i].usage;
1675        DWORD register_token = semantics_out[i].reg;
1676        DWORD usage, usage_idx;
1677        char reg_mask[6];
1678
1679        /* Uninitialized */
1680        if (!usage_token) continue;
1681
1682        usage = (usage_token & D3DSP_DCL_USAGE_MASK) >> D3DSP_DCL_USAGE_SHIFT;
1683        usage_idx = (usage_token & D3DSP_DCL_USAGEINDEX_MASK) >> D3DSP_DCL_USAGEINDEX_SHIFT;
1684        shader_glsl_get_output_register_swizzle(register_token, reg_mask);
1685
1686        switch(usage) {
1687
1688            case D3DDECLUSAGE_COLOR:
1689                if (usage_idx == 0)
1690                    shader_addline(buffer, "gl_FrontColor%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
1691                else if (usage_idx == 1)
1692                    shader_addline(buffer, "gl_FrontSecondaryColor%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
1693                else
1694                    shader_addline(buffer, "unsupported_color_output%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
1695                break;
1696
1697            case D3DDECLUSAGE_POSITION:
1698                shader_addline(buffer, "gl_Position%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
1699                break;
1700  
1701            case D3DDECLUSAGE_TEXCOORD:
1702                shader_addline(buffer, "gl_TexCoord[%lu]%s = OUT%lu%s;\n",
1703                    usage_idx, reg_mask, i, reg_mask);
1704                break;
1705
1706            case WINED3DSHADERDECLUSAGE_PSIZE:
1707                shader_addline(buffer, "gl_PointSize = OUT%lu.x;\n", i);
1708                break;
1709
1710            case WINED3DSHADERDECLUSAGE_FOG:
1711                shader_addline(buffer, "gl_FogFragCoord%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
1712                break;
1713
1714            default:
1715                shader_addline(buffer, "unsupported_output%s = OUT%lu%s;\n", reg_mask, i, reg_mask);
1716        }
1717     }
1718 }