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