msi: Open the database storage in transacted mode when MSIDBOPEN_CREATE or MSIDBOPEN_...
[wine] / dlls / wined3d / arb_program_shader.c
1 /*
2  * Pixel and vertex shaders implementation using ARB_vertex_program
3  * and ARB_fragment_program GL extensions.
4  *
5  * Copyright 2002-2003 Jason Edmeades
6  * Copyright 2002-2003 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Ivan Gyurdiev
10  * Copyright 2006 Jason Green
11  * Copyright 2006 Henri Verbeet
12  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
13  * Copyright 2009 Henri Verbeet for CodeWeavers
14  *
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28  */
29
30 #include "config.h"
31
32 #include <math.h>
33 #include <stdio.h>
34
35 #include "wined3d_private.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
38 WINE_DECLARE_DEBUG_CHANNEL(d3d_constants);
39 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
40 WINE_DECLARE_DEBUG_CHANNEL(d3d);
41
42 /* Extract a line. Note that this modifies the source string. */
43 static char *get_line(char **ptr)
44 {
45     char *p, *q;
46
47     p = *ptr;
48     if (!(q = strstr(p, "\n")))
49     {
50         if (!*p) return NULL;
51         *ptr += strlen(p);
52         return p;
53     }
54     *q = '\0';
55     *ptr = q + 1;
56
57     return p;
58 }
59
60 static void shader_arb_dump_program_source(const char *source)
61 {
62     ULONG source_size;
63     char *ptr, *line, *tmp;
64
65     source_size = strlen(source) + 1;
66     tmp = HeapAlloc(GetProcessHeap(), 0, source_size);
67     if (!tmp)
68     {
69         ERR("Failed to allocate %u bytes for shader source.\n", source_size);
70         return;
71     }
72     memcpy(tmp, source, source_size);
73
74     ptr = tmp;
75     while ((line = get_line(&ptr))) FIXME("    %s\n", line);
76     FIXME("\n");
77
78     HeapFree(GetProcessHeap(), 0, tmp);
79 }
80
81 /* GL locking for state handlers is done by the caller. */
82 static BOOL need_rel_addr_const(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info)
83 {
84     if (shader->baseShader.reg_maps.shader_version.type == WINED3D_SHADER_TYPE_VERTEX)
85     {
86         if (((IWineD3DVertexShaderImpl *)shader)->rel_offset) return TRUE;
87     }
88     if (!shader->baseShader.reg_maps.usesmova) return FALSE;
89     return !gl_info->supported[NV_VERTEX_PROGRAM2_OPTION];
90 }
91
92 /* Returns TRUE if result.clip from GL_NV_vertex_program2 should be used and FALSE otherwise */
93 static inline BOOL use_nv_clip(const struct wined3d_gl_info *gl_info)
94 {
95     return gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]
96             && !(gl_info->quirks & WINED3D_QUIRK_NV_CLIP_BROKEN);
97 }
98
99 static BOOL need_helper_const(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info)
100 {
101     if (need_rel_addr_const(shader, gl_info)) return TRUE;
102     if (!gl_info->supported[NV_VERTEX_PROGRAM]) return TRUE; /* Need to init colors. */
103     if (gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT) return TRUE; /* Load the immval offset. */
104     if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W) return TRUE; /* Have to init texcoords. */
105     if (!use_nv_clip(gl_info)) return TRUE; /* Init the clip texcoord */
106     if (shader->baseShader.reg_maps.usesnrm) return TRUE; /* 0.0 */
107     if (shader->baseShader.reg_maps.usesrcp) return TRUE; /* EPS */
108     return FALSE;
109 }
110
111 static unsigned int reserved_vs_const(IWineD3DBaseShaderImpl *shader, const struct wined3d_gl_info *gl_info)
112 {
113     unsigned int ret = 1;
114     /* We use one PARAM for the pos fixup, and in some cases one to load
115      * some immediate values into the shader
116      */
117     if(need_helper_const(shader, gl_info)) ret++;
118     if(need_rel_addr_const(shader, gl_info)) ret++;
119     return ret;
120 }
121
122 enum arb_helper_value
123 {
124     ARB_ZERO,
125     ARB_ONE,
126     ARB_TWO,
127     ARB_0001,
128     ARB_EPS,
129
130     ARB_VS_REL_OFFSET
131 };
132
133 static const char *arb_get_helper_value(enum wined3d_shader_type shader, enum arb_helper_value value)
134 {
135     if (shader == WINED3D_SHADER_TYPE_GEOMETRY)
136     {
137         ERR("Geometry shaders are unsupported\n");
138         return "bad";
139     }
140
141     if (shader == WINED3D_SHADER_TYPE_PIXEL)
142     {
143         switch (value)
144         {
145             case ARB_ZERO: return "ps_helper_const.x";
146             case ARB_ONE: return "ps_helper_const.y";
147             case ARB_TWO: return "coefmul.x";
148             case ARB_0001: return "helper_const.xxxy";
149             case ARB_EPS: return "ps_helper_const.z";
150             default: break;
151         }
152     }
153     else
154     {
155         switch (value)
156         {
157             case ARB_ZERO: return "helper_const.x";
158             case ARB_ONE: return "helper_const.y";
159             case ARB_TWO: return "helper_const.z";
160             case ARB_EPS: return "helper_const.w";
161             case ARB_0001: return "helper_const.xxxy";
162             case ARB_VS_REL_OFFSET: return "rel_addr_const.y";
163         }
164     }
165     FIXME("Unmanaged %s shader helper constant requested: %u\n",
166           shader == WINED3D_SHADER_TYPE_PIXEL ? "pixel" : "vertex", value);
167     switch (value)
168     {
169         case ARB_ZERO: return "0.0";
170         case ARB_ONE: return "1.0";
171         case ARB_TWO: return "2.0";
172         case ARB_0001: return "{0.0, 0.0, 0.0, 1.0}";
173         case ARB_EPS: return "1e-8";
174         default: return "bad";
175     }
176 }
177
178 static inline BOOL ffp_clip_emul(IWineD3DStateBlockImpl *stateblock)
179 {
180     return stateblock->lowest_disabled_stage < 7;
181 }
182
183 /* ARB_program_shader private data */
184
185 struct control_frame
186 {
187     struct                          list entry;
188     enum
189     {
190         IF,
191         IFC,
192         LOOP,
193         REP
194     } type;
195     BOOL                            muting;
196     BOOL                            outer_loop;
197     union
198     {
199         unsigned int                loop;
200         unsigned int                ifc;
201     } no;
202     struct wined3d_shader_loop_control loop_control;
203     BOOL                            had_else;
204 };
205
206 struct arb_ps_np2fixup_info
207 {
208     struct ps_np2fixup_info         super;
209     /* For ARB we need a offset value:
210      * With both GLSL and ARB mode the NP2 fixup information (the texture dimensions) are stored in a
211      * consecutive way (GLSL uses a uniform array). Since ARB doesn't know the notion of a "standalone"
212      * array we need an offset to the index inside the program local parameter array. */
213     UINT                            offset;
214 };
215
216 struct arb_ps_compile_args
217 {
218     struct ps_compile_args          super;
219     WORD                            bools;
220     WORD                            clip;  /* only a boolean, use a WORD for alignment */
221     unsigned char                   loop_ctrl[MAX_CONST_I][3];
222 };
223
224 struct stb_const_desc
225 {
226     unsigned char           texunit;
227     UINT                    const_num;
228 };
229
230 struct arb_ps_compiled_shader
231 {
232     struct arb_ps_compile_args      args;
233     struct arb_ps_np2fixup_info     np2fixup_info;
234     struct stb_const_desc           bumpenvmatconst[MAX_TEXTURES];
235     struct stb_const_desc           luminanceconst[MAX_TEXTURES];
236     UINT                            int_consts[MAX_CONST_I];
237     GLuint                          prgId;
238     UINT                            ycorrection;
239     unsigned char                   numbumpenvmatconsts;
240     char                            num_int_consts;
241 };
242
243 struct arb_vs_compile_args
244 {
245     struct vs_compile_args          super;
246     union
247     {
248         struct
249         {
250             WORD                    bools;
251             unsigned char           clip_texcoord;
252             unsigned char           clipplane_mask;
253         }                           boolclip;
254         DWORD                       boolclip_compare;
255     } clip;
256     DWORD                           ps_signature;
257     union
258     {
259         unsigned char               samplers[4];
260         DWORD                       samplers_compare;
261     } vertex;
262     unsigned char                   loop_ctrl[MAX_CONST_I][3];
263 };
264
265 struct arb_vs_compiled_shader
266 {
267     struct arb_vs_compile_args      args;
268     GLuint                          prgId;
269     UINT                            int_consts[MAX_CONST_I];
270     char                            num_int_consts;
271     char                            need_color_unclamp;
272     UINT                            pos_fixup;
273 };
274
275 struct recorded_instruction
276 {
277     struct wined3d_shader_instruction ins;
278     struct list entry;
279 };
280
281 struct shader_arb_ctx_priv
282 {
283     char addr_reg[20];
284     enum
285     {
286         /* plain GL_ARB_vertex_program or GL_ARB_fragment_program */
287         ARB,
288         /* GL_NV_vertex_progam2_option or GL_NV_fragment_program_option */
289         NV2,
290         /* GL_NV_vertex_program3 or GL_NV_fragment_program2 */
291         NV3
292     } target_version;
293
294     const struct arb_vs_compile_args    *cur_vs_args;
295     const struct arb_ps_compile_args    *cur_ps_args;
296     const struct arb_ps_compiled_shader *compiled_fprog;
297     const struct arb_vs_compiled_shader *compiled_vprog;
298     struct arb_ps_np2fixup_info         *cur_np2fixup_info;
299     struct list                         control_frames;
300     struct list                         record;
301     BOOL                                recording;
302     BOOL                                muted;
303     unsigned int                        num_loops, loop_depth, num_ifcs;
304     int                                 aL;
305
306     unsigned int                        vs_clipplanes;
307     BOOL                                footer_written;
308     BOOL                                in_main_func;
309
310     /* For 3.0 vertex shaders */
311     const char                          *vs_output[MAX_REG_OUTPUT];
312     /* For 2.x and earlier vertex shaders */
313     const char                          *texcrd_output[8], *color_output[2], *fog_output;
314
315     /* 3.0 pshader input for compatibility with fixed function */
316     const char                          *ps_input[MAX_REG_INPUT];
317 };
318
319 struct ps_signature
320 {
321     struct wined3d_shader_signature_element *sig;
322     DWORD                               idx;
323     struct wine_rb_entry                entry;
324 };
325
326 struct arb_pshader_private {
327     struct arb_ps_compiled_shader   *gl_shaders;
328     UINT                            num_gl_shaders, shader_array_size;
329     BOOL                            has_signature_idx;
330     DWORD                           input_signature_idx;
331     DWORD                           clipplane_emulation;
332     BOOL                            clamp_consts;
333 };
334
335 struct arb_vshader_private {
336     struct arb_vs_compiled_shader   *gl_shaders;
337     UINT                            num_gl_shaders, shader_array_size;
338 };
339
340 struct shader_arb_priv
341 {
342     GLuint                  current_vprogram_id;
343     GLuint                  current_fprogram_id;
344     const struct arb_ps_compiled_shader *compiled_fprog;
345     const struct arb_vs_compiled_shader *compiled_vprog;
346     GLuint                  depth_blt_vprogram_id;
347     GLuint                  depth_blt_fprogram_id_full[tex_type_count];
348     GLuint                  depth_blt_fprogram_id_masked[tex_type_count];
349     BOOL                    use_arbfp_fixed_func;
350     struct wine_rb_tree     fragment_shaders;
351     BOOL                    last_ps_const_clamped;
352     BOOL                    last_vs_color_unclamp;
353
354     struct wine_rb_tree     signature_tree;
355     DWORD ps_sig_number;
356 };
357
358 /********************************************************
359  * ARB_[vertex/fragment]_program helper functions follow
360  ********************************************************/
361
362 /* Loads floating point constants into the currently set ARB_vertex/fragment_program.
363  * When constant_list == NULL, it will load all the constants.
364  *
365  * @target_type should be either GL_VERTEX_PROGRAM_ARB (for vertex shaders)
366  *  or GL_FRAGMENT_PROGRAM_ARB (for pixel shaders)
367  */
368 /* GL locking is done by the caller */
369 static unsigned int shader_arb_load_constantsF(IWineD3DBaseShaderImpl *This, const struct wined3d_gl_info *gl_info,
370         GLuint target_type, unsigned int max_constants, const float *constants, char *dirty_consts)
371 {
372     local_constant* lconst;
373     DWORD i, j;
374     unsigned int ret;
375
376     if (TRACE_ON(d3d_constants))
377     {
378         for(i = 0; i < max_constants; i++) {
379             if(!dirty_consts[i]) continue;
380             TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i,
381                         constants[i * 4 + 0], constants[i * 4 + 1],
382                         constants[i * 4 + 2], constants[i * 4 + 3]);
383         }
384     }
385
386     i = 0;
387
388     /* In 1.X pixel shaders constants are implicitly clamped in the range [-1;1] */
389     if (target_type == GL_FRAGMENT_PROGRAM_ARB && This->baseShader.reg_maps.shader_version.major == 1)
390     {
391         float lcl_const[4];
392         /* ps 1.x supports only 8 constants, clamp only those. When switching between 1.x and higher
393          * shaders, the first 8 constants are marked dirty for reload
394          */
395         for(; i < min(8, max_constants); i++) {
396             if(!dirty_consts[i]) continue;
397             dirty_consts[i] = 0;
398
399             j = 4 * i;
400             if (constants[j + 0] > 1.0f) lcl_const[0] = 1.0f;
401             else if (constants[j + 0] < -1.0f) lcl_const[0] = -1.0f;
402             else lcl_const[0] = constants[j + 0];
403
404             if (constants[j + 1] > 1.0f) lcl_const[1] = 1.0f;
405             else if (constants[j + 1] < -1.0f) lcl_const[1] = -1.0f;
406             else lcl_const[1] = constants[j + 1];
407
408             if (constants[j + 2] > 1.0f) lcl_const[2] = 1.0f;
409             else if (constants[j + 2] < -1.0f) lcl_const[2] = -1.0f;
410             else lcl_const[2] = constants[j + 2];
411
412             if (constants[j + 3] > 1.0f) lcl_const[3] = 1.0f;
413             else if (constants[j + 3] < -1.0f) lcl_const[3] = -1.0f;
414             else lcl_const[3] = constants[j + 3];
415
416             GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, lcl_const));
417         }
418
419         /* If further constants are dirty, reload them without clamping.
420          *
421          * The alternative is not to touch them, but then we cannot reset the dirty constant count
422          * to zero. That's bad for apps that only use PS 1.x shaders, because in that case the code
423          * above would always re-check the first 8 constants since max_constant remains at the init
424          * value
425          */
426     }
427
428     if (gl_info->supported[EXT_GPU_PROGRAM_PARAMETERS])
429     {
430         /* TODO: Benchmark if we're better of with finding the dirty constants ourselves,
431          * or just reloading *all* constants at once
432          *
433         GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, i, max_constants, constants + (i * 4)));
434          */
435         for(; i < max_constants; i++) {
436             if(!dirty_consts[i]) continue;
437
438             /* Find the next block of dirty constants */
439             dirty_consts[i] = 0;
440             j = i;
441             for(i++; (i < max_constants) && dirty_consts[i]; i++) {
442                 dirty_consts[i] = 0;
443             }
444
445             GL_EXTCALL(glProgramEnvParameters4fvEXT(target_type, j, i - j, constants + (j * 4)));
446         }
447     } else {
448         for(; i < max_constants; i++) {
449             if(dirty_consts[i]) {
450                 dirty_consts[i] = 0;
451                 GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, i, constants + (i * 4)));
452             }
453         }
454     }
455     checkGLcall("glProgramEnvParameter4fvARB()");
456
457     /* Load immediate constants */
458     if(This->baseShader.load_local_constsF) {
459         if (TRACE_ON(d3d_shader)) {
460             LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
461                 GLfloat* values = (GLfloat*)lconst->value;
462                 TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
463                         values[0], values[1], values[2], values[3]);
464             }
465         }
466         /* Immediate constants are clamped for 1.X shaders at loading times */
467         ret = 0;
468         LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
469             dirty_consts[lconst->idx] = 1; /* Dirtify so the non-immediate constant overwrites it next time */
470             ret = max(ret, lconst->idx + 1);
471             GL_EXTCALL(glProgramEnvParameter4fvARB(target_type, lconst->idx, (GLfloat*)lconst->value));
472         }
473         checkGLcall("glProgramEnvParameter4fvARB()");
474         return ret; /* The loaded immediate constants need reloading for the next shader */
475     } else {
476         return 0; /* No constants are dirty now */
477     }
478 }
479
480 /**
481  * Loads the texture dimensions for NP2 fixup into the currently set ARB_[vertex/fragment]_programs.
482  */
483 static void shader_arb_load_np2fixup_constants(
484     IWineD3DDevice* device,
485     char usePixelShader,
486     char useVertexShader) {
487
488     IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl *) device;
489     const struct shader_arb_priv* const priv = (const struct shader_arb_priv *) deviceImpl->shader_priv;
490     IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
491     const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info;
492
493     if (!usePixelShader) {
494         /* NP2 texcoord fixup is (currently) only done for pixelshaders. */
495         return;
496     }
497
498     if (priv->compiled_fprog && priv->compiled_fprog->np2fixup_info.super.active) {
499         const struct arb_ps_np2fixup_info* const fixup = &priv->compiled_fprog->np2fixup_info;
500         UINT i;
501         WORD active = fixup->super.active;
502         GLfloat np2fixup_constants[4 * MAX_FRAGMENT_SAMPLERS];
503
504         for (i = 0; active; active >>= 1, ++i) {
505             const unsigned char idx = fixup->super.idx[i];
506             const IWineD3DTextureImpl* const tex = (const IWineD3DTextureImpl*) stateBlock->textures[i];
507             GLfloat* tex_dim = &np2fixup_constants[(idx >> 1) * 4];
508
509             if (!(active & 1)) continue;
510
511             if (!tex) {
512                 FIXME("Nonexistent texture is flagged for NP2 texcoord fixup\n");
513                 continue;
514             }
515
516             if (idx % 2) {
517                 tex_dim[2] = tex->baseTexture.pow2Matrix[0]; tex_dim[3] = tex->baseTexture.pow2Matrix[5];
518             } else {
519                 tex_dim[0] = tex->baseTexture.pow2Matrix[0]; tex_dim[1] = tex->baseTexture.pow2Matrix[5];
520             }
521         }
522
523         for (i = 0; i < fixup->super.num_consts; ++i) {
524             GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
525                                                    fixup->offset + i, &np2fixup_constants[i * 4]));
526         }
527     }
528 }
529
530 /* GL locking is done by the caller. */
531 static inline void shader_arb_ps_local_constants(IWineD3DDeviceImpl* deviceImpl)
532 {
533     const struct wined3d_context *context = context_get_current();
534     IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
535     const struct wined3d_gl_info *gl_info = context->gl_info;
536     unsigned char i;
537     struct shader_arb_priv *priv = deviceImpl->shader_priv;
538     const struct arb_ps_compiled_shader *gl_shader = priv->compiled_fprog;
539
540     for(i = 0; i < gl_shader->numbumpenvmatconsts; i++)
541     {
542         int texunit = gl_shader->bumpenvmatconst[i].texunit;
543
544         /* The state manager takes care that this function is always called if the bump env matrix changes */
545         const float *data = (const float *)&stateBlock->textureState[texunit][WINED3DTSS_BUMPENVMAT00];
546         GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->bumpenvmatconst[i].const_num, data));
547
548         if (gl_shader->luminanceconst[i].const_num != WINED3D_CONST_NUM_UNUSED)
549         {
550             /* WINED3DTSS_BUMPENVLSCALE and WINED3DTSS_BUMPENVLOFFSET are next to each other.
551              * point gl to the scale, and load 4 floats. x = scale, y = offset, z and w are junk, we
552              * don't care about them. The pointers are valid for sure because the stateblock is bigger.
553              * (they're WINED3DTSS_TEXTURETRANSFORMFLAGS and WINED3DTSS_ADDRESSW, so most likely 0 or NaN
554             */
555             const float *scale = (const float *)&stateBlock->textureState[texunit][WINED3DTSS_BUMPENVLSCALE];
556             GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->luminanceconst[i].const_num, scale));
557         }
558     }
559     checkGLcall("Load bumpmap consts");
560
561     if(gl_shader->ycorrection != WINED3D_CONST_NUM_UNUSED)
562     {
563         /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen).
564         * ycorrection.y: -1.0(onscreen), 1.0(offscreen)
565         * ycorrection.z: 1.0
566         * ycorrection.w: 0.0
567         */
568         float val[4];
569         val[0] = context->render_offscreen ? 0.0f
570                 : deviceImpl->render_targets[0]->currentDesc.Height;
571         val[1] = context->render_offscreen ? 1.0f : -1.0f;
572         val[2] = 1.0f;
573         val[3] = 0.0f;
574         GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->ycorrection, val));
575         checkGLcall("y correction loading");
576     }
577
578     if(gl_shader->num_int_consts == 0) return;
579
580     for(i = 0; i < MAX_CONST_I; i++)
581     {
582         if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED)
583         {
584             float val[4];
585             val[0] = (float) stateBlock->pixelShaderConstantI[4 * i];
586             val[1] = (float) stateBlock->pixelShaderConstantI[4 * i + 1];
587             val[2] = (float) stateBlock->pixelShaderConstantI[4 * i + 2];
588             val[3] = -1.0f;
589
590             GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, gl_shader->int_consts[i], val));
591         }
592     }
593     checkGLcall("Load ps int consts");
594 }
595
596 /* GL locking is done by the caller. */
597 static inline void shader_arb_vs_local_constants(IWineD3DDeviceImpl* deviceImpl)
598 {
599     IWineD3DStateBlockImpl* stateBlock;
600     const struct wined3d_gl_info *gl_info = &deviceImpl->adapter->gl_info;
601     unsigned char i;
602     struct shader_arb_priv *priv = deviceImpl->shader_priv;
603     const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog;
604
605     /* Upload the position fixup */
606     GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->pos_fixup, deviceImpl->posFixup));
607
608     if(gl_shader->num_int_consts == 0) return;
609
610     stateBlock = deviceImpl->stateBlock;
611
612     for(i = 0; i < MAX_CONST_I; i++)
613     {
614         if(gl_shader->int_consts[i] != WINED3D_CONST_NUM_UNUSED)
615         {
616             float val[4];
617             val[0] = (float) stateBlock->vertexShaderConstantI[4 * i];
618             val[1] = (float) stateBlock->vertexShaderConstantI[4 * i + 1];
619             val[2] = (float) stateBlock->vertexShaderConstantI[4 * i + 2];
620             val[3] = -1.0f;
621
622             GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, gl_shader->int_consts[i], val));
623         }
624     }
625     checkGLcall("Load vs int consts");
626 }
627
628 /**
629  * Loads the app-supplied constants into the currently set ARB_[vertex/fragment]_programs.
630  *
631  * We only support float constants in ARB at the moment, so don't
632  * worry about the Integers or Booleans
633  */
634 /* GL locking is done by the caller (state handler) */
635 static void shader_arb_load_constants(const struct wined3d_context *context, char usePixelShader, char useVertexShader)
636 {
637     IWineD3DDeviceImpl *device = context->swapchain->device;
638     IWineD3DStateBlockImpl* stateBlock = device->stateBlock;
639     const struct wined3d_gl_info *gl_info = context->gl_info;
640
641     if (useVertexShader) {
642         IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
643
644         /* Load DirectX 9 float constants for vertex shader */
645         device->highest_dirty_vs_const = shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
646                 device->highest_dirty_vs_const, stateBlock->vertexShaderConstantF, context->vshader_const_dirty);
647         shader_arb_vs_local_constants(device);
648     }
649
650     if (usePixelShader) {
651         IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
652
653         /* Load DirectX 9 float constants for pixel shader */
654         device->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
655                 device->highest_dirty_ps_const, stateBlock->pixelShaderConstantF, context->pshader_const_dirty);
656         shader_arb_ps_local_constants(device);
657     }
658 }
659
660 static void shader_arb_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
661 {
662     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
663     struct wined3d_context *context = context_get_current();
664
665     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
666      * context. On a context switch the old context will be fully dirtified */
667     if (!context || context->swapchain->device != This) return;
668
669     memset(context->vshader_const_dirty + start, 1, sizeof(*context->vshader_const_dirty) * count);
670     This->highest_dirty_vs_const = max(This->highest_dirty_vs_const, start + count);
671 }
672
673 static void shader_arb_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
674 {
675     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
676     struct wined3d_context *context = context_get_current();
677
678     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
679      * context. On a context switch the old context will be fully dirtified */
680     if (!context || context->swapchain->device != This) return;
681
682     memset(context->pshader_const_dirty + start, 1, sizeof(*context->pshader_const_dirty) * count);
683     This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, start + count);
684 }
685
686 static DWORD *local_const_mapping(IWineD3DBaseShaderImpl *This)
687 {
688     DWORD *ret;
689     DWORD idx = 0;
690     const local_constant *lconst;
691
692     if(This->baseShader.load_local_constsF || list_empty(&This->baseShader.constantsF)) return NULL;
693
694     ret = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * This->baseShader.limits.constant_float);
695     if(!ret) {
696         ERR("Out of memory\n");
697         return NULL;
698     }
699
700     LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
701         ret[lconst->idx] = idx++;
702     }
703     return ret;
704 }
705
706 /* Generate the variable & register declarations for the ARB_vertex_program output target */
707 static DWORD shader_generate_arb_declarations(IWineD3DBaseShader *iface, const shader_reg_maps *reg_maps,
708         struct wined3d_shader_buffer *buffer, const struct wined3d_gl_info *gl_info, DWORD *lconst_map,
709         DWORD *num_clipplanes, struct shader_arb_ctx_priv *ctx)
710 {
711     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
712     DWORD i, next_local = 0;
713     char pshader = shader_is_pshader_version(reg_maps->shader_version.type);
714     unsigned max_constantsF;
715     const local_constant *lconst;
716     DWORD map;
717
718     /* In pixel shaders, all private constants are program local, we don't need anything
719      * from program.env. Thus we can advertise the full set of constants in pixel shaders.
720      * If we need a private constant the GL implementation will squeeze it in somewhere
721      *
722      * With vertex shaders we need the posFixup and on some GL implementations 4 helper
723      * immediate values. The posFixup is loaded using program.env for now, so always
724      * subtract one from the number of constants. If the shader uses indirect addressing,
725      * account for the helper const too because we have to declare all availabke d3d constants
726      * and don't know which are actually used.
727      */
728     if (pshader)
729     {
730         max_constantsF = gl_info->limits.arb_ps_native_constants;
731         /* 24 is the minimum MAX_PROGRAM_ENV_PARAMETERS_ARB value. */
732         if (max_constantsF < 24)
733             max_constantsF = gl_info->limits.arb_ps_float_constants;
734     }
735     else
736     {
737         max_constantsF = gl_info->limits.arb_vs_native_constants;
738         /* 96 is the minimum MAX_PROGRAM_ENV_PARAMETERS_ARB value.
739          * Also prevents max_constantsF from becoming less than 0 and
740          * wrapping . */
741         if (max_constantsF < 96)
742             max_constantsF = gl_info->limits.arb_vs_float_constants;
743
744         if(This->baseShader.reg_maps.usesrelconstF) {
745             DWORD highest_constf = 0, clip_limit;
746
747             max_constantsF -= reserved_vs_const(This, gl_info);
748             max_constantsF -= count_bits(This->baseShader.reg_maps.integer_constants);
749
750             for(i = 0; i < This->baseShader.limits.constant_float; i++)
751             {
752                 DWORD idx = i >> 5;
753                 DWORD shift = i & 0x1f;
754                 if(reg_maps->constf[idx] & (1 << shift)) highest_constf = i;
755             }
756
757             if(use_nv_clip(gl_info) && ctx->target_version >= NV2)
758             {
759                 if(ctx->cur_vs_args->super.clip_enabled)
760                     clip_limit = gl_info->limits.clipplanes;
761                 else
762                     clip_limit = 0;
763             }
764             else
765             {
766                 unsigned int mask = ctx->cur_vs_args->clip.boolclip.clipplane_mask;
767                 clip_limit = min(count_bits(mask), 4);
768             }
769             *num_clipplanes = min(clip_limit, max_constantsF - highest_constf - 1);
770             max_constantsF -= *num_clipplanes;
771             if(*num_clipplanes < clip_limit)
772             {
773                 WARN("Only %u clipplanes out of %u enabled\n", *num_clipplanes, gl_info->limits.clipplanes);
774             }
775         }
776         else
777         {
778             if (ctx->target_version >= NV2) *num_clipplanes = gl_info->limits.clipplanes;
779             else *num_clipplanes = min(gl_info->limits.clipplanes, 4);
780         }
781     }
782
783     for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
784     {
785         if (map & 1) shader_addline(buffer, "TEMP R%u;\n", i);
786     }
787
788     for (i = 0, map = reg_maps->address; map; map >>= 1, ++i)
789     {
790         if (map & 1) shader_addline(buffer, "ADDRESS A%u;\n", i);
791     }
792
793     if (pshader && reg_maps->shader_version.major == 1 && reg_maps->shader_version.minor <= 3)
794     {
795         for (i = 0, map = reg_maps->texcoord; map; map >>= 1, ++i)
796         {
797             if (map & 1) shader_addline(buffer, "TEMP T%u;\n", i);
798         }
799     }
800
801     /* Load local constants using the program-local space,
802      * this avoids reloading them each time the shader is used
803      */
804     if(lconst_map) {
805         LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
806             shader_addline(buffer, "PARAM C%u = program.local[%u];\n", lconst->idx,
807                            lconst_map[lconst->idx]);
808             next_local = max(next_local, lconst_map[lconst->idx] + 1);
809         }
810     }
811
812     /* After subtracting privately used constants from the hardware limit(they are loaded as
813      * local constants), make sure the shader doesn't violate the env constant limit
814      */
815     if(pshader)
816     {
817         max_constantsF = min(max_constantsF, gl_info->limits.arb_ps_float_constants);
818     }
819     else
820     {
821         max_constantsF = min(max_constantsF, gl_info->limits.arb_vs_float_constants);
822     }
823
824     /* Avoid declaring more constants than needed */
825     max_constantsF = min(max_constantsF, This->baseShader.limits.constant_float);
826
827     /* we use the array-based constants array if the local constants are marked for loading,
828      * because then we use indirect addressing, or when the local constant list is empty,
829      * because then we don't know if we're using indirect addressing or not. If we're hardcoding
830      * local constants do not declare the loaded constants as an array because ARB compilers usually
831      * do not optimize unused constants away
832      */
833     if(This->baseShader.reg_maps.usesrelconstF) {
834         /* Need to PARAM the environment parameters (constants) so we can use relative addressing */
835         shader_addline(buffer, "PARAM C[%d] = { program.env[0..%d] };\n",
836                     max_constantsF, max_constantsF - 1);
837     } else {
838         for(i = 0; i < max_constantsF; i++) {
839             DWORD idx, mask;
840             idx = i >> 5;
841             mask = 1 << (i & 0x1f);
842             if(!shader_constant_is_local(This, i) && (This->baseShader.reg_maps.constf[idx] & mask)) {
843                 shader_addline(buffer, "PARAM C%d = program.env[%d];\n",i, i);
844             }
845         }
846     }
847
848     return next_local;
849 }
850
851 static const char * const shift_tab[] = {
852     "dummy",     /*  0 (none) */
853     "coefmul.x", /*  1 (x2)   */
854     "coefmul.y", /*  2 (x4)   */
855     "coefmul.z", /*  3 (x8)   */
856     "coefmul.w", /*  4 (x16)  */
857     "dummy",     /*  5 (x32)  */
858     "dummy",     /*  6 (x64)  */
859     "dummy",     /*  7 (x128) */
860     "dummy",     /*  8 (d256) */
861     "dummy",     /*  9 (d128) */
862     "dummy",     /* 10 (d64)  */
863     "dummy",     /* 11 (d32)  */
864     "coefdiv.w", /* 12 (d16)  */
865     "coefdiv.z", /* 13 (d8)   */
866     "coefdiv.y", /* 14 (d4)   */
867     "coefdiv.x"  /* 15 (d2)   */
868 };
869
870 static void shader_arb_get_write_mask(const struct wined3d_shader_instruction *ins,
871         const struct wined3d_shader_dst_param *dst, char *write_mask)
872 {
873     char *ptr = write_mask;
874
875     if (dst->write_mask != WINED3DSP_WRITEMASK_ALL)
876     {
877         *ptr++ = '.';
878         if (dst->write_mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x';
879         if (dst->write_mask & WINED3DSP_WRITEMASK_1) *ptr++ = 'y';
880         if (dst->write_mask & WINED3DSP_WRITEMASK_2) *ptr++ = 'z';
881         if (dst->write_mask & WINED3DSP_WRITEMASK_3) *ptr++ = 'w';
882     }
883
884     *ptr = '\0';
885 }
886
887 static void shader_arb_get_swizzle(const struct wined3d_shader_src_param *param, BOOL fixup, char *swizzle_str)
888 {
889     /* For registers of type WINED3DDECLTYPE_D3DCOLOR, data is stored as "bgra",
890      * but addressed as "rgba". To fix this we need to swap the register's x
891      * and z components. */
892     const char *swizzle_chars = fixup ? "zyxw" : "xyzw";
893     char *ptr = swizzle_str;
894
895     /* swizzle bits fields: wwzzyyxx */
896     DWORD swizzle = param->swizzle;
897     DWORD swizzle_x = swizzle & 0x03;
898     DWORD swizzle_y = (swizzle >> 2) & 0x03;
899     DWORD swizzle_z = (swizzle >> 4) & 0x03;
900     DWORD swizzle_w = (swizzle >> 6) & 0x03;
901
902     /* If the swizzle is the default swizzle (ie, "xyzw"), we don't need to
903      * generate a swizzle string. Unless we need to our own swizzling. */
904     if (swizzle != WINED3DSP_NOSWIZZLE || fixup)
905     {
906         *ptr++ = '.';
907         if (swizzle_x == swizzle_y && swizzle_x == swizzle_z && swizzle_x == swizzle_w) {
908             *ptr++ = swizzle_chars[swizzle_x];
909         } else {
910             *ptr++ = swizzle_chars[swizzle_x];
911             *ptr++ = swizzle_chars[swizzle_y];
912             *ptr++ = swizzle_chars[swizzle_z];
913             *ptr++ = swizzle_chars[swizzle_w];
914         }
915     }
916
917     *ptr = '\0';
918 }
919
920 static void shader_arb_request_a0(const struct wined3d_shader_instruction *ins, const char *src)
921 {
922     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
923     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
924
925     if(strcmp(priv->addr_reg, src) == 0) return;
926
927     strcpy(priv->addr_reg, src);
928     shader_addline(buffer, "ARL A0.x, %s;\n", src);
929 }
930
931 static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
932         const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr);
933
934 static void shader_arb_get_register_name(const struct wined3d_shader_instruction *ins,
935         const struct wined3d_shader_register *reg, char *register_name, BOOL *is_color)
936 {
937     /* oPos, oFog and oPts in D3D */
938     static const char * const rastout_reg_names[] = {"TMP_OUT", "result.fogcoord", "result.pointsize"};
939     IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
940     BOOL pshader = shader_is_pshader_version(This->baseShader.reg_maps.shader_version.type);
941     struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
942
943     *is_color = FALSE;
944
945     switch (reg->type)
946     {
947         case WINED3DSPR_TEMP:
948             sprintf(register_name, "R%u", reg->idx);
949             break;
950
951         case WINED3DSPR_INPUT:
952             if (pshader)
953             {
954                 if(This->baseShader.reg_maps.shader_version.major < 3)
955                 {
956                     if (reg->idx == 0) strcpy(register_name, "fragment.color.primary");
957                     else strcpy(register_name, "fragment.color.secondary");
958                 }
959                 else
960                 {
961                     if(reg->rel_addr)
962                     {
963                         char rel_reg[50];
964                         shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg);
965
966                         if(strcmp(rel_reg, "**aL_emul**") == 0)
967                         {
968                             DWORD idx = ctx->aL + reg->idx;
969                             if(idx < MAX_REG_INPUT)
970                             {
971                                 strcpy(register_name, ctx->ps_input[idx]);
972                             }
973                             else
974                             {
975                                 ERR("Pixel shader input register out of bounds: %u\n", idx);
976                                 sprintf(register_name, "out_of_bounds_%u", idx);
977                             }
978                         }
979                         else if(This->baseShader.reg_maps.input_registers & 0x0300)
980                         {
981                             /* There are two ways basically:
982                              *
983                              * 1) Use the unrolling code that is used for loop emulation and unroll the loop.
984                              *    That means trouble if the loop also contains a breakc or if the control values
985                              *    aren't local constants.
986                              * 2) Generate an if block that checks if aL.y < 8, == 8 or == 9 and selects the
987                              *    source dynamically. The trouble is that we cannot simply read aL.y because it
988                              *    is an ADDRESS register. We could however push it, load .zw with a value and use
989                              *    ADAC to load the condition code register and pop it again afterwards
990                              */
991                             FIXME("Relative input register addressing with more than 8 registers\n");
992
993                             /* This is better than nothing for now */
994                             sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx);
995                         }
996                         else if(ctx->cur_ps_args->super.vp_mode != vertexshader)
997                         {
998                             /* This is problematic because we'd have to consult the ctx->ps_input strings
999                              * for where to find the varying. Some may be "0.0", others can be texcoords or
1000                              * colors. This needs either a pipeline replacement to make the vertex shader feed
1001                              * proper varyings, or loop unrolling
1002                              *
1003                              * For now use the texcoords and hope for the best
1004                              */
1005                             FIXME("Non-vertex shader varying input with indirect addressing\n");
1006                             sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx);
1007                         }
1008                         else
1009                         {
1010                             /* D3D supports indirect addressing only with aL in loop registers. The loop instruction
1011                              * pulls GL_NV_fragment_program2 in
1012                              */
1013                             sprintf(register_name, "fragment.texcoord[%s + %u]", rel_reg, reg->idx);
1014                         }
1015                     }
1016                     else
1017                     {
1018                         if(reg->idx < MAX_REG_INPUT)
1019                         {
1020                             strcpy(register_name, ctx->ps_input[reg->idx]);
1021                         }
1022                         else
1023                         {
1024                             ERR("Pixel shader input register out of bounds: %u\n", reg->idx);
1025                             sprintf(register_name, "out_of_bounds_%u", reg->idx);
1026                         }
1027                     }
1028                 }
1029             }
1030             else
1031             {
1032                 if (ctx->cur_vs_args->super.swizzle_map & (1 << reg->idx)) *is_color = TRUE;
1033                 sprintf(register_name, "vertex.attrib[%u]", reg->idx);
1034             }
1035             break;
1036
1037         case WINED3DSPR_CONST:
1038             if (!pshader && reg->rel_addr)
1039             {
1040                 BOOL aL = FALSE;
1041                 char rel_reg[50];
1042                 UINT rel_offset = ((IWineD3DVertexShaderImpl *)This)->rel_offset;
1043                 if(This->baseShader.reg_maps.shader_version.major < 2) {
1044                     sprintf(rel_reg, "A0.x");
1045                 } else {
1046                     shader_arb_get_src_param(ins, reg->rel_addr, 0, rel_reg);
1047                     if(ctx->target_version == ARB) {
1048                         if(strcmp(rel_reg, "**aL_emul**") == 0) {
1049                             aL = TRUE;
1050                         } else {
1051                             shader_arb_request_a0(ins, rel_reg);
1052                             sprintf(rel_reg, "A0.x");
1053                         }
1054                     }
1055                 }
1056                 if(aL)
1057                     sprintf(register_name, "C[%u]", ctx->aL + reg->idx);
1058                 else if (reg->idx >= rel_offset)
1059                     sprintf(register_name, "C[%s + %u]", rel_reg, reg->idx - rel_offset);
1060                 else
1061                     sprintf(register_name, "C[%s - %u]", rel_reg, rel_offset - reg->idx);
1062             }
1063             else
1064             {
1065                 if (This->baseShader.reg_maps.usesrelconstF)
1066                     sprintf(register_name, "C[%u]", reg->idx);
1067                 else
1068                     sprintf(register_name, "C%u", reg->idx);
1069             }
1070             break;
1071
1072         case WINED3DSPR_TEXTURE: /* case WINED3DSPR_ADDR: */
1073             if (pshader) {
1074                 if(This->baseShader.reg_maps.shader_version.major == 1 &&
1075                    This->baseShader.reg_maps.shader_version.minor <= 3) {
1076                     /* In ps <= 1.3, Tx is a temporary register as destination to all instructions,
1077                      * and as source to most instructions. For some instructions it is the texcoord
1078                      * input. Those instructions know about the special use
1079                      */
1080                     sprintf(register_name, "T%u", reg->idx);
1081                 } else {
1082                     /* in ps 1.4 and 2.x Tx is always a (read-only) varying */
1083                     sprintf(register_name, "fragment.texcoord[%u]", reg->idx);
1084                 }
1085             }
1086             else
1087             {
1088                 if(This->baseShader.reg_maps.shader_version.major == 1 || ctx->target_version >= NV2)
1089                 {
1090                     sprintf(register_name, "A%u", reg->idx);
1091                 }
1092                 else
1093                 {
1094                     sprintf(register_name, "A%u_SHADOW", reg->idx);
1095                 }
1096             }
1097             break;
1098
1099         case WINED3DSPR_COLOROUT:
1100             if(ctx->cur_ps_args->super.srgb_correction && reg->idx == 0)
1101             {
1102                 strcpy(register_name, "TMP_COLOR");
1103             }
1104             else
1105             {
1106                 if(ctx->cur_ps_args->super.srgb_correction) FIXME("sRGB correction on higher render targets\n");
1107                 if(This->baseShader.reg_maps.highest_render_target > 0)
1108                 {
1109                     sprintf(register_name, "result.color[%u]", reg->idx);
1110                 }
1111                 else
1112                 {
1113                     strcpy(register_name, "result.color");
1114                 }
1115             }
1116             break;
1117
1118         case WINED3DSPR_RASTOUT:
1119             if(reg->idx == 1) sprintf(register_name, "%s", ctx->fog_output);
1120             else sprintf(register_name, "%s", rastout_reg_names[reg->idx]);
1121             break;
1122
1123         case WINED3DSPR_DEPTHOUT:
1124             strcpy(register_name, "result.depth");
1125             break;
1126
1127         case WINED3DSPR_ATTROUT:
1128         /* case WINED3DSPR_OUTPUT: */
1129             if (pshader) sprintf(register_name, "oD[%u]", reg->idx);
1130             else strcpy(register_name, ctx->color_output[reg->idx]);
1131             break;
1132
1133         case WINED3DSPR_TEXCRDOUT:
1134             if (pshader)
1135             {
1136                 sprintf(register_name, "oT[%u]", reg->idx);
1137             }
1138             else
1139             {
1140                 if(This->baseShader.reg_maps.shader_version.major < 3)
1141                 {
1142                     strcpy(register_name, ctx->texcrd_output[reg->idx]);
1143                 }
1144                 else
1145                 {
1146                     strcpy(register_name, ctx->vs_output[reg->idx]);
1147                 }
1148             }
1149             break;
1150
1151         case WINED3DSPR_LOOP:
1152             if(ctx->target_version >= NV2)
1153             {
1154                 /* Pshader has an implicitly declared loop index counter A0.x that cannot be renamed */
1155                 if(pshader) sprintf(register_name, "A0.x");
1156                 else sprintf(register_name, "aL.y");
1157             }
1158             else
1159             {
1160                 /* Unfortunately this code cannot return the value of ctx->aL here. An immediate value
1161                  * would be valid, but if aL is used for indexing(its only use), there's likely an offset,
1162                  * thus the result would be something like C[15 + 30], which is not valid in the ARB program
1163                  * grammar. So return a marker for the emulated aL and intercept it in constant and varying
1164                  * indexing
1165                  */
1166                 sprintf(register_name, "**aL_emul**");
1167             }
1168
1169             break;
1170
1171         case WINED3DSPR_CONSTINT:
1172             sprintf(register_name, "I%u", reg->idx);
1173             break;
1174
1175         case WINED3DSPR_MISCTYPE:
1176             if(reg->idx == 0)
1177             {
1178                 sprintf(register_name, "vpos");
1179             }
1180             else if(reg->idx == 1)
1181             {
1182                 sprintf(register_name, "fragment.facing.x");
1183             }
1184             else
1185             {
1186                 FIXME("Unknown MISCTYPE register index %u\n", reg->idx);
1187             }
1188             break;
1189
1190         default:
1191             FIXME("Unhandled register type %#x[%u]\n", reg->type, reg->idx);
1192             sprintf(register_name, "unrecognized_register[%u]", reg->idx);
1193             break;
1194     }
1195 }
1196
1197 static void shader_arb_get_dst_param(const struct wined3d_shader_instruction *ins,
1198         const struct wined3d_shader_dst_param *wined3d_dst, char *str)
1199 {
1200     char register_name[255];
1201     char write_mask[6];
1202     BOOL is_color;
1203
1204     shader_arb_get_register_name(ins, &wined3d_dst->reg, register_name, &is_color);
1205     strcpy(str, register_name);
1206
1207     shader_arb_get_write_mask(ins, wined3d_dst, write_mask);
1208     strcat(str, write_mask);
1209 }
1210
1211 static const char *shader_arb_get_fixup_swizzle(enum fixup_channel_source channel_source)
1212 {
1213     switch(channel_source)
1214     {
1215         case CHANNEL_SOURCE_ZERO: return "0";
1216         case CHANNEL_SOURCE_ONE: return "1";
1217         case CHANNEL_SOURCE_X: return "x";
1218         case CHANNEL_SOURCE_Y: return "y";
1219         case CHANNEL_SOURCE_Z: return "z";
1220         case CHANNEL_SOURCE_W: return "w";
1221         default:
1222             FIXME("Unhandled channel source %#x\n", channel_source);
1223             return "undefined";
1224     }
1225 }
1226
1227 static void gen_color_correction(struct wined3d_shader_buffer *buffer, const char *reg,
1228         DWORD dst_mask, const char *one, const char *two, struct color_fixup_desc fixup)
1229 {
1230     DWORD mask;
1231
1232     if (is_complex_fixup(fixup))
1233     {
1234         enum complex_fixup complex_fixup = get_complex_fixup(fixup);
1235         FIXME("Complex fixup (%#x) not supported\n", complex_fixup);
1236         return;
1237     }
1238
1239     mask = 0;
1240     if (fixup.x_source != CHANNEL_SOURCE_X) mask |= WINED3DSP_WRITEMASK_0;
1241     if (fixup.y_source != CHANNEL_SOURCE_Y) mask |= WINED3DSP_WRITEMASK_1;
1242     if (fixup.z_source != CHANNEL_SOURCE_Z) mask |= WINED3DSP_WRITEMASK_2;
1243     if (fixup.w_source != CHANNEL_SOURCE_W) mask |= WINED3DSP_WRITEMASK_3;
1244     mask &= dst_mask;
1245
1246     if (mask)
1247     {
1248         shader_addline(buffer, "SWZ %s, %s, %s, %s, %s, %s;\n", reg, reg,
1249                 shader_arb_get_fixup_swizzle(fixup.x_source), shader_arb_get_fixup_swizzle(fixup.y_source),
1250                 shader_arb_get_fixup_swizzle(fixup.z_source), shader_arb_get_fixup_swizzle(fixup.w_source));
1251     }
1252
1253     mask = 0;
1254     if (fixup.x_sign_fixup) mask |= WINED3DSP_WRITEMASK_0;
1255     if (fixup.y_sign_fixup) mask |= WINED3DSP_WRITEMASK_1;
1256     if (fixup.z_sign_fixup) mask |= WINED3DSP_WRITEMASK_2;
1257     if (fixup.w_sign_fixup) mask |= WINED3DSP_WRITEMASK_3;
1258     mask &= dst_mask;
1259
1260     if (mask)
1261     {
1262         char reg_mask[6];
1263         char *ptr = reg_mask;
1264
1265         if (mask != WINED3DSP_WRITEMASK_ALL)
1266         {
1267             *ptr++ = '.';
1268             if (mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x';
1269             if (mask & WINED3DSP_WRITEMASK_1) *ptr++ = 'y';
1270             if (mask & WINED3DSP_WRITEMASK_2) *ptr++ = 'z';
1271             if (mask & WINED3DSP_WRITEMASK_3) *ptr++ = 'w';
1272         }
1273         *ptr = '\0';
1274
1275         shader_addline(buffer, "MAD %s%s, %s, %s, -%s;\n", reg, reg_mask, reg, two, one);
1276     }
1277 }
1278
1279 static const char *shader_arb_get_modifier(const struct wined3d_shader_instruction *ins)
1280 {
1281     DWORD mod;
1282     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
1283     if (!ins->dst_count) return "";
1284
1285     mod = ins->dst[0].modifiers;
1286
1287     /* Silently ignore PARTIALPRECISION if its not supported */
1288     if(priv->target_version == ARB) mod &= ~WINED3DSPDM_PARTIALPRECISION;
1289
1290     if(mod & WINED3DSPDM_MSAMPCENTROID)
1291     {
1292         FIXME("Unhandled modifier WINED3DSPDM_MSAMPCENTROID\n");
1293         mod &= ~WINED3DSPDM_MSAMPCENTROID;
1294     }
1295
1296     switch(mod)
1297     {
1298         case WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION:
1299             return "H_SAT";
1300
1301         case WINED3DSPDM_SATURATE:
1302             return "_SAT";
1303
1304         case WINED3DSPDM_PARTIALPRECISION:
1305             return "H";
1306
1307         case 0:
1308             return "";
1309
1310         default:
1311             FIXME("Unknown modifiers 0x%08x\n", mod);
1312             return "";
1313     }
1314 }
1315
1316 #define TEX_PROJ        0x1
1317 #define TEX_BIAS        0x2
1318 #define TEX_LOD         0x4
1319 #define TEX_DERIV       0x10
1320
1321 static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx,
1322         const char *dst_str, const char *coord_reg, WORD flags, const char *dsx, const char *dsy)
1323 {
1324     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1325     DWORD sampler_type = ins->ctx->reg_maps->sampler_type[sampler_idx];
1326     const char *tex_type;
1327     BOOL np2_fixup = FALSE;
1328     IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
1329     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
1330     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
1331     const char *mod;
1332     BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type);
1333
1334     /* D3D vertex shader sampler IDs are vertex samplers(0-3), not global d3d samplers */
1335     if(!pshader) sampler_idx += MAX_FRAGMENT_SAMPLERS;
1336
1337     switch(sampler_type) {
1338         case WINED3DSTT_1D:
1339             tex_type = "1D";
1340             break;
1341
1342         case WINED3DSTT_2D:
1343             if(device->stateBlock->textures[sampler_idx] &&
1344                IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
1345                 tex_type = "RECT";
1346             } else {
1347                 tex_type = "2D";
1348             }
1349             if (shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type))
1350             {
1351                 if (priv->cur_np2fixup_info->super.active & (1 << sampler_idx))
1352                 {
1353                     if (flags) FIXME("Only ordinary sampling from NP2 textures is supported.\n");
1354                     else np2_fixup = TRUE;
1355                 }
1356             }
1357             break;
1358
1359         case WINED3DSTT_VOLUME:
1360             tex_type = "3D";
1361             break;
1362
1363         case WINED3DSTT_CUBE:
1364             tex_type = "CUBE";
1365             break;
1366
1367         default:
1368             ERR("Unexpected texture type %d\n", sampler_type);
1369             tex_type = "";
1370     }
1371
1372     /* TEX, TXL, TXD and TXP do not support the "H" modifier,
1373      * so don't use shader_arb_get_modifier
1374      */
1375     if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) mod = "_SAT";
1376     else mod = "";
1377
1378     /* Fragment samplers always have indentity mapping */
1379     if(sampler_idx >= MAX_FRAGMENT_SAMPLERS)
1380     {
1381         sampler_idx = priv->cur_vs_args->vertex.samplers[sampler_idx - MAX_FRAGMENT_SAMPLERS];
1382     }
1383
1384     if (flags & TEX_DERIV)
1385     {
1386         if(flags & TEX_PROJ) FIXME("Projected texture sampling with custom derivatives\n");
1387         if(flags & TEX_BIAS) FIXME("Biased texture sampling with custom derivatives\n");
1388         shader_addline(buffer, "TXD%s %s, %s, %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg,
1389                        dsx, dsy,sampler_idx, tex_type);
1390     }
1391     else if(flags & TEX_LOD)
1392     {
1393         if(flags & TEX_PROJ) FIXME("Projected texture sampling with explicit lod\n");
1394         if(flags & TEX_BIAS) FIXME("Biased texture sampling with explicit lod\n");
1395         shader_addline(buffer, "TXL%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg,
1396                        sampler_idx, tex_type);
1397     }
1398     else if (flags & TEX_BIAS)
1399     {
1400         /* Shouldn't be possible, but let's check for it */
1401         if(flags & TEX_PROJ) FIXME("Biased and Projected texture sampling\n");
1402         /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */
1403         shader_addline(buffer, "TXB%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type);
1404     }
1405     else if (flags & TEX_PROJ)
1406     {
1407         shader_addline(buffer, "TXP%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type);
1408     }
1409     else
1410     {
1411         if (np2_fixup)
1412         {
1413             const unsigned char idx = priv->cur_np2fixup_info->super.idx[sampler_idx];
1414             shader_addline(buffer, "MUL TA, np2fixup[%u].%s, %s;\n", idx >> 1,
1415                            (idx % 2) ? "zwxy" : "xyzw", coord_reg);
1416
1417             shader_addline(buffer, "TEX%s %s, TA, texture[%u], %s;\n", mod, dst_str, sampler_idx, tex_type);
1418         }
1419         else
1420             shader_addline(buffer, "TEX%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type);
1421     }
1422
1423     if (pshader)
1424     {
1425         gen_color_correction(buffer, dst_str, ins->dst[0].write_mask,
1426                 arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_ONE),
1427                 arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_TWO),
1428                 priv->cur_ps_args->super.color_fixup[sampler_idx]);
1429     }
1430 }
1431
1432 static void shader_arb_get_src_param(const struct wined3d_shader_instruction *ins,
1433         const struct wined3d_shader_src_param *src, unsigned int tmpreg, char *outregstr)
1434 {
1435     /* Generate a line that does the input modifier computation and return the input register to use */
1436     BOOL is_color = FALSE;
1437     char regstr[256];
1438     char swzstr[20];
1439     int insert_line;
1440     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1441     struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
1442     const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
1443     const char *two = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_TWO);
1444
1445     /* Assume a new line will be added */
1446     insert_line = 1;
1447
1448     /* Get register name */
1449     shader_arb_get_register_name(ins, &src->reg, regstr, &is_color);
1450     shader_arb_get_swizzle(src, is_color, swzstr);
1451
1452     switch (src->modifiers)
1453     {
1454     case WINED3DSPSM_NONE:
1455         sprintf(outregstr, "%s%s", regstr, swzstr);
1456         insert_line = 0;
1457         break;
1458     case WINED3DSPSM_NEG:
1459         sprintf(outregstr, "-%s%s", regstr, swzstr);
1460         insert_line = 0;
1461         break;
1462     case WINED3DSPSM_BIAS:
1463         shader_addline(buffer, "ADD T%c, %s, -coefdiv.x;\n", 'A' + tmpreg, regstr);
1464         break;
1465     case WINED3DSPSM_BIASNEG:
1466         shader_addline(buffer, "ADD T%c, -%s, coefdiv.x;\n", 'A' + tmpreg, regstr);
1467         break;
1468     case WINED3DSPSM_SIGN:
1469         shader_addline(buffer, "MAD T%c, %s, %s, -%s;\n", 'A' + tmpreg, regstr, two, one);
1470         break;
1471     case WINED3DSPSM_SIGNNEG:
1472         shader_addline(buffer, "MAD T%c, %s, %s, %s;\n", 'A' + tmpreg, regstr, two, one);
1473         break;
1474     case WINED3DSPSM_COMP:
1475         shader_addline(buffer, "SUB T%c, %s, %s;\n", 'A' + tmpreg, one, regstr);
1476         break;
1477     case WINED3DSPSM_X2:
1478         shader_addline(buffer, "ADD T%c, %s, %s;\n", 'A' + tmpreg, regstr, regstr);
1479         break;
1480     case WINED3DSPSM_X2NEG:
1481         shader_addline(buffer, "ADD T%c, -%s, -%s;\n", 'A' + tmpreg, regstr, regstr);
1482         break;
1483     case WINED3DSPSM_DZ:
1484         shader_addline(buffer, "RCP T%c, %s.z;\n", 'A' + tmpreg, regstr);
1485         shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg);
1486         break;
1487     case WINED3DSPSM_DW:
1488         shader_addline(buffer, "RCP T%c, %s.w;\n", 'A' + tmpreg, regstr);
1489         shader_addline(buffer, "MUL T%c, %s, T%c;\n", 'A' + tmpreg, regstr, 'A' + tmpreg);
1490         break;
1491     case WINED3DSPSM_ABS:
1492         if(ctx->target_version >= NV2) {
1493             sprintf(outregstr, "|%s%s|", regstr, swzstr);
1494             insert_line = 0;
1495         } else {
1496             shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr);
1497         }
1498         break;
1499     case WINED3DSPSM_ABSNEG:
1500         if(ctx->target_version >= NV2) {
1501             sprintf(outregstr, "-|%s%s|", regstr, swzstr);
1502         } else {
1503             shader_addline(buffer, "ABS T%c, %s;\n", 'A' + tmpreg, regstr);
1504             sprintf(outregstr, "-T%c%s", 'A' + tmpreg, swzstr);
1505         }
1506         insert_line = 0;
1507         break;
1508     default:
1509         sprintf(outregstr, "%s%s", regstr, swzstr);
1510         insert_line = 0;
1511     }
1512
1513     /* Return modified or original register, with swizzle */
1514     if (insert_line)
1515         sprintf(outregstr, "T%c%s", 'A' + tmpreg, swzstr);
1516 }
1517
1518 static void pshader_hw_bem(const struct wined3d_shader_instruction *ins)
1519 {
1520     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1521     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1522     char dst_name[50];
1523     char src_name[2][50];
1524     DWORD sampler_code = dst->reg.idx;
1525
1526     shader_arb_get_dst_param(ins, dst, dst_name);
1527
1528     /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed
1529      *
1530      * Keep in mind that src_name[1] can be "TB" and src_name[0] can be "TA" because modifiers like _x2 are valid
1531      * with bem. So delay loading the first parameter until after the perturbation calculation which needs two
1532      * temps is done.
1533      */
1534     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
1535     shader_addline(buffer, "SWZ TA, bumpenvmat%d, x, z, 0, 0;\n", sampler_code);
1536     shader_addline(buffer, "DP3 TC.r, TA, %s;\n", src_name[1]);
1537     shader_addline(buffer, "SWZ TA, bumpenvmat%d, y, w, 0, 0;\n", sampler_code);
1538     shader_addline(buffer, "DP3 TC.g, TA, %s;\n", src_name[1]);
1539
1540     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
1541     shader_addline(buffer, "ADD %s, %s, TC;\n", dst_name, src_name[0]);
1542 }
1543
1544 static DWORD negate_modifiers(DWORD mod, char *extra_char)
1545 {
1546     *extra_char = ' ';
1547     switch(mod)
1548     {
1549         case WINED3DSPSM_NONE:      return WINED3DSPSM_NEG;
1550         case WINED3DSPSM_NEG:       return WINED3DSPSM_NONE;
1551         case WINED3DSPSM_BIAS:      return WINED3DSPSM_BIASNEG;
1552         case WINED3DSPSM_BIASNEG:   return WINED3DSPSM_BIAS;
1553         case WINED3DSPSM_SIGN:      return WINED3DSPSM_SIGNNEG;
1554         case WINED3DSPSM_SIGNNEG:   return WINED3DSPSM_SIGN;
1555         case WINED3DSPSM_COMP:      *extra_char = '-'; return WINED3DSPSM_COMP;
1556         case WINED3DSPSM_X2:        return WINED3DSPSM_X2NEG;
1557         case WINED3DSPSM_X2NEG:     return WINED3DSPSM_X2;
1558         case WINED3DSPSM_DZ:        *extra_char = '-'; return WINED3DSPSM_DZ;
1559         case WINED3DSPSM_DW:        *extra_char = '-'; return WINED3DSPSM_DW;
1560         case WINED3DSPSM_ABS:       return WINED3DSPSM_ABSNEG;
1561         case WINED3DSPSM_ABSNEG:    return WINED3DSPSM_ABS;
1562     }
1563     FIXME("Unknown modifier %u\n", mod);
1564     return mod;
1565 }
1566
1567 static void pshader_hw_cnd(const struct wined3d_shader_instruction *ins)
1568 {
1569     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1570     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1571     char dst_name[50];
1572     char src_name[3][50];
1573     DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
1574             ins->ctx->reg_maps->shader_version.minor);
1575     BOOL is_color;
1576
1577     shader_arb_get_dst_param(ins, dst, dst_name);
1578     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
1579
1580     /* The coissue flag changes the semantic of the cnd instruction in <= 1.3 shaders */
1581     if (shader_version <= WINED3D_SHADER_VERSION(1, 3) && ins->coissue)
1582     {
1583         shader_addline(buffer, "MOV%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[1]);
1584     } else {
1585         struct wined3d_shader_src_param src0_copy = ins->src[0];
1586         char extra_neg;
1587
1588         /* src0 may have a negate srcmod set, so we can't blindly add "-" to the name */
1589         src0_copy.modifiers = negate_modifiers(src0_copy.modifiers, &extra_neg);
1590
1591         shader_arb_get_src_param(ins, &src0_copy, 0, src_name[0]);
1592         shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
1593         shader_addline(buffer, "ADD TA, %c%s, coefdiv.x;\n", extra_neg, src_name[0]);
1594         /* No modifiers supported on CMP */
1595         shader_addline(buffer, "CMP %s, TA, %s, %s;\n", dst_name, src_name[1], src_name[2]);
1596
1597         /* _SAT on CMP doesn't make much sense, but it is not a pure NOP */
1598         if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE)
1599         {
1600             shader_arb_get_register_name(ins, &dst->reg, src_name[0], &is_color);
1601             shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, dst_name);
1602         }
1603     }
1604 }
1605
1606 static void pshader_hw_cmp(const struct wined3d_shader_instruction *ins)
1607 {
1608     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1609     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1610     char dst_name[50];
1611     char src_name[3][50];
1612     BOOL is_color;
1613
1614     shader_arb_get_dst_param(ins, dst, dst_name);
1615
1616     /* Generate input register names (with modifiers) */
1617     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
1618     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
1619     shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
1620
1621     /* No modifiers are supported on CMP */
1622     shader_addline(buffer, "CMP %s, %s, %s, %s;\n", dst_name,
1623                    src_name[0], src_name[2], src_name[1]);
1624
1625     if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE)
1626     {
1627         shader_arb_get_register_name(ins, &dst->reg, src_name[0], &is_color);
1628         shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name[0]);
1629     }
1630 }
1631
1632 /** Process the WINED3DSIO_DP2ADD instruction in ARB.
1633  * dst = dot2(src0, src1) + src2 */
1634 static void pshader_hw_dp2add(const struct wined3d_shader_instruction *ins)
1635 {
1636     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1637     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1638     char dst_name[50];
1639     char src_name[3][50];
1640     struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
1641
1642     shader_arb_get_dst_param(ins, dst, dst_name);
1643     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
1644     shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
1645
1646     if(ctx->target_version >= NV3)
1647     {
1648         /* GL_NV_fragment_program2 has a 1:1 matching instruction */
1649         shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
1650         shader_addline(buffer, "DP2A%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins),
1651                        dst_name, src_name[0], src_name[1], src_name[2]);
1652     }
1653     else if(ctx->target_version >= NV2)
1654     {
1655         /* dst.x = src2.?, src0.x, src1.x + src0.y * src1.y
1656          * dst.y = src2.?, src0.x, src1.z + src0.y * src1.w
1657          * dst.z = src2.?, src0.x, src1.x + src0.y * src1.y
1658          * dst.z = src2.?, src0.x, src1.z + src0.y * src1.w
1659          *
1660          * Make sure that src1.zw = src1.xy, then we get a classic dp2add
1661          *
1662          * .xyxy and other swizzles that we could get with this are not valid in
1663          * plain ARBfp, but luckily the NV extension grammar lifts this limitation.
1664          */
1665         struct wined3d_shader_src_param tmp_param = ins->src[1];
1666         DWORD swizzle = tmp_param.swizzle & 0xf; /* Selects .xy */
1667         tmp_param.swizzle = swizzle | (swizzle << 4); /* Creates .xyxy */
1668
1669         shader_arb_get_src_param(ins, &tmp_param, 1, src_name[1]);
1670
1671         shader_addline(buffer, "X2D%s %s, %s, %s, %s;\n", shader_arb_get_modifier(ins),
1672                        dst_name, src_name[2], src_name[0], src_name[1]);
1673     }
1674     else
1675     {
1676         shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
1677         /* Emulate a DP2 with a DP3 and 0.0. Don't use the dest as temp register, it could be src[1] or src[2]
1678         * src_name[0] can be TA, but TA is a private temp for modifiers, so it is save to overwrite
1679         */
1680         shader_addline(buffer, "MOV TA, %s;\n", src_name[0]);
1681         shader_addline(buffer, "MOV TA.z, 0.0;\n");
1682         shader_addline(buffer, "DP3 TA, TA, %s;\n", src_name[1]);
1683         shader_addline(buffer, "ADD%s %s, TA, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name[2]);
1684     }
1685 }
1686
1687 /* Map the opcode 1-to-1 to the GL code */
1688 static void shader_hw_map2gl(const struct wined3d_shader_instruction *ins)
1689 {
1690     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1691     const char *instruction;
1692     char arguments[256], dst_str[50];
1693     unsigned int i;
1694     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1695
1696     switch (ins->handler_idx)
1697     {
1698         case WINED3DSIH_ABS: instruction = "ABS"; break;
1699         case WINED3DSIH_ADD: instruction = "ADD"; break;
1700         case WINED3DSIH_CRS: instruction = "XPD"; break;
1701         case WINED3DSIH_DP3: instruction = "DP3"; break;
1702         case WINED3DSIH_DP4: instruction = "DP4"; break;
1703         case WINED3DSIH_DST: instruction = "DST"; break;
1704         case WINED3DSIH_FRC: instruction = "FRC"; break;
1705         case WINED3DSIH_LIT: instruction = "LIT"; break;
1706         case WINED3DSIH_LRP: instruction = "LRP"; break;
1707         case WINED3DSIH_MAD: instruction = "MAD"; break;
1708         case WINED3DSIH_MAX: instruction = "MAX"; break;
1709         case WINED3DSIH_MIN: instruction = "MIN"; break;
1710         case WINED3DSIH_MOV: instruction = "MOV"; break;
1711         case WINED3DSIH_MUL: instruction = "MUL"; break;
1712         case WINED3DSIH_SGE: instruction = "SGE"; break;
1713         case WINED3DSIH_SLT: instruction = "SLT"; break;
1714         case WINED3DSIH_SUB: instruction = "SUB"; break;
1715         case WINED3DSIH_MOVA:instruction = "ARR"; break;
1716         case WINED3DSIH_DSX: instruction = "DDX"; break;
1717         default: instruction = "";
1718             FIXME("Unhandled opcode %#x\n", ins->handler_idx);
1719             break;
1720     }
1721
1722     /* Note that shader_arb_add_dst_param() adds spaces. */
1723     arguments[0] = '\0';
1724     shader_arb_get_dst_param(ins, dst, dst_str);
1725     for (i = 0; i < ins->src_count; ++i)
1726     {
1727         char operand[100];
1728         strcat(arguments, ", ");
1729         shader_arb_get_src_param(ins, &ins->src[i], i, operand);
1730         strcat(arguments, operand);
1731     }
1732     shader_addline(buffer, "%s%s %s%s;\n", instruction, shader_arb_get_modifier(ins), dst_str, arguments);
1733 }
1734
1735 static void shader_hw_nop(const struct wined3d_shader_instruction *ins)
1736 {
1737     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1738     shader_addline(buffer, "NOP;\n");
1739 }
1740
1741 static void shader_hw_mov(const struct wined3d_shader_instruction *ins)
1742 {
1743     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
1744     BOOL pshader = shader_is_pshader_version(shader->baseShader.reg_maps.shader_version.type);
1745     struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
1746     const char *zero = arb_get_helper_value(shader->baseShader.reg_maps.shader_version.type, ARB_ZERO);
1747     const char *one = arb_get_helper_value(shader->baseShader.reg_maps.shader_version.type, ARB_ONE);
1748     const char *two = arb_get_helper_value(shader->baseShader.reg_maps.shader_version.type, ARB_TWO);
1749
1750     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1751     char src0_param[256];
1752
1753     if(ins->handler_idx == WINED3DSIH_MOVA) {
1754         char write_mask[6];
1755         const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET);
1756
1757         if(ctx->target_version >= NV2) {
1758             shader_hw_map2gl(ins);
1759             return;
1760         }
1761         shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param);
1762         shader_arb_get_write_mask(ins, &ins->dst[0], write_mask);
1763
1764         /* This implements the mova formula used in GLSL. The first two instructions
1765          * prepare the sign() part. Note that it is fine to have my_sign(0.0) = 1.0
1766          * in this case:
1767          * mova A0.x, 0.0
1768          *
1769          * A0.x = arl(floor(abs(0.0) + 0.5) * 1.0) = floor(0.5) = 0.0 since arl does a floor
1770          *
1771          * The ARL is performed when A0 is used - the requested component is read from A0_SHADOW into
1772          * A0.x. We can use the overwritten component of A0_shadow as temporary storage for the sign.
1773          */
1774         shader_addline(buffer, "SGE A0_SHADOW%s, %s, %s;\n", write_mask, src0_param, zero);
1775         shader_addline(buffer, "MAD A0_SHADOW%s, A0_SHADOW, %s, -%s;\n", write_mask, two, one);
1776
1777         shader_addline(buffer, "ABS TA%s, %s;\n", write_mask, src0_param);
1778         shader_addline(buffer, "ADD TA%s, TA, rel_addr_const.x;\n", write_mask);
1779         shader_addline(buffer, "FLR TA%s, TA;\n", write_mask);
1780         if (((IWineD3DVertexShaderImpl *)shader)->rel_offset)
1781         {
1782             shader_addline(buffer, "ADD TA%s, TA, %s;\n", write_mask, offset);
1783         }
1784         shader_addline(buffer, "MUL A0_SHADOW%s, TA, A0_SHADOW;\n", write_mask);
1785
1786         ((struct shader_arb_ctx_priv *)ins->ctx->backend_data)->addr_reg[0] = '\0';
1787     } else if (ins->ctx->reg_maps->shader_version.major == 1
1788           && !shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)
1789           && ins->dst[0].reg.type == WINED3DSPR_ADDR)
1790     {
1791         src0_param[0] = '\0';
1792         if (((IWineD3DVertexShaderImpl *)shader)->rel_offset)
1793         {
1794             const char *offset = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_VS_REL_OFFSET);
1795             shader_arb_get_src_param(ins, &ins->src[0], 0, src0_param);
1796             shader_addline(buffer, "ADD TA.x, %s, %s;\n", src0_param, offset);
1797             shader_addline(buffer, "ARL A0.x, TA.x;\n");
1798         }
1799         else
1800         {
1801             /* Apple's ARB_vertex_program implementation does not accept an ARL source argument
1802              * with more than one component. Thus replicate the first source argument over all
1803              * 4 components. For example, .xyzw -> .x (or better: .xxxx), .zwxy -> .z, etc) */
1804             struct wined3d_shader_src_param tmp_src = ins->src[0];
1805             tmp_src.swizzle = (tmp_src.swizzle & 0x3) * 0x55;
1806             shader_arb_get_src_param(ins, &tmp_src, 0, src0_param);
1807             shader_addline(buffer, "ARL A0.x, %s;\n", src0_param);
1808         }
1809     }
1810     else if(ins->dst[0].reg.type == WINED3DSPR_COLOROUT && ins->dst[0].reg.idx == 0 && pshader)
1811     {
1812         IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) shader;
1813         if(ctx->cur_ps_args->super.srgb_correction && ps->color0_mov)
1814         {
1815             shader_addline(buffer, "#mov handled in srgb write code\n");
1816             return;
1817         }
1818         shader_hw_map2gl(ins);
1819     }
1820     else
1821     {
1822         shader_hw_map2gl(ins);
1823     }
1824 }
1825
1826 static void pshader_hw_texkill(const struct wined3d_shader_instruction *ins)
1827 {
1828     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1829     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1830     char reg_dest[40];
1831
1832     /* No swizzles are allowed in d3d's texkill. PS 1.x ignores the 4th component as documented,
1833      * but >= 2.0 honors it(undocumented, but tested by the d3d9 testsuit)
1834      */
1835     shader_arb_get_dst_param(ins, dst, reg_dest);
1836
1837     if (ins->ctx->reg_maps->shader_version.major >= 2)
1838     {
1839         const char *kilsrc = "TA";
1840         BOOL is_color;
1841
1842         shader_arb_get_register_name(ins, &dst->reg, reg_dest, &is_color);
1843         if(dst->write_mask == WINED3DSP_WRITEMASK_ALL)
1844         {
1845             kilsrc = reg_dest;
1846         }
1847         else
1848         {
1849             /* Sigh. KIL doesn't support swizzles/writemasks. KIL passes a writemask, but ".xy" for example
1850              * is not valid as a swizzle in ARB (needs ".xyyy"). Use SWZ to load the register properly, and set
1851              * masked out components to 0(won't kill)
1852              */
1853             char x = '0', y = '0', z = '0', w = '0';
1854             if(dst->write_mask & WINED3DSP_WRITEMASK_0) x = 'x';
1855             if(dst->write_mask & WINED3DSP_WRITEMASK_1) y = 'y';
1856             if(dst->write_mask & WINED3DSP_WRITEMASK_2) z = 'z';
1857             if(dst->write_mask & WINED3DSP_WRITEMASK_3) w = 'w';
1858             shader_addline(buffer, "SWZ TA, %s, %c, %c, %c, %c;\n", reg_dest, x, y, z, w);
1859         }
1860         shader_addline(buffer, "KIL %s;\n", kilsrc);
1861     } else {
1862         /* ARB fp doesn't like swizzles on the parameter of the KIL instruction. To mask the 4th component,
1863          * copy the register into our general purpose TMP variable, overwrite .w and pass TMP to KIL
1864          *
1865          * ps_1_3 shaders use the texcoord incarnation of the Tx register. ps_1_4 shaders can use the same,
1866          * or pass in any temporary register(in shader phase 2)
1867          */
1868         if(ins->ctx->reg_maps->shader_version.minor <= 3) {
1869             sprintf(reg_dest, "fragment.texcoord[%u]", dst->reg.idx);
1870         } else {
1871             shader_arb_get_dst_param(ins, dst, reg_dest);
1872         }
1873         shader_addline(buffer, "SWZ TA, %s, x, y, z, 1;\n", reg_dest);
1874         shader_addline(buffer, "KIL TA;\n");
1875     }
1876 }
1877
1878 static void pshader_hw_tex(const struct wined3d_shader_instruction *ins)
1879 {
1880     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
1881     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
1882     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1883     DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
1884             ins->ctx->reg_maps->shader_version.minor);
1885     struct wined3d_shader_src_param src;
1886
1887     char reg_dest[40];
1888     char reg_coord[40];
1889     DWORD reg_sampler_code;
1890     WORD myflags = 0;
1891
1892     /* All versions have a destination register */
1893     shader_arb_get_dst_param(ins, dst, reg_dest);
1894
1895     /* 1.0-1.4: Use destination register number as texture code.
1896        2.0+: Use provided sampler number as texure code. */
1897     if (shader_version < WINED3D_SHADER_VERSION(2,0))
1898         reg_sampler_code = dst->reg.idx;
1899     else
1900         reg_sampler_code = ins->src[1].reg.idx;
1901
1902     /* 1.0-1.3: Use the texcoord varying.
1903        1.4+: Use provided coordinate source register. */
1904     if (shader_version < WINED3D_SHADER_VERSION(1,4))
1905         sprintf(reg_coord, "fragment.texcoord[%u]", reg_sampler_code);
1906     else {
1907         /* TEX is the only instruction that can handle DW and DZ natively */
1908         src = ins->src[0];
1909         if(src.modifiers == WINED3DSPSM_DW) src.modifiers = WINED3DSPSM_NONE;
1910         if(src.modifiers == WINED3DSPSM_DZ) src.modifiers = WINED3DSPSM_NONE;
1911         shader_arb_get_src_param(ins, &src, 0, reg_coord);
1912     }
1913
1914     /* projection flag:
1915      * 1.1, 1.2, 1.3: Use WINED3DTSS_TEXTURETRANSFORMFLAGS
1916      * 1.4: Use WINED3DSPSM_DZ or WINED3DSPSM_DW on src[0]
1917      * 2.0+: Use WINED3DSI_TEXLD_PROJECT on the opcode
1918      */
1919     if (shader_version < WINED3D_SHADER_VERSION(1,4))
1920     {
1921         DWORD flags = 0;
1922         if(reg_sampler_code < MAX_TEXTURES) {
1923             flags = deviceImpl->stateBlock->textureState[reg_sampler_code][WINED3DTSS_TEXTURETRANSFORMFLAGS];
1924         }
1925         if (flags & WINED3DTTFF_PROJECTED) {
1926             myflags |= TEX_PROJ;
1927         }
1928     }
1929     else if (shader_version < WINED3D_SHADER_VERSION(2,0))
1930     {
1931         DWORD src_mod = ins->src[0].modifiers;
1932         if (src_mod == WINED3DSPSM_DZ) {
1933             /* TXP cannot handle DZ natively, so move the z coordinate to .w. reg_coord is a read-only
1934              * varying register, so we need a temp reg
1935              */
1936             shader_addline(ins->ctx->buffer, "SWZ TA, %s, x, y, z, z;\n", reg_coord);
1937             strcpy(reg_coord, "TA");
1938             myflags |= TEX_PROJ;
1939         } else if(src_mod == WINED3DSPSM_DW) {
1940             myflags |= TEX_PROJ;
1941         }
1942     } else {
1943         if (ins->flags & WINED3DSI_TEXLD_PROJECT) myflags |= TEX_PROJ;
1944         if (ins->flags & WINED3DSI_TEXLD_BIAS) myflags |= TEX_BIAS;
1945     }
1946     shader_hw_sample(ins, reg_sampler_code, reg_dest, reg_coord, myflags, NULL, NULL);
1947 }
1948
1949 static void pshader_hw_texcoord(const struct wined3d_shader_instruction *ins)
1950 {
1951     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
1952     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1953     DWORD shader_version = WINED3D_SHADER_VERSION(ins->ctx->reg_maps->shader_version.major,
1954             ins->ctx->reg_maps->shader_version.minor);
1955     char dst_str[50];
1956
1957     if (shader_version < WINED3D_SHADER_VERSION(1,4))
1958     {
1959         DWORD reg = dst->reg.idx;
1960
1961         shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
1962         shader_addline(buffer, "MOV_SAT %s, fragment.texcoord[%u];\n", dst_str, reg);
1963     } else {
1964         char reg_src[40];
1965
1966         shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src);
1967         shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
1968         shader_addline(buffer, "MOV %s, %s;\n", dst_str, reg_src);
1969    }
1970 }
1971
1972 static void pshader_hw_texreg2ar(const struct wined3d_shader_instruction *ins)
1973 {
1974      struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1975      IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
1976      IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
1977      DWORD flags;
1978
1979      DWORD reg1 = ins->dst[0].reg.idx;
1980      char dst_str[50];
1981      char src_str[50];
1982
1983      /* Note that texreg2ar treats Tx as a temporary register, not as a varying */
1984      shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
1985      shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
1986      /* Move .x first in case src_str is "TA" */
1987      shader_addline(buffer, "MOV TA.y, %s.x;\n", src_str);
1988      shader_addline(buffer, "MOV TA.x, %s.w;\n", src_str);
1989      flags = reg1 < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg1][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
1990      shader_hw_sample(ins, reg1, dst_str, "TA", flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
1991 }
1992
1993 static void pshader_hw_texreg2gb(const struct wined3d_shader_instruction *ins)
1994 {
1995      struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
1996
1997      DWORD reg1 = ins->dst[0].reg.idx;
1998      char dst_str[50];
1999      char src_str[50];
2000
2001      /* Note that texreg2gb treats Tx as a temporary register, not as a varying */
2002      shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2003      shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
2004      shader_addline(buffer, "MOV TA.x, %s.y;\n", src_str);
2005      shader_addline(buffer, "MOV TA.y, %s.z;\n", src_str);
2006      shader_hw_sample(ins, reg1, dst_str, "TA", 0, NULL, NULL);
2007 }
2008
2009 static void pshader_hw_texreg2rgb(const struct wined3d_shader_instruction *ins)
2010 {
2011     DWORD reg1 = ins->dst[0].reg.idx;
2012     char dst_str[50];
2013     char src_str[50];
2014
2015     /* Note that texreg2rg treats Tx as a temporary register, not as a varying */
2016     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2017     shader_arb_get_src_param(ins, &ins->src[0], 0, src_str);
2018     shader_hw_sample(ins, reg1, dst_str, src_str, 0, NULL, NULL);
2019 }
2020
2021 static void pshader_hw_texbem(const struct wined3d_shader_instruction *ins)
2022 {
2023     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
2024     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
2025     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
2026     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2027     char reg_coord[40], dst_reg[50], src_reg[50];
2028     DWORD reg_dest_code;
2029
2030     /* All versions have a destination register. The Tx where the texture coordinates come
2031      * from is the varying incarnation of the texture register
2032      */
2033     reg_dest_code = dst->reg.idx;
2034     shader_arb_get_dst_param(ins, &ins->dst[0], dst_reg);
2035     shader_arb_get_src_param(ins, &ins->src[0], 0, src_reg);
2036     sprintf(reg_coord, "fragment.texcoord[%u]", reg_dest_code);
2037
2038     /* Sampling the perturbation map in Tsrc was done already, including the signedness correction if needed
2039      * The Tx in which the perturbation map is stored is the tempreg incarnation of the texture register
2040      *
2041      * GL_NV_fragment_program_option could handle this in one instruction via X2D:
2042      * X2D TA.xy, fragment.texcoord, T%u, bumpenvmat%u.xzyw
2043      *
2044      * However, the NV extensions are never enabled for <= 2.0 shaders because of the performance penalty that
2045      * comes with it, and texbem is an 1.x only instruction. No 1.x instruction forces us to enable the NV
2046      * extension.
2047      */
2048     shader_addline(buffer, "SWZ TB, bumpenvmat%d, x, z, 0, 0;\n", reg_dest_code);
2049     shader_addline(buffer, "DP3 TA.x, TB, %s;\n", src_reg);
2050     shader_addline(buffer, "SWZ TB, bumpenvmat%d, y, w, 0, 0;\n", reg_dest_code);
2051     shader_addline(buffer, "DP3 TA.y, TB, %s;\n", src_reg);
2052
2053     /* with projective textures, texbem only divides the static texture coord, not the displacement,
2054      * so we can't let the GL handle this.
2055      */
2056     if (device->stateBlock->textureState[reg_dest_code][WINED3DTSS_TEXTURETRANSFORMFLAGS] & WINED3DTTFF_PROJECTED)
2057     {
2058         shader_addline(buffer, "RCP TB.w, %s.w;\n", reg_coord);
2059         shader_addline(buffer, "MUL TB.xy, %s, TB.w;\n", reg_coord);
2060         shader_addline(buffer, "ADD TA.xy, TA, TB;\n");
2061     } else {
2062         shader_addline(buffer, "ADD TA.xy, TA, %s;\n", reg_coord);
2063     }
2064
2065     shader_hw_sample(ins, reg_dest_code, dst_reg, "TA", 0, NULL, NULL);
2066
2067     if (ins->handler_idx == WINED3DSIH_TEXBEML)
2068     {
2069         /* No src swizzles are allowed, so this is ok */
2070         shader_addline(buffer, "MAD TA, %s.z, luminance%d.x, luminance%d.y;\n",
2071                        src_reg, reg_dest_code, reg_dest_code);
2072         shader_addline(buffer, "MUL %s, %s, TA;\n", dst_reg, dst_reg);
2073     }
2074 }
2075
2076 static void pshader_hw_texm3x2pad(const struct wined3d_shader_instruction *ins)
2077 {
2078     DWORD reg = ins->dst[0].reg.idx;
2079     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2080     char src0_name[50], dst_name[50];
2081     BOOL is_color;
2082     struct wined3d_shader_register tmp_reg = ins->dst[0].reg;
2083
2084     shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
2085     /* The next instruction will be a texm3x2tex or texm3x2depth that writes to the uninitialized
2086      * T<reg+1> register. Use this register to store the calculated vector
2087      */
2088     tmp_reg.idx = reg + 1;
2089     shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color);
2090     shader_addline(buffer, "DP3 %s.x, fragment.texcoord[%u], %s;\n", dst_name, reg, src0_name);
2091 }
2092
2093 static void pshader_hw_texm3x2tex(const struct wined3d_shader_instruction *ins)
2094 {
2095     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
2096     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
2097     DWORD flags;
2098     DWORD reg = ins->dst[0].reg.idx;
2099     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2100     char dst_str[50];
2101     char src0_name[50];
2102     char dst_reg[50];
2103     BOOL is_color;
2104
2105     /* We know that we're writing to the uninitialized T<reg> register, so use it for temporary storage */
2106     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color);
2107
2108     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2109     shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
2110     shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name);
2111     flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
2112     shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
2113 }
2114
2115 static void pshader_hw_texm3x3pad(const struct wined3d_shader_instruction *ins)
2116 {
2117     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
2118     SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state;
2119     DWORD reg = ins->dst[0].reg.idx;
2120     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2121     char src0_name[50], dst_name[50];
2122     struct wined3d_shader_register tmp_reg = ins->dst[0].reg;
2123     BOOL is_color;
2124
2125     /* There are always 2 texm3x3pad instructions followed by one texm3x3[tex,vspec, ...] instruction, with
2126      * incrementing ins->dst[0].register_idx numbers. So the pad instruction already knows the final destination
2127      * register, and this register is uninitialized(otherwise the assembler complains that it is 'redeclared')
2128      */
2129     tmp_reg.idx = reg + 2 - current_state->current_row;
2130     shader_arb_get_register_name(ins, &tmp_reg, dst_name, &is_color);
2131
2132     shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
2133     shader_addline(buffer, "DP3 %s.%c, fragment.texcoord[%u], %s;\n",
2134                    dst_name, 'x' + current_state->current_row, reg, src0_name);
2135     current_state->texcoord_w[current_state->current_row++] = reg;
2136 }
2137
2138 static void pshader_hw_texm3x3tex(const struct wined3d_shader_instruction *ins)
2139 {
2140     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
2141     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
2142     SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state;
2143     DWORD flags;
2144     DWORD reg = ins->dst[0].reg.idx;
2145     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2146     char dst_str[50];
2147     char src0_name[50], dst_name[50];
2148     BOOL is_color;
2149
2150     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
2151     shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
2152     shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_name, reg, src0_name);
2153
2154     /* Sample the texture using the calculated coordinates */
2155     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2156     flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
2157     shader_hw_sample(ins, reg, dst_str, dst_name, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
2158     current_state->current_row = 0;
2159 }
2160
2161 static void pshader_hw_texm3x3vspec(const struct wined3d_shader_instruction *ins)
2162 {
2163     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
2164     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
2165     SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state;
2166     DWORD flags;
2167     DWORD reg = ins->dst[0].reg.idx;
2168     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2169     char dst_str[50];
2170     char src0_name[50];
2171     char dst_reg[50];
2172     BOOL is_color;
2173
2174     /* Get the dst reg without writemask strings. We know this register is uninitialized, so we can use all
2175      * components for temporary data storage
2176      */
2177     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color);
2178     shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
2179     shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name);
2180
2181     /* Construct the eye-ray vector from w coordinates */
2182     shader_addline(buffer, "MOV TB.x, fragment.texcoord[%u].w;\n", current_state->texcoord_w[0]);
2183     shader_addline(buffer, "MOV TB.y, fragment.texcoord[%u].w;\n", current_state->texcoord_w[1]);
2184     shader_addline(buffer, "MOV TB.z, fragment.texcoord[%u].w;\n", reg);
2185
2186     /* Calculate reflection vector
2187      */
2188     shader_addline(buffer, "DP3 %s.w, %s, TB;\n", dst_reg, dst_reg);
2189     /* The .w is ignored when sampling, so I can use TB.w to calculate dot(N, N) */
2190     shader_addline(buffer, "DP3 TB.w, %s, %s;\n", dst_reg, dst_reg);
2191     shader_addline(buffer, "RCP TB.w, TB.w;\n");
2192     shader_addline(buffer, "MUL %s.w, %s.w, TB.w;\n", dst_reg, dst_reg);
2193     shader_addline(buffer, "MUL %s, %s.w, %s;\n", dst_reg, dst_reg, dst_reg);
2194     shader_addline(buffer, "MAD %s, coefmul.x, %s, -TB;\n", dst_reg, dst_reg);
2195
2196     /* Sample the texture using the calculated coordinates */
2197     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2198     flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
2199     shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
2200     current_state->current_row = 0;
2201 }
2202
2203 static void pshader_hw_texm3x3spec(const struct wined3d_shader_instruction *ins)
2204 {
2205     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
2206     IWineD3DDeviceImpl *deviceImpl = (IWineD3DDeviceImpl *)shader->baseShader.device;
2207     SHADER_PARSE_STATE *current_state = &shader->baseShader.parse_state;
2208     DWORD flags;
2209     DWORD reg = ins->dst[0].reg.idx;
2210     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2211     char dst_str[50];
2212     char src0_name[50];
2213     char src1_name[50];
2214     char dst_reg[50];
2215     BOOL is_color;
2216
2217     shader_arb_get_src_param(ins, &ins->src[0], 0, src0_name);
2218     shader_arb_get_src_param(ins, &ins->src[0], 1, src1_name);
2219     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_reg, &is_color);
2220     /* Note: dst_reg.xy is input here, generated by two texm3x3pad instructions */
2221     shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_reg, reg, src0_name);
2222
2223     /* Calculate reflection vector.
2224      *
2225      *                   dot(N, E)
2226      * dst_reg.xyz = 2 * --------- * N - E
2227      *                   dot(N, N)
2228      *
2229      * Which normalizes the normal vector
2230      */
2231     shader_addline(buffer, "DP3 %s.w, %s, %s;\n", dst_reg, dst_reg, src1_name);
2232     shader_addline(buffer, "DP3 TC.w, %s, %s;\n", dst_reg, dst_reg);
2233     shader_addline(buffer, "RCP TC.w, TC.w;\n");
2234     shader_addline(buffer, "MUL %s.w, %s.w, TC.w;\n", dst_reg, dst_reg);
2235     shader_addline(buffer, "MUL %s, %s.w, %s;\n", dst_reg, dst_reg, dst_reg);
2236     shader_addline(buffer, "MAD %s, coefmul.x, %s, -%s;\n", dst_reg, dst_reg, src1_name);
2237
2238     /* Sample the texture using the calculated coordinates */
2239     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2240     flags = reg < MAX_TEXTURES ? deviceImpl->stateBlock->textureState[reg][WINED3DTSS_TEXTURETRANSFORMFLAGS] : 0;
2241     shader_hw_sample(ins, reg, dst_str, dst_reg, flags & WINED3DTTFF_PROJECTED ? TEX_PROJ : 0, NULL, NULL);
2242     current_state->current_row = 0;
2243 }
2244
2245 static void pshader_hw_texdepth(const struct wined3d_shader_instruction *ins)
2246 {
2247     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
2248     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2249     char dst_name[50];
2250     const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
2251     const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
2252
2253     /* texdepth has an implicit destination, the fragment depth value. It's only parameter,
2254      * which is essentially an input, is the destination register because it is the first
2255      * parameter. According to the msdn, this must be register r5, but let's keep it more flexible
2256      * here(writemasks/swizzles are not valid on texdepth)
2257      */
2258     shader_arb_get_dst_param(ins, dst, dst_name);
2259
2260     /* According to the msdn, the source register(must be r5) is unusable after
2261      * the texdepth instruction, so we're free to modify it
2262      */
2263     shader_addline(buffer, "MIN %s.y, %s.y, %s;\n", dst_name, dst_name, one);
2264
2265     /* How to deal with the special case dst_name.g == 0? if r != 0, then
2266      * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
2267      * result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
2268      */
2269     shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
2270     shader_addline(buffer, "MUL TA.x, %s.x, %s.y;\n", dst_name, dst_name);
2271     shader_addline(buffer, "MIN TA.x, TA.x, %s;\n", one);
2272     shader_addline(buffer, "MAX result.depth, TA.x, %s;\n", zero);
2273 }
2274
2275 /** Process the WINED3DSIO_TEXDP3TEX instruction in ARB:
2276  * Take a 3-component dot product of the TexCoord[dstreg] and src,
2277  * then perform a 1D texture lookup from stage dstregnum, place into dst. */
2278 static void pshader_hw_texdp3tex(const struct wined3d_shader_instruction *ins)
2279 {
2280     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2281     DWORD sampler_idx = ins->dst[0].reg.idx;
2282     char src0[50];
2283     char dst_str[50];
2284
2285     shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
2286     shader_addline(buffer, "MOV TB, 0.0;\n");
2287     shader_addline(buffer, "DP3 TB.x, fragment.texcoord[%u], %s;\n", sampler_idx, src0);
2288
2289     shader_arb_get_dst_param(ins, &ins->dst[0], dst_str);
2290     shader_hw_sample(ins, sampler_idx, dst_str, "TB", 0 /* Only one coord, can't be projected */, NULL, NULL);
2291 }
2292
2293 /** Process the WINED3DSIO_TEXDP3 instruction in ARB:
2294  * Take a 3-component dot product of the TexCoord[dstreg] and src. */
2295 static void pshader_hw_texdp3(const struct wined3d_shader_instruction *ins)
2296 {
2297     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
2298     char src0[50];
2299     char dst_str[50];
2300     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2301
2302     /* Handle output register */
2303     shader_arb_get_dst_param(ins, dst, dst_str);
2304     shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
2305     shader_addline(buffer, "DP3 %s, fragment.texcoord[%u], %s;\n", dst_str, dst->reg.idx, src0);
2306 }
2307
2308 /** Process the WINED3DSIO_TEXM3X3 instruction in ARB
2309  * Perform the 3rd row of a 3x3 matrix multiply */
2310 static void pshader_hw_texm3x3(const struct wined3d_shader_instruction *ins)
2311 {
2312     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
2313     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2314     char dst_str[50], dst_name[50];
2315     char src0[50];
2316     BOOL is_color;
2317
2318     shader_arb_get_dst_param(ins, dst, dst_str);
2319     shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
2320     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
2321     shader_addline(buffer, "DP3 %s.z, fragment.texcoord[%u], %s;\n", dst_name, dst->reg.idx, src0);
2322     shader_addline(buffer, "MOV %s, %s;\n", dst_str, dst_name);
2323 }
2324
2325 /** Process the WINED3DSIO_TEXM3X2DEPTH instruction in ARB:
2326  * Last row of a 3x2 matrix multiply, use the result to calculate the depth:
2327  * Calculate tmp0.y = TexCoord[dstreg] . src.xyz;  (tmp0.x has already been calculated)
2328  * depth = (tmp0.y == 0.0) ? 1.0 : tmp0.x / tmp0.y
2329  */
2330 static void pshader_hw_texm3x2depth(const struct wined3d_shader_instruction *ins)
2331 {
2332     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2333     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
2334     char src0[50], dst_name[50];
2335     BOOL is_color;
2336     const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
2337     const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
2338
2339     shader_arb_get_src_param(ins, &ins->src[0], 0, src0);
2340     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
2341     shader_addline(buffer, "DP3 %s.y, fragment.texcoord[%u], %s;\n", dst_name, dst->reg.idx, src0);
2342
2343     /* How to deal with the special case dst_name.g == 0? if r != 0, then
2344      * the r * (1 / 0) will give infinity, which is clamped to 1.0, the correct
2345      * result. But if r = 0.0, then 0 * inf = 0, which is incorrect.
2346      */
2347     shader_addline(buffer, "RCP %s.y, %s.y;\n", dst_name, dst_name);
2348     shader_addline(buffer, "MUL %s.x, %s.x, %s.y;\n", dst_name, dst_name, dst_name);
2349     shader_addline(buffer, "MIN %s.x, %s.x, %s;\n", dst_name, dst_name, one);
2350     shader_addline(buffer, "MAX result.depth, %s.x, %s;\n", dst_name, zero);
2351 }
2352
2353 /** Handles transforming all WINED3DSIO_M?x? opcodes for
2354     Vertex/Pixel shaders to ARB_vertex_program codes */
2355 static void shader_hw_mnxn(const struct wined3d_shader_instruction *ins)
2356 {
2357     int i;
2358     int nComponents = 0;
2359     struct wined3d_shader_dst_param tmp_dst = {{0}};
2360     struct wined3d_shader_src_param tmp_src[2] = {{{0}}};
2361     struct wined3d_shader_instruction tmp_ins;
2362
2363     memset(&tmp_ins, 0, sizeof(tmp_ins));
2364
2365     /* Set constants for the temporary argument */
2366     tmp_ins.ctx = ins->ctx;
2367     tmp_ins.dst_count = 1;
2368     tmp_ins.dst = &tmp_dst;
2369     tmp_ins.src_count = 2;
2370     tmp_ins.src = tmp_src;
2371
2372     switch(ins->handler_idx)
2373     {
2374         case WINED3DSIH_M4x4:
2375             nComponents = 4;
2376             tmp_ins.handler_idx = WINED3DSIH_DP4;
2377             break;
2378         case WINED3DSIH_M4x3:
2379             nComponents = 3;
2380             tmp_ins.handler_idx = WINED3DSIH_DP4;
2381             break;
2382         case WINED3DSIH_M3x4:
2383             nComponents = 4;
2384             tmp_ins.handler_idx = WINED3DSIH_DP3;
2385             break;
2386         case WINED3DSIH_M3x3:
2387             nComponents = 3;
2388             tmp_ins.handler_idx = WINED3DSIH_DP3;
2389             break;
2390         case WINED3DSIH_M3x2:
2391             nComponents = 2;
2392             tmp_ins.handler_idx = WINED3DSIH_DP3;
2393             break;
2394         default:
2395             FIXME("Unhandled opcode %#x\n", ins->handler_idx);
2396             break;
2397     }
2398
2399     tmp_dst = ins->dst[0];
2400     tmp_src[0] = ins->src[0];
2401     tmp_src[1] = ins->src[1];
2402     for (i = 0; i < nComponents; i++) {
2403         tmp_dst.write_mask = WINED3DSP_WRITEMASK_0 << i;
2404         shader_hw_map2gl(&tmp_ins);
2405         ++tmp_src[1].reg.idx;
2406     }
2407 }
2408
2409 static void shader_hw_rcp(const struct wined3d_shader_instruction *ins)
2410 {
2411     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2412     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2413     const char *flt_eps = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_EPS);
2414
2415     char dst[50];
2416     char src[50];
2417
2418     shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */
2419     shader_arb_get_src_param(ins, &ins->src[0], 0, src);
2420     if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE)
2421     {
2422         /* Dx sdk says .x is used if no swizzle is given, but our test shows that
2423          * .w is used
2424          */
2425         strcat(src, ".w");
2426     }
2427
2428     /* TODO: If the destination is readable, and not the same as the source, the destination
2429      * can be used instead of TA
2430      */
2431     if (priv->target_version >= NV2)
2432     {
2433         shader_addline(buffer, "MOVC TA.x, %s;\n", src);
2434         shader_addline(buffer, "MOV TA.x (EQ.x), %s;\n", flt_eps);
2435         shader_addline(buffer, "RCP%s %s, TA.x;\n", shader_arb_get_modifier(ins), dst);
2436     }
2437     else
2438     {
2439         const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
2440         shader_addline(buffer, "ABS TA.x, %s;\n", src);
2441         shader_addline(buffer, "SGE TA.y, -TA.x, %s;\n", zero);
2442         shader_addline(buffer, "MAD TA.x, TA.y, %s, %s;\n", flt_eps, src);
2443         shader_addline(buffer, "RCP%s %s, TA.x;\n", shader_arb_get_modifier(ins), dst);
2444     }
2445 }
2446
2447 static void shader_hw_scalar_op(const struct wined3d_shader_instruction *ins)
2448 {
2449     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2450     const char *instruction;
2451
2452     char dst[50];
2453     char src[50];
2454
2455     switch(ins->handler_idx)
2456     {
2457         case WINED3DSIH_RSQ:  instruction = "RSQ"; break;
2458         case WINED3DSIH_RCP:  instruction = "RCP"; break;
2459         case WINED3DSIH_EXP:  instruction = "EX2"; break;
2460         case WINED3DSIH_EXPP: instruction = "EXP"; break;
2461         default: instruction = "";
2462             FIXME("Unhandled opcode %#x\n", ins->handler_idx);
2463             break;
2464     }
2465
2466     shader_arb_get_dst_param(ins, &ins->dst[0], dst); /* Destination */
2467     shader_arb_get_src_param(ins, &ins->src[0], 0, src);
2468     if (ins->src[0].swizzle == WINED3DSP_NOSWIZZLE)
2469     {
2470         /* Dx sdk says .x is used if no swizzle is given, but our test shows that
2471          * .w is used
2472          */
2473         strcat(src, ".w");
2474     }
2475
2476     shader_addline(buffer, "%s%s %s, %s;\n", instruction, shader_arb_get_modifier(ins), dst, src);
2477 }
2478
2479 static void shader_hw_nrm(const struct wined3d_shader_instruction *ins)
2480 {
2481     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2482     char dst_name[50];
2483     char src_name[50];
2484     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2485     BOOL pshader = shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type);
2486     const char *zero = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ZERO);
2487
2488     shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
2489     shader_arb_get_src_param(ins, &ins->src[0], 1 /* Use TB */, src_name);
2490
2491     /* In D3D, NRM of a vector with length zero returns zero. Catch this situation, as
2492      * otherwise NRM or RSQ would return NaN */
2493     if(pshader && priv->target_version >= NV3)
2494     {
2495         /* GL_NV_fragment_program2's NRM needs protection against length zero vectors too
2496          *
2497          * TODO: Find out if DP3+NRM+MOV is really faster than DP3+RSQ+MUL
2498          */
2499         shader_addline(buffer, "DP3C TA, %s, %s;\n", src_name, src_name);
2500         shader_addline(buffer, "NRM%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name);
2501         shader_addline(buffer, "MOV %s (EQ), %s;\n", dst_name, zero);
2502     }
2503     else if(priv->target_version >= NV2)
2504     {
2505         shader_addline(buffer, "DP3C TA.x, %s, %s;\n", src_name, src_name);
2506         shader_addline(buffer, "RSQ TA.x (NE), TA.x;\n");
2507         shader_addline(buffer, "MUL%s %s, %s, TA.x;\n", shader_arb_get_modifier(ins), dst_name,
2508                        src_name);
2509     }
2510     else
2511     {
2512         const char *one = arb_get_helper_value(ins->ctx->reg_maps->shader_version.type, ARB_ONE);
2513
2514         shader_addline(buffer, "DP3 TA.x, %s, %s;\n", src_name, src_name);
2515         /* Pass any non-zero value to RSQ if the input vector has a length of zero. The
2516          * RSQ result doesn't matter, as long as multiplying it by 0 returns 0.
2517          */
2518         shader_addline(buffer, "SGE TA.y, -TA.x, %s;\n", zero);
2519         shader_addline(buffer, "MAD TA.x, %s, TA.y, TA.x;\n", one);
2520
2521         shader_addline(buffer, "RSQ TA.x, TA.x;\n");
2522         /* dst.w = src[0].w * 1 / (src.x^2 + src.y^2 + src.z^2)^(1/2) according to msdn*/
2523         shader_addline(buffer, "MUL%s %s, %s, TA.x;\n", shader_arb_get_modifier(ins), dst_name,
2524                     src_name);
2525     }
2526 }
2527
2528 static void shader_hw_lrp(const struct wined3d_shader_instruction *ins)
2529 {
2530     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2531     char dst_name[50];
2532     char src_name[3][50];
2533
2534     /* ARB_fragment_program has a convenient LRP instruction */
2535     if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) {
2536         shader_hw_map2gl(ins);
2537         return;
2538     }
2539
2540     shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
2541     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name[0]);
2542     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name[1]);
2543     shader_arb_get_src_param(ins, &ins->src[2], 2, src_name[2]);
2544
2545     shader_addline(buffer, "SUB TA, %s, %s;\n", src_name[1], src_name[2]);
2546     shader_addline(buffer, "MAD%s %s, %s, TA, %s;\n", shader_arb_get_modifier(ins),
2547                    dst_name, src_name[0], src_name[2]);
2548 }
2549
2550 static void shader_hw_sincos(const struct wined3d_shader_instruction *ins)
2551 {
2552     /* This instruction exists in ARB, but the d3d instruction takes two extra parameters which
2553      * must contain fixed constants. So we need a separate function to filter those constants and
2554      * can't use map2gl
2555      */
2556     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2557     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2558     const struct wined3d_shader_dst_param *dst = &ins->dst[0];
2559     char dst_name[50];
2560     char src_name0[50], src_name1[50], src_name2[50];
2561     BOOL is_color;
2562
2563     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
2564     if(shader_is_pshader_version(ins->ctx->reg_maps->shader_version.type)) {
2565         shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
2566         /* No modifiers are supported on SCS */
2567         shader_addline(buffer, "SCS %s, %s;\n", dst_name, src_name0);
2568
2569         if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE)
2570         {
2571             shader_arb_get_register_name(ins, &dst->reg, src_name0, &is_color);
2572             shader_addline(buffer, "MOV_SAT %s, %s;\n", dst_name, src_name0);
2573         }
2574     } else if(priv->target_version >= NV2) {
2575         shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color);
2576
2577         /* Sincos writemask must be .x, .y or .xy */
2578         if(dst->write_mask & WINED3DSP_WRITEMASK_0)
2579             shader_addline(buffer, "COS%s %s.x, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name0);
2580         if(dst->write_mask & WINED3DSP_WRITEMASK_1)
2581             shader_addline(buffer, "SIN%s %s.y, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name0);
2582     } else {
2583         /* Approximate sine and cosine with a taylor series, as per math textbook. The application passes 8
2584          * helper constants(D3DSINCOSCONST1 and D3DSINCOSCONST2) in src1 and src2.
2585          *
2586          * sin(x) = x - x^3/3! + x^5/5! - x^7/7! + ...
2587          * cos(x) = 1 - x^2/2! + x^4/4! - x^6/6! + ...
2588          *
2589          * The constants we get are:
2590          *
2591          *  +1   +1,     -1     -1     +1      +1      -1       -1
2592          *      ---- ,  ---- , ---- , ----- , ----- , ----- , ------
2593          *      1!*2    2!*4   3!*8   4!*16   5!*32   6!*64   7!*128
2594          *
2595          * If used with x^2, x^3, x^4 etc they calculate sin(x/2) and cos(x/2):
2596          *
2597          * (x/2)^2 = x^2 / 4
2598          * (x/2)^3 = x^3 / 8
2599          * (x/2)^4 = x^4 / 16
2600          * (x/2)^5 = x^5 / 32
2601          * etc
2602          *
2603          * To get the final result:
2604          * sin(x) = 2 * sin(x/2) * cos(x/2)
2605          * cos(x) = cos(x/2)^2 - sin(x/2)^2
2606          * (from sin(x+y) and cos(x+y) rules)
2607          *
2608          * As per MSDN, dst.z is undefined after the operation, and so is
2609          * dst.x and dst.y if they're masked out by the writemask. Ie
2610          * sincos dst.y, src1, c0, c1
2611          * returns the sine in dst.y. dst.x and dst.z are undefined, dst.w is not touched. The assembler
2612          * vsa.exe also stops with an error if the dest register is the same register as the source
2613          * register. This means we can use dest.xyz as temporary storage. The assembler vsa.exe output also
2614          * indicates that sincos consumes 8 instruction slots in vs_2_0(and, strangely, in vs_3_0).
2615          */
2616         shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
2617         shader_arb_get_src_param(ins, &ins->src[2], 2, src_name2);
2618         shader_arb_get_register_name(ins, &dst->reg, dst_name, &is_color);
2619
2620         shader_addline(buffer, "MUL %s.x, %s, %s;\n", dst_name, src_name0, src_name0);  /* x ^ 2 */
2621         shader_addline(buffer, "MUL TA.y, %s.x, %s;\n", dst_name, src_name0);           /* x ^ 3 */
2622         shader_addline(buffer, "MUL %s.y, TA.y, %s;\n", dst_name, src_name0);           /* x ^ 4 */
2623         shader_addline(buffer, "MUL TA.z, %s.y, %s;\n", dst_name, src_name0);           /* x ^ 5 */
2624         shader_addline(buffer, "MUL %s.z, TA.z, %s;\n", dst_name, src_name0);           /* x ^ 6 */
2625         shader_addline(buffer, "MUL TA.w, %s.z, %s;\n", dst_name, src_name0);           /* x ^ 7 */
2626
2627         /* sin(x/2)
2628          *
2629          * Unfortunately we don't get the constants in a DP4-capable form. Is there a way to
2630          * properly merge that with MULs in the code above?
2631          * The swizzles .yz and xw however fit into the .yzxw swizzle added to ps_2_0. Maybe
2632          * we can merge the sine and cosine MAD rows to calculate them together.
2633          */
2634         shader_addline(buffer, "MUL TA.x, %s, %s.w;\n", src_name0, src_name2); /* x^1, +1/(1!*2) */
2635         shader_addline(buffer, "MAD TA.x, TA.y, %s.x, TA.x;\n", src_name2); /* -1/(3!*8) */
2636         shader_addline(buffer, "MAD TA.x, TA.z, %s.w, TA.x;\n", src_name1); /* +1/(5!*32) */
2637         shader_addline(buffer, "MAD TA.x, TA.w, %s.x, TA.x;\n", src_name1); /* -1/(7!*128) */
2638
2639         /* cos(x/2) */
2640         shader_addline(buffer, "MAD TA.y, %s.x, %s.y, %s.z;\n", dst_name, src_name2, src_name2); /* -1/(2!*4), +1.0 */
2641         shader_addline(buffer, "MAD TA.y, %s.y, %s.z, TA.y;\n", dst_name, src_name1); /* +1/(4!*16) */
2642         shader_addline(buffer, "MAD TA.y, %s.z, %s.y, TA.y;\n", dst_name, src_name1); /* -1/(6!*64) */
2643
2644         if(dst->write_mask & WINED3DSP_WRITEMASK_0) {
2645             /* cos x */
2646             shader_addline(buffer, "MUL TA.z, TA.y, TA.y;\n");
2647             shader_addline(buffer, "MAD %s.x, -TA.x, TA.x, TA.z;\n", dst_name);
2648         }
2649         if(dst->write_mask & WINED3DSP_WRITEMASK_1) {
2650             /* sin x */
2651             shader_addline(buffer, "MUL %s.y, TA.x, TA.y;\n", dst_name);
2652             shader_addline(buffer, "ADD %s.y, %s.y, %s.y;\n", dst_name, dst_name, dst_name);
2653         }
2654     }
2655 }
2656
2657 static void shader_hw_sgn(const struct wined3d_shader_instruction *ins)
2658 {
2659     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2660     char dst_name[50];
2661     char src_name[50];
2662     struct shader_arb_ctx_priv *ctx = ins->ctx->backend_data;
2663
2664     shader_arb_get_dst_param(ins, &ins->dst[0], dst_name);
2665     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
2666
2667     /* SGN is only valid in vertex shaders */
2668     if(ctx->target_version >= NV2) {
2669         shader_addline(buffer, "SSG%s %s, %s;\n", shader_arb_get_modifier(ins), dst_name, src_name);
2670         return;
2671     }
2672
2673     /* If SRC > 0.0, -SRC < SRC = TRUE, otherwise false.
2674      * if SRC < 0.0,  SRC < -SRC = TRUE. If neither is true, src = 0.0
2675      */
2676     if(ins->dst[0].modifiers & WINED3DSPDM_SATURATE) {
2677         shader_addline(buffer, "SLT %s, -%s, %s;\n", dst_name, src_name, src_name);
2678     } else {
2679         /* src contains TA? Write to the dest first. This won't overwrite our destination.
2680          * Then use TA, and calculate the final result
2681          *
2682          * Not reading from TA? Store the first result in TA to avoid overwriting the
2683          * destination if src reg = dst reg
2684          */
2685         if(strstr(src_name, "TA"))
2686         {
2687             shader_addline(buffer, "SLT %s,  %s, -%s;\n", dst_name, src_name, src_name);
2688             shader_addline(buffer, "SLT TA, -%s, %s;\n", src_name, src_name);
2689             shader_addline(buffer, "ADD %s, %s, -TA;\n", dst_name, dst_name);
2690         }
2691         else
2692         {
2693             shader_addline(buffer, "SLT TA, -%s, %s;\n", src_name, src_name);
2694             shader_addline(buffer, "SLT %s,  %s, -%s;\n", dst_name, src_name, src_name);
2695             shader_addline(buffer, "ADD %s, TA, -%s;\n", dst_name, dst_name);
2696         }
2697     }
2698 }
2699
2700 static void shader_hw_dsy(const struct wined3d_shader_instruction *ins)
2701 {
2702     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2703     char src[50];
2704     char dst[50];
2705     char dst_name[50];
2706     BOOL is_color;
2707
2708     shader_arb_get_dst_param(ins, &ins->dst[0], dst);
2709     shader_arb_get_src_param(ins, &ins->src[0], 0, src);
2710     shader_arb_get_register_name(ins, &ins->dst[0].reg, dst_name, &is_color);
2711
2712     shader_addline(buffer, "DDY %s, %s;\n", dst, src);
2713     shader_addline(buffer, "MUL%s %s, %s, ycorrection.y;\n", shader_arb_get_modifier(ins), dst, dst_name);
2714 }
2715
2716 static DWORD abs_modifier(DWORD mod, BOOL *need_abs)
2717 {
2718     *need_abs = FALSE;
2719
2720     switch(mod)
2721     {
2722         case WINED3DSPSM_NONE:      return WINED3DSPSM_ABS;
2723         case WINED3DSPSM_NEG:       return WINED3DSPSM_ABS;
2724         case WINED3DSPSM_BIAS:      *need_abs = TRUE; return WINED3DSPSM_BIAS;
2725         case WINED3DSPSM_BIASNEG:   *need_abs = TRUE; return WINED3DSPSM_BIASNEG;
2726         case WINED3DSPSM_SIGN:      *need_abs = TRUE; return WINED3DSPSM_SIGN;
2727         case WINED3DSPSM_SIGNNEG:   *need_abs = TRUE; return WINED3DSPSM_SIGNNEG;
2728         case WINED3DSPSM_COMP:      *need_abs = TRUE; return WINED3DSPSM_COMP;
2729         case WINED3DSPSM_X2:        *need_abs = TRUE; return WINED3DSPSM_X2;
2730         case WINED3DSPSM_X2NEG:     *need_abs = TRUE; return WINED3DSPSM_X2NEG;
2731         case WINED3DSPSM_DZ:        *need_abs = TRUE; return WINED3DSPSM_DZ;
2732         case WINED3DSPSM_DW:        *need_abs = TRUE; return WINED3DSPSM_DW;
2733         case WINED3DSPSM_ABS:       return WINED3DSPSM_ABS;
2734         case WINED3DSPSM_ABSNEG:    return WINED3DSPSM_ABS;
2735     }
2736     FIXME("Unknown modifier %u\n", mod);
2737     return mod;
2738 }
2739
2740 static void shader_hw_log_pow(const struct wined3d_shader_instruction *ins)
2741 {
2742     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2743     char src0[50], src1[50], dst[50];
2744     struct wined3d_shader_src_param src0_copy = ins->src[0];
2745     BOOL need_abs = FALSE;
2746     const char *instr;
2747     BOOL arg2 = FALSE;
2748
2749     switch(ins->handler_idx)
2750     {
2751         case WINED3DSIH_LOG:  instr = "LG2"; break;
2752         case WINED3DSIH_LOGP: instr = "LOG"; break;
2753         case WINED3DSIH_POW:  instr = "POW"; arg2 = TRUE; break;
2754         default:
2755             ERR("Unexpected instruction %d\n", ins->handler_idx);
2756             return;
2757     }
2758
2759     /* LOG, LOGP and POW operate on the absolute value of the input */
2760     src0_copy.modifiers = abs_modifier(src0_copy.modifiers, &need_abs);
2761
2762     shader_arb_get_dst_param(ins, &ins->dst[0], dst);
2763     shader_arb_get_src_param(ins, &src0_copy, 0, src0);
2764     if(arg2) shader_arb_get_src_param(ins, &ins->src[1], 1, src1);
2765
2766     if(need_abs)
2767     {
2768         shader_addline(buffer, "ABS TA, %s;\n", src0);
2769         if(arg2)
2770         {
2771             shader_addline(buffer, "%s%s %s, TA, %s;\n", instr, shader_arb_get_modifier(ins), dst, src1);
2772         }
2773         else
2774         {
2775             shader_addline(buffer, "%s%s %s, TA;\n", instr, shader_arb_get_modifier(ins), dst);
2776         }
2777     }
2778     else if(arg2)
2779     {
2780         shader_addline(buffer, "%s%s %s, %s, %s;\n", instr, shader_arb_get_modifier(ins), dst, src0, src1);
2781     }
2782     else
2783     {
2784         shader_addline(buffer, "%s%s %s, %s;\n", instr, shader_arb_get_modifier(ins), dst, src0);
2785     }
2786 }
2787
2788 static void shader_hw_loop(const struct wined3d_shader_instruction *ins)
2789 {
2790     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2791     char src_name[50];
2792     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2793
2794     /* src0 is aL */
2795     shader_arb_get_src_param(ins, &ins->src[1], 0, src_name);
2796
2797     if(vshader)
2798     {
2799         struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2800         struct list *e = list_head(&priv->control_frames);
2801         struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
2802
2803         if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n");
2804         /* The constant loader makes sure to load -1 into iX.w */
2805         shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name);
2806         shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->no.loop);
2807         shader_addline(buffer, "loop_%u_start:\n", control_frame->no.loop);
2808     }
2809     else
2810     {
2811         shader_addline(buffer, "LOOP %s;\n", src_name);
2812     }
2813 }
2814
2815 static void shader_hw_rep(const struct wined3d_shader_instruction *ins)
2816 {
2817     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2818     char src_name[50];
2819     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2820
2821     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name);
2822
2823     /* The constant loader makes sure to load -1 into iX.w */
2824     if(vshader)
2825     {
2826         struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2827         struct list *e = list_head(&priv->control_frames);
2828         struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
2829
2830         if(priv->loop_depth > 1) shader_addline(buffer, "PUSHA aL;\n");
2831
2832         shader_addline(buffer, "ARLC aL, %s.xywz;\n", src_name);
2833         shader_addline(buffer, "BRA loop_%u_end (LE.x);\n", control_frame->no.loop);
2834         shader_addline(buffer, "loop_%u_start:\n", control_frame->no.loop);
2835     }
2836     else
2837     {
2838         shader_addline(buffer, "REP %s;\n", src_name);
2839     }
2840 }
2841
2842 static void shader_hw_endloop(const struct wined3d_shader_instruction *ins)
2843 {
2844     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2845     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2846
2847     if(vshader)
2848     {
2849         struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2850         struct list *e = list_head(&priv->control_frames);
2851         struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
2852
2853         shader_addline(buffer, "ARAC aL.xy, aL;\n");
2854         shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->no.loop);
2855         shader_addline(buffer, "loop_%u_end:\n", control_frame->no.loop);
2856
2857         if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n");
2858     }
2859     else
2860     {
2861         shader_addline(buffer, "ENDLOOP;\n");
2862     }
2863 }
2864
2865 static void shader_hw_endrep(const struct wined3d_shader_instruction *ins)
2866 {
2867     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2868     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2869
2870     if(vshader)
2871     {
2872         struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2873         struct list *e = list_head(&priv->control_frames);
2874         struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
2875
2876         shader_addline(buffer, "ARAC aL.xy, aL;\n");
2877         shader_addline(buffer, "BRA loop_%u_start (GT.x);\n", control_frame->no.loop);
2878         shader_addline(buffer, "loop_%u_end:\n", control_frame->no.loop);
2879
2880         if(priv->loop_depth > 1) shader_addline(buffer, "POPA aL;\n");
2881     }
2882     else
2883     {
2884         shader_addline(buffer, "ENDREP;\n");
2885     }
2886 }
2887
2888 static const struct control_frame *find_last_loop(const struct shader_arb_ctx_priv *priv)
2889 {
2890     struct control_frame *control_frame;
2891
2892     LIST_FOR_EACH_ENTRY(control_frame, &priv->control_frames, struct control_frame, entry)
2893     {
2894         if(control_frame->type == LOOP || control_frame->type == REP) return control_frame;
2895     }
2896     ERR("Could not find loop for break\n");
2897     return NULL;
2898 }
2899
2900 static void shader_hw_break(const struct wined3d_shader_instruction *ins)
2901 {
2902     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2903     const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data);
2904     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2905
2906     if(vshader)
2907     {
2908         shader_addline(buffer, "BRA loop_%u_end;\n", control_frame->no.loop);
2909     }
2910     else
2911     {
2912         shader_addline(buffer, "BRK;\n");
2913     }
2914 }
2915
2916 static const char *get_compare(COMPARISON_TYPE flags)
2917 {
2918     switch (flags)
2919     {
2920         case COMPARISON_GT: return "GT";
2921         case COMPARISON_EQ: return "EQ";
2922         case COMPARISON_GE: return "GE";
2923         case COMPARISON_LT: return "LT";
2924         case COMPARISON_NE: return "NE";
2925         case COMPARISON_LE: return "LE";
2926         default:
2927             FIXME("Unrecognized comparison value: %u\n", flags);
2928             return "(\?\?)";
2929     }
2930 }
2931
2932 static COMPARISON_TYPE invert_compare(COMPARISON_TYPE flags)
2933 {
2934     switch (flags)
2935     {
2936         case COMPARISON_GT: return COMPARISON_LE;
2937         case COMPARISON_EQ: return COMPARISON_NE;
2938         case COMPARISON_GE: return COMPARISON_LT;
2939         case COMPARISON_LT: return COMPARISON_GE;
2940         case COMPARISON_NE: return COMPARISON_EQ;
2941         case COMPARISON_LE: return COMPARISON_GT;
2942         default:
2943             FIXME("Unrecognized comparison value: %u\n", flags);
2944             return -1;
2945     }
2946 }
2947
2948 static void shader_hw_breakc(const struct wined3d_shader_instruction *ins)
2949 {
2950     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2951     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2952     const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data);
2953     char src_name0[50];
2954     char src_name1[50];
2955     const char *comp = get_compare(ins->flags);
2956
2957     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
2958     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
2959
2960     if(vshader)
2961     {
2962         /* SUBC CC, src0, src1" works only in pixel shaders, so use TA to throw
2963          * away the subtraction result
2964          */
2965         shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
2966         shader_addline(buffer, "BRA loop_%u_end (%s.x);\n", control_frame->no.loop, comp);
2967     }
2968     else
2969     {
2970         shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
2971         shader_addline(buffer, "BRK (%s.x);\n", comp);
2972     }
2973 }
2974
2975 static void shader_hw_ifc(const struct wined3d_shader_instruction *ins)
2976 {
2977     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
2978     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
2979     struct list *e = list_head(&priv->control_frames);
2980     struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
2981     const char *comp;
2982     char src_name0[50];
2983     char src_name1[50];
2984     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
2985
2986     shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
2987     shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
2988
2989     if(vshader)
2990     {
2991         /* Invert the flag. We jump to the else label if the condition is NOT true */
2992         comp = get_compare(invert_compare(ins->flags));
2993         shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
2994         shader_addline(buffer, "BRA ifc_%u_else (%s.x);\n", control_frame->no.ifc, comp);
2995     }
2996     else
2997     {
2998         comp = get_compare(ins->flags);
2999         shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
3000         shader_addline(buffer, "IF %s.x;\n", comp);
3001     }
3002 }
3003
3004 static void shader_hw_else(const struct wined3d_shader_instruction *ins)
3005 {
3006     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
3007     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
3008     struct list *e = list_head(&priv->control_frames);
3009     struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
3010     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
3011
3012     if(vshader)
3013     {
3014         shader_addline(buffer, "BRA ifc_%u_endif;\n", control_frame->no.ifc);
3015         shader_addline(buffer, "ifc_%u_else:\n", control_frame->no.ifc);
3016         control_frame->had_else = TRUE;
3017     }
3018     else
3019     {
3020         shader_addline(buffer, "ELSE;\n");
3021     }
3022 }
3023
3024 static void shader_hw_endif(const struct wined3d_shader_instruction *ins)
3025 {
3026     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
3027     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
3028     struct list *e = list_head(&priv->control_frames);
3029     struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
3030     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
3031
3032     if(vshader)
3033     {
3034         if(control_frame->had_else)
3035         {
3036             shader_addline(buffer, "ifc_%u_endif:\n", control_frame->no.ifc);
3037         }
3038         else
3039         {
3040             shader_addline(buffer, "#No else branch. else is endif\n");
3041             shader_addline(buffer, "ifc_%u_else:\n", control_frame->no.ifc);
3042         }
3043     }
3044     else
3045     {
3046         shader_addline(buffer, "ENDIF;\n");
3047     }
3048 }
3049
3050 static void shader_hw_texldd(const struct wined3d_shader_instruction *ins)
3051 {
3052     DWORD sampler_idx = ins->src[1].reg.idx;
3053     char reg_dest[40];
3054     char reg_src[3][40];
3055     WORD flags = TEX_DERIV;
3056
3057     shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest);
3058     shader_arb_get_src_param(ins, &ins->src[0], 0, reg_src[0]);
3059     shader_arb_get_src_param(ins, &ins->src[2], 1, reg_src[1]);
3060     shader_arb_get_src_param(ins, &ins->src[3], 2, reg_src[2]);
3061
3062     if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ;
3063     if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS;
3064
3065     shader_hw_sample(ins, sampler_idx, reg_dest, reg_src[0], flags, reg_src[1], reg_src[2]);
3066 }
3067
3068 static void shader_hw_texldl(const struct wined3d_shader_instruction *ins)
3069 {
3070     DWORD sampler_idx = ins->src[1].reg.idx;
3071     char reg_dest[40];
3072     char reg_coord[40];
3073     WORD flags = TEX_LOD;
3074
3075     shader_arb_get_dst_param(ins, &ins->dst[0], reg_dest);
3076     shader_arb_get_src_param(ins, &ins->src[0], 0, reg_coord);
3077
3078     if (ins->flags & WINED3DSI_TEXLD_PROJECT) flags |= TEX_PROJ;
3079     if (ins->flags & WINED3DSI_TEXLD_BIAS) flags |= TEX_BIAS;
3080
3081     shader_hw_sample(ins, sampler_idx, reg_dest, reg_coord, flags, NULL, NULL);
3082 }
3083
3084 static void shader_hw_label(const struct wined3d_shader_instruction *ins)
3085 {
3086     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
3087     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
3088
3089     priv->in_main_func = FALSE;
3090     /* Call instructions activate the NV extensions, not labels and rets. If there is an uncalled
3091      * subroutine, don't generate a label that will make GL complain
3092      */
3093     if(priv->target_version == ARB) return;
3094
3095     shader_addline(buffer, "l%u:\n", ins->src[0].reg.idx);
3096 }
3097
3098 static void vshader_add_footer(IWineD3DVertexShaderImpl *This, struct wined3d_shader_buffer *buffer,
3099         const struct arb_vs_compile_args *args, struct shader_arb_ctx_priv *priv_ctx)
3100 {
3101     const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
3102     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device;
3103     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
3104     unsigned int i;
3105
3106     /* The D3DRS_FOGTABLEMODE render state defines if the shader-generated fog coord is used
3107      * or if the fragment depth is used. If the fragment depth is used(FOGTABLEMODE != NONE),
3108      * the fog frag coord is thrown away. If the fog frag coord is used, but not written by
3109      * the shader, it is set to 0.0(fully fogged, since start = 1.0, end = 0.0)
3110      */
3111     if(args->super.fog_src == VS_FOG_Z) {
3112         shader_addline(buffer, "MOV result.fogcoord, TMP_OUT.z;\n");
3113     } else if (!reg_maps->fog) {
3114         /* posFixup.x is always 1.0, so we can savely use it */
3115         shader_addline(buffer, "ADD result.fogcoord, posFixup.x, -posFixup.x;\n");
3116     }
3117
3118     /* Write the final position.
3119      *
3120      * OpenGL coordinates specify the center of the pixel while d3d coords specify
3121      * the corner. The offsets are stored in z and w in posFixup. posFixup.y contains
3122      * 1.0 or -1.0 to turn the rendering upside down for offscreen rendering. PosFixup.x
3123      * contains 1.0 to allow a mad, but arb vs swizzles are too restricted for that.
3124      */
3125     shader_addline(buffer, "MUL TA, posFixup, TMP_OUT.w;\n");
3126     shader_addline(buffer, "ADD TMP_OUT.x, TMP_OUT.x, TA.z;\n");
3127     shader_addline(buffer, "MAD TMP_OUT.y, TMP_OUT.y, posFixup.y, TA.w;\n");
3128
3129     if(use_nv_clip(gl_info) && priv_ctx->target_version >= NV2)
3130     {
3131         if(args->super.clip_enabled)
3132         {
3133             for(i = 0; i < priv_ctx->vs_clipplanes; i++)
3134             {
3135                 shader_addline(buffer, "DP4 result.clip[%u].x, TMP_OUT, state.clip[%u].plane;\n", i, i);
3136             }
3137         }
3138     }
3139     else if(args->clip.boolclip.clip_texcoord)
3140     {
3141         unsigned int cur_clip = 0;
3142         char component[4] = {'x', 'y', 'z', 'w'};
3143         const char *zero = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ZERO);
3144
3145         for (i = 0; i < gl_info->limits.clipplanes; ++i)
3146         {
3147             if(args->clip.boolclip.clipplane_mask & (1 << i))
3148             {
3149                 shader_addline(buffer, "DP4 TA.%c, TMP_OUT, state.clip[%u].plane;\n",
3150                                component[cur_clip++], i);
3151             }
3152         }
3153         switch(cur_clip)
3154         {
3155             case 0:
3156                 shader_addline(buffer, "MOV TA, %s;\n", zero);
3157                 break;
3158             case 1:
3159                 shader_addline(buffer, "MOV TA.yzw, %s;\n", zero);
3160                 break;
3161             case 2:
3162                 shader_addline(buffer, "MOV TA.zw, %s;\n", zero);
3163                 break;
3164             case 3:
3165                 shader_addline(buffer, "MOV TA.w, %s;\n", zero);
3166                 break;
3167         }
3168         shader_addline(buffer, "MOV result.texcoord[%u], TA;\n",
3169                        args->clip.boolclip.clip_texcoord - 1);
3170     }
3171
3172     /* Z coord [0;1]->[-1;1] mapping, see comment in transform_projection in state.c
3173      * and the glsl equivalent
3174      */
3175     if(need_helper_const((IWineD3DBaseShaderImpl *) This, gl_info)) {
3176         const char *two = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_TWO);
3177         shader_addline(buffer, "MAD TMP_OUT.z, TMP_OUT.z, %s, -TMP_OUT.w;\n", two);
3178     } else {
3179         shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, TMP_OUT.z;\n");
3180         shader_addline(buffer, "ADD TMP_OUT.z, TMP_OUT.z, -TMP_OUT.w;\n");
3181     }
3182
3183     shader_addline(buffer, "MOV result.position, TMP_OUT;\n");
3184
3185     priv_ctx->footer_written = TRUE;
3186 }
3187
3188 static void shader_hw_ret(const struct wined3d_shader_instruction *ins)
3189 {
3190     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
3191     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
3192     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *) ins->ctx->shader;
3193     BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
3194
3195     if(priv->target_version == ARB) return;
3196
3197     if(vshader)
3198     {
3199         if(priv->in_main_func) vshader_add_footer((IWineD3DVertexShaderImpl *) shader, buffer, priv->cur_vs_args, priv);
3200     }
3201
3202     shader_addline(buffer, "RET;\n");
3203 }
3204
3205 static void shader_hw_call(const struct wined3d_shader_instruction *ins)
3206 {
3207     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
3208     shader_addline(buffer, "CAL l%u;\n", ins->src[0].reg.idx);
3209 }
3210
3211 /* GL locking is done by the caller */
3212 static GLuint create_arb_blt_vertex_program(const struct wined3d_gl_info *gl_info)
3213 {
3214     GLuint program_id = 0;
3215     GLint pos;
3216
3217     const char *blt_vprogram =
3218         "!!ARBvp1.0\n"
3219         "PARAM c[1] = { { 1, 0.5 } };\n"
3220         "MOV result.position, vertex.position;\n"
3221         "MOV result.color, c[0].x;\n"
3222         "MOV result.texcoord[0], vertex.texcoord[0];\n"
3223         "END\n";
3224
3225     GL_EXTCALL(glGenProgramsARB(1, &program_id));
3226     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, program_id));
3227     GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
3228             strlen(blt_vprogram), blt_vprogram));
3229     checkGLcall("glProgramStringARB()");
3230
3231     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
3232     if (pos != -1)
3233     {
3234         FIXME("Vertex program error at position %d: %s\n\n", pos,
3235             debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
3236         shader_arb_dump_program_source(blt_vprogram);
3237     }
3238     else
3239     {
3240         GLint native;
3241
3242         GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
3243         checkGLcall("glGetProgramivARB()");
3244         if (!native) WARN("Program exceeds native resource limits.\n");
3245     }
3246
3247     return program_id;
3248 }
3249
3250 /* GL locking is done by the caller */
3251 static GLuint create_arb_blt_fragment_program(const struct wined3d_gl_info *gl_info,
3252         enum tex_types tex_type, BOOL masked)
3253 {
3254     GLuint program_id = 0;
3255     const char *fprogram;
3256     GLint pos;
3257
3258     static const char * const blt_fprograms_full[tex_type_count] =
3259     {
3260         /* tex_1d */
3261         NULL,
3262         /* tex_2d */
3263         "!!ARBfp1.0\n"
3264         "TEMP R0;\n"
3265         "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n"
3266         "MOV result.depth.z, R0.x;\n"
3267         "END\n",
3268         /* tex_3d */
3269         NULL,
3270         /* tex_cube */
3271         "!!ARBfp1.0\n"
3272         "TEMP R0;\n"
3273         "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n"
3274         "MOV result.depth.z, R0.x;\n"
3275         "END\n",
3276         /* tex_rect */
3277         "!!ARBfp1.0\n"
3278         "TEMP R0;\n"
3279         "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n"
3280         "MOV result.depth.z, R0.x;\n"
3281         "END\n",
3282     };
3283
3284     static const char * const blt_fprograms_masked[tex_type_count] =
3285     {
3286         /* tex_1d */
3287         NULL,
3288         /* tex_2d */
3289         "!!ARBfp1.0\n"
3290         "PARAM mask = program.local[0];\n"
3291         "TEMP R0;\n"
3292         "SLT R0.xy, fragment.position, mask.zwzw;\n"
3293         "MUL R0.x, R0.x, R0.y;\n"
3294         "KIL -R0.x;\n"
3295         "TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n"
3296         "MOV result.depth.z, R0.x;\n"
3297         "END\n",
3298         /* tex_3d */
3299         NULL,
3300         /* tex_cube */
3301         "!!ARBfp1.0\n"
3302         "PARAM mask = program.local[0];\n"
3303         "TEMP R0;\n"
3304         "SLT R0.xy, fragment.position, mask.zwzw;\n"
3305         "MUL R0.x, R0.x, R0.y;\n"
3306         "KIL -R0.x;\n"
3307         "TEX R0.x, fragment.texcoord[0], texture[0], CUBE;\n"
3308         "MOV result.depth.z, R0.x;\n"
3309         "END\n",
3310         /* tex_rect */
3311         "!!ARBfp1.0\n"
3312         "PARAM mask = program.local[0];\n"
3313         "TEMP R0;\n"
3314         "SLT R0.xy, fragment.position, mask.zwzw;\n"
3315         "MUL R0.x, R0.x, R0.y;\n"
3316         "KIL -R0.x;\n"
3317         "TEX R0.x, fragment.texcoord[0], texture[0], RECT;\n"
3318         "MOV result.depth.z, R0.x;\n"
3319         "END\n",
3320     };
3321
3322     fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type];
3323     if (!fprogram)
3324     {
3325         FIXME("tex_type %#x not supported, falling back to tex_2d\n", tex_type);
3326         tex_type = tex_2d;
3327         fprogram = masked ? blt_fprograms_masked[tex_type] : blt_fprograms_full[tex_type];
3328     }
3329
3330     GL_EXTCALL(glGenProgramsARB(1, &program_id));
3331     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id));
3332     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(fprogram), fprogram));
3333     checkGLcall("glProgramStringARB()");
3334
3335     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
3336     if (pos != -1)
3337     {
3338         FIXME("Fragment program error at position %d: %s\n\n", pos,
3339             debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
3340         shader_arb_dump_program_source(fprogram);
3341     }
3342     else
3343     {
3344         GLint native;
3345
3346         GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
3347         checkGLcall("glGetProgramivARB()");
3348         if (!native) WARN("Program exceeds native resource limits.\n");
3349     }
3350
3351     return program_id;
3352 }
3353
3354 static void arbfp_add_sRGB_correction(struct wined3d_shader_buffer *buffer, const char *fragcolor,
3355         const char *tmp1, const char *tmp2, const char *tmp3, const char *tmp4, BOOL condcode)
3356 {
3357     /* Perform sRGB write correction. See GLX_EXT_framebuffer_sRGB */
3358
3359     if(condcode)
3360     {
3361         /* Sigh. MOVC CC doesn't work, so use one of the temps as dummy dest */
3362         shader_addline(buffer, "SUBC %s, %s.x, srgb_consts1.y;\n", tmp1, fragcolor);
3363         /* Calculate the > 0.0031308 case */
3364         shader_addline(buffer, "POW %s.x (GE), %s.x, srgb_consts1.z;\n", fragcolor, fragcolor);
3365         shader_addline(buffer, "POW %s.y (GE), %s.y, srgb_consts1.z;\n", fragcolor, fragcolor);
3366         shader_addline(buffer, "POW %s.z (GE), %s.z, srgb_consts1.z;\n", fragcolor, fragcolor);
3367         shader_addline(buffer, "MUL %s.xyz (GE), %s, srgb_consts1.w;\n", fragcolor, fragcolor);
3368         shader_addline(buffer, "SUB %s.xyz (GE), %s, srgb_consts2.x;\n", fragcolor, fragcolor);
3369         /* Calculate the < case */
3370         shader_addline(buffer, "MUL %s.xyz (LT), srgb_consts1.x, %s;\n", fragcolor, fragcolor);
3371     }
3372     else
3373     {
3374         /* Calculate the > 0.0031308 case */
3375         shader_addline(buffer, "POW %s.x, %s.x, srgb_consts1.z;\n", tmp1, fragcolor);
3376         shader_addline(buffer, "POW %s.y, %s.y, srgb_consts1.z;\n", tmp1, fragcolor);
3377         shader_addline(buffer, "POW %s.z, %s.z, srgb_consts1.z;\n", tmp1, fragcolor);
3378         shader_addline(buffer, "MUL %s, %s, srgb_consts1.w;\n", tmp1, tmp1);
3379         shader_addline(buffer, "SUB %s, %s, srgb_consts2.x;\n", tmp1, tmp1);
3380         /* Calculate the < case */
3381         shader_addline(buffer, "MUL %s, srgb_consts1.x, %s;\n", tmp2, fragcolor);
3382         /* Get 1.0 / 0.0 masks for > 0.0031308 and < 0.0031308 */
3383         shader_addline(buffer, "SLT %s, srgb_consts1.y, %s;\n", tmp3, fragcolor);
3384         shader_addline(buffer, "SGE %s, srgb_consts1.y, %s;\n", tmp4, fragcolor);
3385         /* Store the components > 0.0031308 in the destination */
3386         shader_addline(buffer, "MUL %s.xyz, %s, %s;\n", fragcolor, tmp1, tmp3);
3387         /* Add the components that are < 0.0031308 */
3388         shader_addline(buffer, "MAD %s.xyz, %s, %s, %s;\n", fragcolor, tmp2, tmp4, fragcolor);
3389         /* Move everything into result.color at once. Nvidia hardware cannot handle partial
3390         * result.color writes(.rgb first, then .a), or handle overwriting already written
3391         * components. The assembler uses a temporary register in this case, which is usually
3392         * not allocated from one of our registers that were used earlier.
3393         */
3394     }
3395     /* [0.0;1.0] clamping. Not needed, this is done implicitly */
3396 }
3397
3398 static const DWORD *find_loop_control_values(IWineD3DBaseShaderImpl *This, DWORD idx)
3399 {
3400     const local_constant *constant;
3401
3402     LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsI, local_constant, entry)
3403     {
3404         if (constant->idx == idx)
3405         {
3406             return constant->value;
3407         }
3408     }
3409     return NULL;
3410 }
3411
3412 static void init_ps_input(const IWineD3DPixelShaderImpl *This, const struct arb_ps_compile_args *args,
3413                           struct shader_arb_ctx_priv *priv)
3414 {
3415     static const char * const texcoords[8] =
3416     {
3417         "fragment.texcoord[0]", "fragment.texcoord[1]", "fragment.texcoord[2]", "fragment.texcoord[3]",
3418         "fragment.texcoord[4]", "fragment.texcoord[5]", "fragment.texcoord[6]", "fragment.texcoord[7]"
3419     };
3420     unsigned int i;
3421     const struct wined3d_shader_signature_element *sig = This->baseShader.input_signature;
3422     const char *semantic_name;
3423     DWORD semantic_idx;
3424
3425     switch(args->super.vp_mode)
3426     {
3427         case pretransformed:
3428         case fixedfunction:
3429             /* The pixelshader has to collect the varyings on its own. In any case properly load
3430              * color0 and color1. In the case of pretransformed vertices also load texcoords. Set
3431              * other attribs to 0.0.
3432              *
3433              * For fixedfunction this behavior is correct, according to the tests. For pretransformed
3434              * we'd either need a replacement shader that can load other attribs like BINORMAL, or
3435              * load the texcoord attrib pointers to match the pixel shader signature
3436              */
3437             for(i = 0; i < MAX_REG_INPUT; i++)
3438             {
3439                 semantic_name = sig[i].semantic_name;
3440                 semantic_idx = sig[i].semantic_idx;
3441                 if(semantic_name == NULL) continue;
3442
3443                 if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR))
3444                 {
3445                     if(semantic_idx == 0) priv->ps_input[i] = "fragment.color.primary";
3446                     else if(semantic_idx == 1) priv->ps_input[i] = "fragment.color.secondary";
3447                     else priv->ps_input[i] = "0.0";
3448                 }
3449                 else if(args->super.vp_mode == fixedfunction)
3450                 {
3451                     priv->ps_input[i] = "0.0";
3452                 }
3453                 else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD))
3454                 {
3455                     if(semantic_idx < 8) priv->ps_input[i] = texcoords[semantic_idx];
3456                     else priv->ps_input[i] = "0.0";
3457                 }
3458                 else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG))
3459                 {
3460                     if(semantic_idx == 0) priv->ps_input[i] = "fragment.fogcoord";
3461                     else priv->ps_input[i] = "0.0";
3462                 }
3463                 else
3464                 {
3465                     priv->ps_input[i] = "0.0";
3466                 }
3467
3468                 TRACE("v%u, semantic %s%u is %s\n", i, semantic_name, semantic_idx, priv->ps_input[i]);
3469             }
3470             break;
3471
3472         case vertexshader:
3473             /* That one is easy. The vertex shaders provide v0-v7 in fragment.texcoord and v8 and v9 in
3474              * fragment.color
3475              */
3476             for(i = 0; i < 8; i++)
3477             {
3478                 priv->ps_input[i] = texcoords[i];
3479             }
3480             priv->ps_input[8] = "fragment.color.primary";
3481             priv->ps_input[9] = "fragment.color.secondary";
3482             break;
3483     }
3484 }
3485
3486 /* GL locking is done by the caller */
3487 static GLuint shader_arb_generate_pshader(IWineD3DPixelShaderImpl *This, struct wined3d_shader_buffer *buffer,
3488         const struct arb_ps_compile_args *args, struct arb_ps_compiled_shader *compiled)
3489 {
3490     const shader_reg_maps* reg_maps = &This->baseShader.reg_maps;
3491     CONST DWORD *function = This->baseShader.function;
3492     const struct wined3d_gl_info *gl_info = &((IWineD3DDeviceImpl *)This->baseShader.device)->adapter->gl_info;
3493     const local_constant *lconst;
3494     GLuint retval;
3495     char fragcolor[16];
3496     DWORD *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This), next_local, cur;
3497     struct shader_arb_ctx_priv priv_ctx;
3498     BOOL dcl_td = FALSE;
3499     BOOL want_nv_prog = FALSE;
3500     struct arb_pshader_private *shader_priv = This->baseShader.backend_data;
3501     GLint errPos;
3502     DWORD map;
3503
3504     char srgbtmp[4][4];
3505     unsigned int i, found = 0;
3506
3507     for (i = 0, map = reg_maps->temporary; map; map >>= 1, ++i)
3508     {
3509         if (!(map & 1)
3510                 || (This->color0_mov && i == This->color0_reg)
3511                 || (reg_maps->shader_version.major < 2 && i == 0))
3512             continue;
3513
3514         sprintf(srgbtmp[found], "R%u", i);
3515         ++found;
3516         if (found == 4) break;
3517     }
3518
3519     switch(found) {
3520         case 0:
3521             sprintf(srgbtmp[0], "TA");
3522             sprintf(srgbtmp[1], "TB");
3523             sprintf(srgbtmp[2], "TC");
3524             sprintf(srgbtmp[3], "TD");
3525             dcl_td = TRUE;
3526             break;
3527         case 1:
3528             sprintf(srgbtmp[1], "TA");
3529             sprintf(srgbtmp[2], "TB");
3530             sprintf(srgbtmp[3], "TC");
3531             break;
3532         case 2:
3533             sprintf(srgbtmp[2], "TA");
3534             sprintf(srgbtmp[3], "TB");
3535             break;
3536         case 3:
3537             sprintf(srgbtmp[3], "TA");
3538             break;
3539         case 4:
3540             break;
3541     }
3542
3543     /*  Create the hw ARB shader */
3544     memset(&priv_ctx, 0, sizeof(priv_ctx));
3545     priv_ctx.cur_ps_args = args;
3546     priv_ctx.compiled_fprog = compiled;
3547     priv_ctx.cur_np2fixup_info = &compiled->np2fixup_info;
3548     init_ps_input(This, args, &priv_ctx);
3549     list_init(&priv_ctx.control_frames);
3550
3551     /* Avoid enabling NV_fragment_program* if we do not need it.
3552      *
3553      * Enabling GL_NV_fragment_program_option causes the driver to occupy a temporary register,
3554      * and it slows down the shader execution noticeably(about 5%). Usually our instruction emulation
3555      * is faster than what we gain from using higher native instructions. There are some things though
3556      * that cannot be emulated. In that case enable the extensions.
3557      * If the extension is enabled, instruction handlers that support both ways will use it.
3558      *
3559      * Testing shows no performance difference between OPTION NV_fragment_program2 and NV_fragment_program.
3560      * So enable the best we can get.
3561      */
3562     if(reg_maps->usesdsx || reg_maps->usesdsy || reg_maps->loop_depth > 0 || reg_maps->usestexldd ||
3563        reg_maps->usestexldl || reg_maps->usesfacing || reg_maps->usesifc || reg_maps->usescall)
3564     {
3565         want_nv_prog = TRUE;
3566     }
3567
3568     shader_addline(buffer, "!!ARBfp1.0\n");
3569     if (want_nv_prog && gl_info->supported[NV_FRAGMENT_PROGRAM2])
3570     {
3571         shader_addline(buffer, "OPTION NV_fragment_program2;\n");
3572         priv_ctx.target_version = NV3;
3573     }
3574     else if (want_nv_prog && gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION])
3575     {
3576         shader_addline(buffer, "OPTION NV_fragment_program;\n");
3577         priv_ctx.target_version = NV2;
3578     } else {
3579         if(want_nv_prog)
3580         {
3581             /* This is an error - either we're advertising the wrong shader version, or aren't enforcing some
3582              * limits properly
3583              */
3584             ERR("The shader requires instructions that are not available in plain GL_ARB_fragment_program\n");
3585             ERR("Try GLSL\n");
3586         }
3587         priv_ctx.target_version = ARB;
3588     }
3589
3590     if(This->baseShader.reg_maps.highest_render_target > 0)
3591     {
3592         shader_addline(buffer, "OPTION ARB_draw_buffers;\n");
3593     }
3594
3595     if (reg_maps->shader_version.major < 3)
3596     {
3597         switch(args->super.fog) {
3598             case FOG_OFF:
3599                 break;
3600             case FOG_LINEAR:
3601                 shader_addline(buffer, "OPTION ARB_fog_linear;\n");
3602                 break;
3603             case FOG_EXP:
3604                 shader_addline(buffer, "OPTION ARB_fog_exp;\n");
3605                 break;
3606             case FOG_EXP2:
3607                 shader_addline(buffer, "OPTION ARB_fog_exp2;\n");
3608                 break;
3609         }
3610     }
3611
3612     /* For now always declare the temps. At least the Nvidia assembler optimizes completely
3613      * unused temps away(but occupies them for the whole shader if they're used once). Always
3614      * declaring them avoids tricky bookkeeping work
3615      */
3616     shader_addline(buffer, "TEMP TA;\n");      /* Used for modifiers */
3617     shader_addline(buffer, "TEMP TB;\n");      /* Used for modifiers */
3618     shader_addline(buffer, "TEMP TC;\n");      /* Used for modifiers */
3619     if(dcl_td) shader_addline(buffer, "TEMP TD;\n"); /* Used for sRGB writing */
3620     shader_addline(buffer, "PARAM coefdiv = { 0.5, 0.25, 0.125, 0.0625 };\n");
3621     shader_addline(buffer, "PARAM coefmul = { 2, 4, 8, 16 };\n");
3622     shader_addline(buffer, "PARAM ps_helper_const = { 0.0, 1.0, %1.10f, 0.0 };\n", eps);
3623
3624     if (reg_maps->shader_version.major < 2)
3625     {
3626         strcpy(fragcolor, "R0");
3627     } else {
3628         if(args->super.srgb_correction) {
3629             if(This->color0_mov) {
3630                 sprintf(fragcolor, "R%u", This->color0_reg);
3631             } else {
3632                 shader_addline(buffer, "TEMP TMP_COLOR;\n");
3633                 strcpy(fragcolor, "TMP_COLOR");
3634             }
3635         } else {
3636             strcpy(fragcolor, "result.color");
3637         }
3638     }
3639
3640     if(args->super.srgb_correction) {
3641         shader_addline(buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
3642                        srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
3643         shader_addline(buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
3644                        srgb_sub_high, 0.0, 0.0, 0.0);
3645     }
3646
3647     /* Base Declarations */
3648     next_local = shader_generate_arb_declarations((IWineD3DBaseShader *)This,
3649             reg_maps, buffer, gl_info, lconst_map, NULL, &priv_ctx);
3650
3651     for (i = 0, map = reg_maps->bumpmat; map; map >>= 1, ++i)
3652     {
3653         if (!(map & 1)) continue;
3654
3655         cur = compiled->numbumpenvmatconsts;
3656         compiled->bumpenvmatconst[cur].const_num = WINED3D_CONST_NUM_UNUSED;
3657         compiled->bumpenvmatconst[cur].texunit = i;
3658         compiled->luminanceconst[cur].const_num = WINED3D_CONST_NUM_UNUSED;
3659         compiled->luminanceconst[cur].texunit = i;
3660
3661         /* We can fit the constants into the constant limit for sure because texbem, texbeml, bem and beml are only supported
3662          * in 1.x shaders, and GL_ARB_fragment_program has a constant limit of 24 constants. So in the worst case we're loading
3663          * 8 shader constants, 8 bump matrices and 8 luminance parameters and are perfectly fine. (No NP2 fixup on bumpmapped
3664          * textures due to conditional NP2 restrictions)
3665          *
3666          * Use local constants to load the bump env parameters, not program.env. This avoids collisions with d3d constants of
3667          * shaders in newer shader models. Since the bump env parameters have to share their space with NP2 fixup constants,
3668          * their location is shader dependent anyway and they cannot be loaded globally.
3669          */
3670         compiled->bumpenvmatconst[cur].const_num = next_local++;
3671         shader_addline(buffer, "PARAM bumpenvmat%d = program.local[%d];\n",
3672                        i, compiled->bumpenvmatconst[cur].const_num);
3673         compiled->numbumpenvmatconsts = cur + 1;
3674
3675         if (!(reg_maps->luminanceparams & (1 << i))) continue;
3676
3677         compiled->luminanceconst[cur].const_num = next_local++;
3678         shader_addline(buffer, "PARAM luminance%d = program.local[%d];\n",
3679                        i, compiled->luminanceconst[cur].const_num);
3680     }
3681
3682     for(i = 0; i < MAX_CONST_I; i++)
3683     {
3684         compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
3685         if (reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
3686         {
3687             const DWORD *control_values = find_loop_control_values((IWineD3DBaseShaderImpl *) This, i);
3688
3689             if(control_values)
3690             {
3691                 shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i,
3692                                 control_values[0], control_values[1], control_values[2]);
3693             }
3694             else
3695             {
3696                 compiled->int_consts[i] = next_local;
3697                 compiled->num_int_consts++;
3698                 shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++);
3699             }
3700         }
3701     }
3702
3703     if(reg_maps->vpos || reg_maps->usesdsy)
3704     {
3705         compiled->ycorrection = next_local;
3706         shader_addline(buffer, "PARAM ycorrection = program.local[%u];\n", next_local++);
3707
3708         if(reg_maps->vpos)
3709         {
3710             shader_addline(buffer, "TEMP vpos;\n");
3711             /* ycorrection.x: Backbuffer height(onscreen) or 0(offscreen).
3712              * ycorrection.y: -1.0(onscreen), 1.0(offscreen)
3713              * ycorrection.z: 1.0
3714              * ycorrection.w: 0.0
3715              */
3716             shader_addline(buffer, "MAD vpos, fragment.position, ycorrection.zyww, ycorrection.wxww;\n");
3717             shader_addline(buffer, "FLR vpos.xy, vpos;\n");
3718         }
3719     }
3720     else
3721     {
3722         compiled->ycorrection = WINED3D_CONST_NUM_UNUSED;
3723     }
3724
3725     /* Load constants to fixup NP2 texcoords if there are still free constants left:
3726      * Constants (texture dimensions) for the NP2 fixup are loaded as local program parameters. This will consume
3727      * at most 8 (MAX_FRAGMENT_SAMPLERS / 2) parameters, which is highly unlikely, since the application had to
3728      * use 16 NP2 textures at the same time. In case that we run out of constants the fixup is simply not
3729      * applied / activated. This will probably result in wrong rendering of the texture, but will save us from
3730      * shader compilation errors and the subsequent errors when drawing with this shader. */
3731     if (priv_ctx.cur_ps_args->super.np2_fixup) {
3732
3733         struct arb_ps_np2fixup_info* const fixup = priv_ctx.cur_np2fixup_info;
3734         const WORD map = priv_ctx.cur_ps_args->super.np2_fixup;
3735         const UINT max_lconsts = gl_info->limits.arb_ps_local_constants;
3736
3737         fixup->offset = next_local;
3738         fixup->super.active = 0;
3739
3740         cur = 0;
3741         for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i) {
3742             if (!(map & (1 << i))) continue;
3743
3744             if (fixup->offset + (cur >> 1) < max_lconsts) {
3745                 fixup->super.active |= (1 << i);
3746                 fixup->super.idx[i] = cur++;
3747             } else {
3748                 FIXME("No free constant found to load NP2 fixup data into shader. "
3749                       "Sampling from this texture will probably look wrong.\n");
3750                 break;
3751             }
3752         }
3753
3754         fixup->super.num_consts = (cur + 1) >> 1;
3755         if (fixup->super.num_consts) {
3756             shader_addline(buffer, "PARAM np2fixup[%u] = { program.env[%u..%u] };\n",
3757                            fixup->super.num_consts, fixup->offset, fixup->super.num_consts + fixup->offset - 1);
3758         }
3759
3760         next_local += fixup->super.num_consts;
3761     }
3762
3763     if (shader_priv->clipplane_emulation != ~0U && args->clip)
3764     {
3765         shader_addline(buffer, "KIL fragment.texcoord[%u];\n", shader_priv->clipplane_emulation);
3766     }
3767
3768     /* Base Shader Body */
3769     shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
3770
3771     if(args->super.srgb_correction) {
3772         arbfp_add_sRGB_correction(buffer, fragcolor, srgbtmp[0], srgbtmp[1], srgbtmp[2], srgbtmp[3],
3773                                   priv_ctx.target_version >= NV2);
3774     }
3775
3776     if(strcmp(fragcolor, "result.color")) {
3777         shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
3778     }
3779     shader_addline(buffer, "END\n");
3780
3781     /* TODO: change to resource.glObjectHandle or something like that */
3782     GL_EXTCALL(glGenProgramsARB(1, &retval));
3783
3784     TRACE("Creating a hw pixel shader, prg=%d\n", retval);
3785     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, retval));
3786
3787     TRACE("Created hw pixel shader, prg=%d\n", retval);
3788     /* Create the program and check for errors */
3789     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
3790                buffer->bsize, buffer->buffer));
3791     checkGLcall("glProgramStringARB()");
3792
3793     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
3794     if (errPos != -1)
3795     {
3796         FIXME("HW PixelShader Error at position %d: %s\n\n",
3797               errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
3798         shader_arb_dump_program_source(buffer->buffer);
3799         retval = 0;
3800     }
3801     else
3802     {
3803         GLint native;
3804
3805         GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
3806         checkGLcall("glGetProgramivARB()");
3807         if (!native) WARN("Program exceeds native resource limits.\n");
3808     }
3809
3810     /* Load immediate constants */
3811     if(lconst_map) {
3812         LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
3813             const float *value = (const float *)lconst->value;
3814             GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, lconst_map[lconst->idx], value));
3815             checkGLcall("glProgramLocalParameter4fvARB");
3816         }
3817         HeapFree(GetProcessHeap(), 0, lconst_map);
3818     }
3819
3820     return retval;
3821 }
3822
3823 static int compare_sig(const struct wined3d_shader_signature_element *sig1, const struct wined3d_shader_signature_element *sig2)
3824 {
3825     unsigned int i;
3826     int ret;
3827
3828     for(i = 0; i < MAX_REG_INPUT; i++)
3829     {
3830         if(sig1[i].semantic_name == NULL || sig2[i].semantic_name == NULL)
3831         {
3832             /* Compare pointers, not contents. One string is NULL(element does not exist), the other one is not NULL */
3833             if(sig1[i].semantic_name != sig2[i].semantic_name) return sig1[i].semantic_name < sig2[i].semantic_name ? -1 : 1;
3834             continue;
3835         }
3836
3837         ret = strcmp(sig1[i].semantic_name, sig2[i].semantic_name);
3838         if(ret != 0) return ret;
3839         if(sig1[i].semantic_idx    != sig2[i].semantic_idx)    return sig1[i].semantic_idx    < sig2[i].semantic_idx    ? -1 : 1;
3840         if(sig1[i].sysval_semantic != sig2[i].sysval_semantic) return sig1[i].sysval_semantic < sig2[i].sysval_semantic ? -1 : 1;
3841         if(sig1[i].component_type  != sig2[i].component_type)  return sig1[i].sysval_semantic < sig2[i].component_type  ? -1 : 1;
3842         if(sig1[i].register_idx    != sig2[i].register_idx)    return sig1[i].register_idx    < sig2[i].register_idx    ? -1 : 1;
3843         if(sig1[i].mask            != sig2->mask)              return sig1[i].mask            < sig2[i].mask            ? -1 : 1;
3844     }
3845     return 0;
3846 }
3847
3848 static struct wined3d_shader_signature_element *clone_sig(const struct wined3d_shader_signature_element *sig)
3849 {
3850     struct wined3d_shader_signature_element *new;
3851     int i;
3852     char *name;
3853
3854     new = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*new) * MAX_REG_INPUT);
3855     for(i = 0; i < MAX_REG_INPUT; i++)
3856     {
3857         if(sig[i].semantic_name == NULL)
3858         {
3859             continue;
3860         }
3861
3862         new[i] = sig[i];
3863         /* Clone the semantic string */
3864         name = HeapAlloc(GetProcessHeap(), 0, strlen(sig[i].semantic_name) + 1);
3865         strcpy(name, sig[i].semantic_name);
3866         new[i].semantic_name = name;
3867     }
3868     return new;
3869 }
3870
3871 static DWORD find_input_signature(struct shader_arb_priv *priv, const struct wined3d_shader_signature_element *sig)
3872 {
3873     struct wine_rb_entry *entry = wine_rb_get(&priv->signature_tree, sig);
3874     struct ps_signature *found_sig;
3875
3876     if(entry != NULL)
3877     {
3878         found_sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
3879         TRACE("Found existing signature %u\n", found_sig->idx);
3880         return found_sig->idx;
3881     }
3882     found_sig = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*sig));
3883     found_sig->sig = clone_sig(sig);
3884     found_sig->idx = priv->ps_sig_number++;
3885     TRACE("New signature stored and assigned number %u\n", found_sig->idx);
3886     if(wine_rb_put(&priv->signature_tree, sig, &found_sig->entry) == -1)
3887     {
3888         ERR("Failed to insert program entry.\n");
3889     }
3890     return found_sig->idx;
3891 }
3892
3893 static void init_output_registers(IWineD3DVertexShaderImpl *shader, DWORD sig_num, struct shader_arb_ctx_priv *priv_ctx,
3894                                   struct arb_vs_compiled_shader *compiled)
3895 {
3896     unsigned int i, j;
3897     static const char * const texcoords[8] =
3898     {
3899         "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]",
3900         "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]"
3901     };
3902     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) shader->baseShader.device;
3903     IWineD3DBaseShaderClass *baseshader = &shader->baseShader;
3904     const struct wined3d_shader_signature_element *sig;
3905     const char *semantic_name;
3906     DWORD semantic_idx, reg_idx;
3907
3908     /* Write generic input varyings 0 to 7 to result.texcoord[], varying 8 to result.color.primary
3909      * and varying 9 to result.color.secondary
3910      */
3911     static const char * const decl_idx_to_string[MAX_REG_INPUT] =
3912     {
3913         "result.texcoord[0]", "result.texcoord[1]", "result.texcoord[2]", "result.texcoord[3]",
3914         "result.texcoord[4]", "result.texcoord[5]", "result.texcoord[6]", "result.texcoord[7]",
3915         "result.color.primary", "result.color.secondary"
3916     };
3917
3918     if(sig_num == ~0)
3919     {
3920         TRACE("Pixel shader uses builtin varyings\n");
3921         /* Map builtins to builtins */
3922         for(i = 0; i < 8; i++)
3923         {
3924             priv_ctx->texcrd_output[i] = texcoords[i];
3925         }
3926         priv_ctx->color_output[0] = "result.color.primary";
3927         priv_ctx->color_output[1] = "result.color.secondary";
3928         priv_ctx->fog_output = "result.fogcoord";
3929
3930         /* Map declared regs to builtins. Use "TA" to /dev/null unread output */
3931         for (i = 0; i < (sizeof(baseshader->output_signature) / sizeof(*baseshader->output_signature)); ++i)
3932         {
3933             semantic_name = baseshader->output_signature[i].semantic_name;
3934             if(semantic_name == NULL) continue;
3935
3936             if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION))
3937             {
3938                 TRACE("o%u is TMP_OUT\n", i);
3939                 if (baseshader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "TMP_OUT";
3940                 else priv_ctx->vs_output[i] = "TA";
3941             }
3942             else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE))
3943             {
3944                 TRACE("o%u is result.pointsize\n", i);
3945                 if (baseshader->output_signature[i].semantic_idx == 0) priv_ctx->vs_output[i] = "result.pointsize";
3946                 else priv_ctx->vs_output[i] = "TA";
3947             }
3948             else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR))
3949             {
3950                 TRACE("o%u is result.color.?, idx %u\n", i, baseshader->output_signature[i].semantic_idx);
3951                 if (baseshader->output_signature[i].semantic_idx == 0)
3952                     priv_ctx->vs_output[i] = "result.color.primary";
3953                 else if (baseshader->output_signature[i].semantic_idx == 1)
3954                     priv_ctx->vs_output[i] = "result.color.secondary";
3955                 else priv_ctx->vs_output[i] = "TA";
3956             }
3957             else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD))
3958             {
3959                 TRACE("o%u is %s\n", i, texcoords[baseshader->output_signature[i].semantic_idx]);
3960                 if (baseshader->output_signature[i].semantic_idx >= 8) priv_ctx->vs_output[i] = "TA";
3961                 else priv_ctx->vs_output[i] = texcoords[baseshader->output_signature[i].semantic_idx];
3962             }
3963             else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG))
3964             {
3965                 TRACE("o%u is result.fogcoord\n", i);
3966                 if (baseshader->output_signature[i].semantic_idx > 0) priv_ctx->vs_output[i] = "TA";
3967                 else priv_ctx->vs_output[i] = "result.fogcoord";
3968             }
3969             else
3970             {
3971                 priv_ctx->vs_output[i] = "TA";
3972             }
3973         }
3974         return;
3975     }
3976
3977     /* Instead of searching for the signature in the signature list, read the one from the current pixel shader.
3978      * Its maybe not the shader where the signature came from, but it is the same signature and faster to find
3979      */
3980     sig = ((IWineD3DPixelShaderImpl *)device->stateBlock->pixelShader)->baseShader.input_signature;
3981     TRACE("Pixel shader uses declared varyings\n");
3982
3983     /* Map builtin to declared. /dev/null the results by default to the TA temp reg */
3984     for(i = 0; i < 8; i++)
3985     {
3986         priv_ctx->texcrd_output[i] = "TA";
3987     }
3988     priv_ctx->color_output[0] = "TA";
3989     priv_ctx->color_output[1] = "TA";
3990     priv_ctx->fog_output = "TA";
3991
3992     for(i = 0; i < MAX_REG_INPUT; i++)
3993     {
3994         semantic_name = sig[i].semantic_name;
3995         semantic_idx = sig[i].semantic_idx;
3996         reg_idx = sig[i].register_idx;
3997         if(semantic_name == NULL) continue;
3998
3999         /* If a declared input register is not written by builtin arguments, don't write to it.
4000          * GL_NV_vertex_program makes sure the input defaults to 0.0, which is correct with D3D
4001          *
4002          * Don't care about POSITION and PSIZE here - this is a builtin vertex shader, position goes
4003          * to TMP_OUT in any case
4004          */
4005         if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_TEXCOORD))
4006         {
4007             if(semantic_idx < 8) priv_ctx->texcrd_output[semantic_idx] = decl_idx_to_string[reg_idx];
4008         }
4009         else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_COLOR))
4010         {
4011             if(semantic_idx < 2) priv_ctx->color_output[semantic_idx] = decl_idx_to_string[reg_idx];
4012         }
4013         else if(shader_match_semantic(semantic_name, WINED3DDECLUSAGE_FOG))
4014         {
4015             if(semantic_idx == 0) priv_ctx->fog_output = decl_idx_to_string[reg_idx];
4016         }
4017         else
4018         {
4019             continue;
4020         }
4021
4022         if(strcmp(decl_idx_to_string[reg_idx], "result.color.primary") == 0 ||
4023            strcmp(decl_idx_to_string[reg_idx], "result.color.secondary") == 0)
4024         {
4025             compiled->need_color_unclamp = TRUE;
4026         }
4027     }
4028
4029     /* Map declared to declared */
4030     for (i = 0; i < (sizeof(baseshader->output_signature) / sizeof(*baseshader->output_signature)); ++i)
4031     {
4032         /* Write unread output to TA to throw them away */
4033         priv_ctx->vs_output[i] = "TA";
4034         semantic_name = baseshader->output_signature[i].semantic_name;
4035         if(semantic_name == NULL)
4036         {
4037             continue;
4038         }
4039
4040         if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_POSITION)
4041                 && baseshader->output_signature[i].semantic_idx == 0)
4042         {
4043             priv_ctx->vs_output[i] = "TMP_OUT";
4044             continue;
4045         }
4046         else if (shader_match_semantic(semantic_name, WINED3DDECLUSAGE_PSIZE)
4047                 && baseshader->output_signature[i].semantic_idx == 0)
4048         {
4049             priv_ctx->vs_output[i] = "result.pointsize";
4050             continue;
4051         }
4052
4053         for(j = 0; j < MAX_REG_INPUT; j++)
4054         {
4055             if(sig[j].semantic_name == NULL)
4056             {
4057                 continue;
4058             }
4059
4060             if (strcmp(sig[j].semantic_name, semantic_name) == 0
4061                     && sig[j].semantic_idx == baseshader->output_signature[i].semantic_idx)
4062             {
4063                 priv_ctx->vs_output[i] = decl_idx_to_string[sig[j].register_idx];
4064
4065                 if(strcmp(priv_ctx->vs_output[i], "result.color.primary") == 0 ||
4066                    strcmp(priv_ctx->vs_output[i], "result.color.secondary") == 0)
4067                 {
4068                     compiled->need_color_unclamp = TRUE;
4069                 }
4070             }
4071         }
4072     }
4073 }
4074
4075 /* GL locking is done by the caller */
4076 static GLuint shader_arb_generate_vshader(IWineD3DVertexShaderImpl *This, struct wined3d_shader_buffer *buffer,
4077         const struct arb_vs_compile_args *args, struct arb_vs_compiled_shader *compiled)
4078 {
4079     const shader_reg_maps *reg_maps = &This->baseShader.reg_maps;
4080     CONST DWORD *function = This->baseShader.function;
4081     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)This->baseShader.device;
4082     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
4083     const local_constant *lconst;
4084     GLuint ret;
4085     DWORD next_local, *lconst_map = local_const_mapping((IWineD3DBaseShaderImpl *) This);
4086     struct shader_arb_ctx_priv priv_ctx;
4087     unsigned int i;
4088     GLint errPos;
4089
4090     memset(&priv_ctx, 0, sizeof(priv_ctx));
4091     priv_ctx.cur_vs_args = args;
4092     list_init(&priv_ctx.control_frames);
4093     init_output_registers(This, args->ps_signature, &priv_ctx, compiled);
4094
4095     /*  Create the hw ARB shader */
4096     shader_addline(buffer, "!!ARBvp1.0\n");
4097
4098     /* Always enable the NV extension if available. Unlike fragment shaders, there is no
4099      * mesurable performance penalty, and we can always make use of it for clipplanes.
4100      */
4101     if (gl_info->supported[NV_VERTEX_PROGRAM3])
4102     {
4103         shader_addline(buffer, "OPTION NV_vertex_program3;\n");
4104         priv_ctx.target_version = NV3;
4105         shader_addline(buffer, "ADDRESS aL;\n");
4106     }
4107     else if (gl_info->supported[NV_VERTEX_PROGRAM2_OPTION])
4108     {
4109         shader_addline(buffer, "OPTION NV_vertex_program2;\n");
4110         priv_ctx.target_version = NV2;
4111         shader_addline(buffer, "ADDRESS aL;\n");
4112     } else {
4113         priv_ctx.target_version = ARB;
4114     }
4115
4116     shader_addline(buffer, "TEMP TMP_OUT;\n");
4117     if(need_helper_const((IWineD3DBaseShaderImpl *) This, gl_info)) {
4118         shader_addline(buffer, "PARAM helper_const = { 0.0, 1.0, 2.0, %1.10f};\n", eps);
4119     }
4120     if(need_rel_addr_const((IWineD3DBaseShaderImpl *) This, gl_info)) {
4121         shader_addline(buffer, "PARAM rel_addr_const = { 0.5, %d.0, 0.0, 0.0 };\n", This->rel_offset);
4122         shader_addline(buffer, "TEMP A0_SHADOW;\n");
4123     }
4124
4125     shader_addline(buffer, "TEMP TA;\n");
4126
4127     /* Base Declarations */
4128     next_local = shader_generate_arb_declarations((IWineD3DBaseShader *)This,
4129             reg_maps, buffer, gl_info, lconst_map, &priv_ctx.vs_clipplanes, &priv_ctx);
4130
4131     for(i = 0; i < MAX_CONST_I; i++)
4132     {
4133         compiled->int_consts[i] = WINED3D_CONST_NUM_UNUSED;
4134         if(reg_maps->integer_constants & (1 << i) && priv_ctx.target_version >= NV2)
4135         {
4136             const DWORD *control_values = find_loop_control_values((IWineD3DBaseShaderImpl *) This, i);
4137
4138             if(control_values)
4139             {
4140                 shader_addline(buffer, "PARAM I%u = {%u, %u, %u, -1};\n", i,
4141                                 control_values[0], control_values[1], control_values[2]);
4142             }
4143             else
4144             {
4145                 compiled->int_consts[i] = next_local;
4146                 compiled->num_int_consts++;
4147                 shader_addline(buffer, "PARAM I%u = program.local[%u];\n", i, next_local++);
4148             }
4149         }
4150     }
4151
4152     /* We need a constant to fixup the final position */
4153     shader_addline(buffer, "PARAM posFixup = program.local[%u];\n", next_local);
4154     compiled->pos_fixup = next_local++;
4155
4156     /* Initialize output parameters. GL_ARB_vertex_program does not require special initialization values
4157      * for output parameters. D3D in theory does not do that either, but some applications depend on a
4158      * proper initialization of the secondary color, and programs using the fixed function pipeline without
4159      * a replacement shader depend on the texcoord.w being set properly.
4160      *
4161      * GL_NV_vertex_program defines that all output values are initialized to {0.0, 0.0, 0.0, 1.0}. This
4162      * assertion is in effect even when using GL_ARB_vertex_program without any NV specific additions. So
4163      * skip this if NV_vertex_program is supported. Otherwise, initialize the secondary color. For the tex-
4164      * coords, we have a flag in the opengl caps. Many cards do not require the texcoord being set, and
4165      * this can eat a number of instructions, so skip it unless this cap is set as well
4166      */
4167     if (!gl_info->supported[NV_VERTEX_PROGRAM])
4168     {
4169         const char *color_init = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_0001);
4170         shader_addline(buffer, "MOV result.color.secondary, %s;\n", color_init);
4171
4172         if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W && !device->frag_pipe->ffp_proj_control)
4173         {
4174             int i;
4175             const char *one = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ONE);
4176             for(i = 0; i < min(8, MAX_REG_TEXCRD); i++)
4177             {
4178                 if (This->baseShader.reg_maps.texcoord_mask[i] != 0 &&
4179                 This->baseShader.reg_maps.texcoord_mask[i] != WINED3DSP_WRITEMASK_ALL) {
4180                     shader_addline(buffer, "MOV result.texcoord[%u].w, %s\n", i, one);
4181                 }
4182             }
4183         }
4184     }
4185
4186     /* The shader starts with the main function */
4187     priv_ctx.in_main_func = TRUE;
4188     /* Base Shader Body */
4189     shader_generate_main((IWineD3DBaseShader *)This, buffer, reg_maps, function, &priv_ctx);
4190
4191     if(!priv_ctx.footer_written) vshader_add_footer(This, buffer, args, &priv_ctx);
4192
4193     shader_addline(buffer, "END\n");
4194
4195     /* TODO: change to resource.glObjectHandle or something like that */
4196     GL_EXTCALL(glGenProgramsARB(1, &ret));
4197
4198     TRACE("Creating a hw vertex shader, prg=%d\n", ret);
4199     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, ret));
4200
4201     TRACE("Created hw vertex shader, prg=%d\n", ret);
4202     /* Create the program and check for errors */
4203     GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
4204                buffer->bsize, buffer->buffer));
4205     checkGLcall("glProgramStringARB()");
4206
4207     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errPos);
4208     if (errPos != -1)
4209     {
4210         FIXME("HW VertexShader Error at position %d: %s\n\n",
4211               errPos, debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
4212         shader_arb_dump_program_source(buffer->buffer);
4213         ret = -1;
4214     }
4215     else
4216     {
4217         GLint native;
4218
4219         GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
4220         checkGLcall("glGetProgramivARB()");
4221         if (!native) WARN("Program exceeds native resource limits.\n");
4222
4223         /* Load immediate constants */
4224         if(lconst_map) {
4225             LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
4226                 const float *value = (const float *)lconst->value;
4227                 GL_EXTCALL(glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, lconst_map[lconst->idx], value));
4228             }
4229         }
4230     }
4231     HeapFree(GetProcessHeap(), 0, lconst_map);
4232
4233     return ret;
4234 }
4235
4236 /* GL locking is done by the caller */
4237 static struct arb_ps_compiled_shader *find_arb_pshader(IWineD3DPixelShaderImpl *shader, const struct arb_ps_compile_args *args)
4238 {
4239     UINT i;
4240     DWORD new_size;
4241     struct arb_ps_compiled_shader *new_array;
4242     struct wined3d_shader_buffer buffer;
4243     struct arb_pshader_private *shader_data;
4244     GLuint ret;
4245
4246     if (!shader->baseShader.backend_data)
4247     {
4248         IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) shader->baseShader.device;
4249         const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
4250         struct shader_arb_priv *priv = device->shader_priv;
4251
4252         shader->baseShader.backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
4253         shader_data = shader->baseShader.backend_data;
4254         shader_data->clamp_consts = shader->baseShader.reg_maps.shader_version.major == 1;
4255
4256         if(shader->baseShader.reg_maps.shader_version.major < 3) shader_data->input_signature_idx = ~0;
4257         else shader_data->input_signature_idx = find_input_signature(priv, shader->baseShader.input_signature);
4258
4259         shader_data->has_signature_idx = TRUE;
4260         TRACE("Shader got assigned input signature index %u\n", shader_data->input_signature_idx);
4261
4262         if (!device->vs_clipping)
4263             shader_data->clipplane_emulation = shader_find_free_input_register(&shader->baseShader.reg_maps,
4264                     gl_info->limits.texture_stages - 1);
4265         else
4266             shader_data->clipplane_emulation = ~0U;
4267     }
4268     shader_data = shader->baseShader.backend_data;
4269
4270     /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
4271      * so a linear search is more performant than a hashmap or a binary search
4272      * (cache coherency etc)
4273      */
4274     for(i = 0; i < shader_data->num_gl_shaders; i++) {
4275         if(memcmp(&shader_data->gl_shaders[i].args, args, sizeof(*args)) == 0) {
4276             return &shader_data->gl_shaders[i];
4277         }
4278     }
4279
4280     TRACE("No matching GL shader found, compiling a new shader\n");
4281     if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
4282         if (shader_data->num_gl_shaders)
4283         {
4284             new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
4285             new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders,
4286                                     new_size * sizeof(*shader_data->gl_shaders));
4287         } else {
4288             new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders));
4289             new_size = 1;
4290         }
4291
4292         if(!new_array) {
4293             ERR("Out of memory\n");
4294             return 0;
4295         }
4296         shader_data->gl_shaders = new_array;
4297         shader_data->shader_array_size = new_size;
4298     }
4299
4300     shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
4301
4302     pixelshader_update_samplers(&shader->baseShader.reg_maps,
4303             ((IWineD3DDeviceImpl *)shader->baseShader.device)->stateBlock->textures);
4304
4305     if (!shader_buffer_init(&buffer))
4306     {
4307         ERR("Failed to initialize shader buffer.\n");
4308         return 0;
4309     }
4310
4311     ret = shader_arb_generate_pshader(shader, &buffer, args,
4312                                       &shader_data->gl_shaders[shader_data->num_gl_shaders]);
4313     shader_buffer_free(&buffer);
4314     shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret;
4315
4316     return &shader_data->gl_shaders[shader_data->num_gl_shaders++];
4317 }
4318
4319 static inline BOOL vs_args_equal(const struct arb_vs_compile_args *stored, const struct arb_vs_compile_args *new,
4320                                  const DWORD use_map, BOOL skip_int) {
4321     if((stored->super.swizzle_map & use_map) != new->super.swizzle_map) return FALSE;
4322     if(stored->super.clip_enabled != new->super.clip_enabled) return FALSE;
4323     if(stored->super.fog_src != new->super.fog_src) return FALSE;
4324     if(stored->clip.boolclip_compare != new->clip.boolclip_compare) return FALSE;
4325     if(stored->ps_signature != new->ps_signature) return FALSE;
4326     if(stored->vertex.samplers_compare != new->vertex.samplers_compare) return FALSE;
4327     if(skip_int) return TRUE;
4328
4329     return memcmp(stored->loop_ctrl, new->loop_ctrl, sizeof(stored->loop_ctrl)) == 0;
4330 }
4331
4332 static struct arb_vs_compiled_shader *find_arb_vshader(IWineD3DVertexShaderImpl *shader, const struct arb_vs_compile_args *args)
4333 {
4334     UINT i;
4335     DWORD new_size;
4336     struct arb_vs_compiled_shader *new_array;
4337     DWORD use_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.use_map;
4338     struct wined3d_shader_buffer buffer;
4339     struct arb_vshader_private *shader_data;
4340     GLuint ret;
4341     const struct wined3d_gl_info *gl_info = &((IWineD3DDeviceImpl *)shader->baseShader.device)->adapter->gl_info;
4342
4343     if (!shader->baseShader.backend_data)
4344     {
4345         shader->baseShader.backend_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data));
4346     }
4347     shader_data = shader->baseShader.backend_data;
4348
4349     /* Usually we have very few GL shaders for each d3d shader(just 1 or maybe 2),
4350      * so a linear search is more performant than a hashmap or a binary search
4351      * (cache coherency etc)
4352      */
4353     for(i = 0; i < shader_data->num_gl_shaders; i++) {
4354         if (vs_args_equal(&shader_data->gl_shaders[i].args, args,
4355                 use_map, gl_info->supported[NV_VERTEX_PROGRAM2_OPTION]))
4356         {
4357             return &shader_data->gl_shaders[i];
4358         }
4359     }
4360
4361     TRACE("No matching GL shader found, compiling a new shader\n");
4362
4363     if(shader_data->shader_array_size == shader_data->num_gl_shaders) {
4364         if (shader_data->num_gl_shaders)
4365         {
4366             new_size = shader_data->shader_array_size + max(1, shader_data->shader_array_size / 2);
4367             new_array = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, shader_data->gl_shaders,
4368                                     new_size * sizeof(*shader_data->gl_shaders));
4369         } else {
4370             new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*shader_data->gl_shaders));
4371             new_size = 1;
4372         }
4373
4374         if(!new_array) {
4375             ERR("Out of memory\n");
4376             return 0;
4377         }
4378         shader_data->gl_shaders = new_array;
4379         shader_data->shader_array_size = new_size;
4380     }
4381
4382     shader_data->gl_shaders[shader_data->num_gl_shaders].args = *args;
4383
4384     if (!shader_buffer_init(&buffer))
4385     {
4386         ERR("Failed to initialize shader buffer.\n");
4387         return 0;
4388     }
4389
4390     ret = shader_arb_generate_vshader(shader, &buffer, args,
4391             &shader_data->gl_shaders[shader_data->num_gl_shaders]);
4392     shader_buffer_free(&buffer);
4393     shader_data->gl_shaders[shader_data->num_gl_shaders].prgId = ret;
4394
4395     return &shader_data->gl_shaders[shader_data->num_gl_shaders++];
4396 }
4397
4398 static inline void find_arb_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock,
4399         struct arb_ps_compile_args *args)
4400 {
4401     int i;
4402     WORD int_skip;
4403     const struct wined3d_gl_info *gl_info = &((IWineD3DDeviceImpl *)shader->baseShader.device)->adapter->gl_info;
4404     find_ps_compile_args(shader, stateblock, &args->super);
4405
4406     /* This forces all local boolean constants to 1 to make them stateblock independent */
4407     args->bools = shader->baseShader.reg_maps.local_bool_consts;
4408
4409     for(i = 0; i < MAX_CONST_B; i++)
4410     {
4411         if(stateblock->pixelShaderConstantB[i]) args->bools |= ( 1 << i);
4412     }
4413
4414     /* Only enable the clip plane emulation KIL if at least one clipplane is enabled. The KIL instruction
4415      * is quite expensive because it forces the driver to disable early Z discards. It is cheaper to
4416      * duplicate the shader than have a no-op KIL instruction in every shader
4417      */
4418     if((!((IWineD3DDeviceImpl *) shader->baseShader.device)->vs_clipping) && use_vs(stateblock) &&
4419        stateblock->renderState[WINED3DRS_CLIPPING] && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE])
4420     {
4421         args->clip = 1;
4422     }
4423     else
4424     {
4425         args->clip = 0;
4426     }
4427
4428     /* Skip if unused or local, or supported natively */
4429     int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts;
4430     if (int_skip == 0xffff || gl_info->supported[NV_FRAGMENT_PROGRAM_OPTION])
4431     {
4432         memset(&args->loop_ctrl, 0, sizeof(args->loop_ctrl));
4433         return;
4434     }
4435
4436     for(i = 0; i < MAX_CONST_I; i++)
4437     {
4438         if(int_skip & (1 << i))
4439         {
4440             args->loop_ctrl[i][0] = 0;
4441             args->loop_ctrl[i][1] = 0;
4442             args->loop_ctrl[i][2] = 0;
4443         }
4444         else
4445         {
4446             args->loop_ctrl[i][0] = stateblock->pixelShaderConstantI[i * 4];
4447             args->loop_ctrl[i][1] = stateblock->pixelShaderConstantI[i * 4 + 1];
4448             args->loop_ctrl[i][2] = stateblock->pixelShaderConstantI[i * 4 + 2];
4449         }
4450     }
4451 }
4452
4453 static inline void find_arb_vs_compile_args(IWineD3DVertexShaderImpl *shader, IWineD3DStateBlockImpl *stateblock,
4454         struct arb_vs_compile_args *args)
4455 {
4456     int i;
4457     WORD int_skip;
4458     IWineD3DDeviceImpl *dev = (IWineD3DDeviceImpl *)shader->baseShader.device;
4459     const struct wined3d_gl_info *gl_info = &dev->adapter->gl_info;
4460     find_vs_compile_args(shader, stateblock, &args->super);
4461
4462     args->clip.boolclip_compare = 0;
4463     if(use_ps(stateblock))
4464     {
4465         IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) stateblock->pixelShader;
4466         struct arb_pshader_private *shader_priv = ps->baseShader.backend_data;
4467         args->ps_signature = shader_priv->input_signature_idx;
4468
4469         args->clip.boolclip.clip_texcoord = shader_priv->clipplane_emulation + 1;
4470     }
4471     else
4472     {
4473         args->ps_signature = ~0;
4474         if(!dev->vs_clipping)
4475         {
4476             args->clip.boolclip.clip_texcoord = ffp_clip_emul(stateblock) ? gl_info->limits.texture_stages : 0;
4477         }
4478         /* Otherwise: Setting boolclip_compare set clip_texcoord to 0 */
4479     }
4480
4481     if(args->clip.boolclip.clip_texcoord)
4482     {
4483         if(stateblock->renderState[WINED3DRS_CLIPPING])
4484         {
4485             args->clip.boolclip.clipplane_mask = (unsigned char) stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
4486         }
4487         /* clipplane_mask was set to 0 by setting boolclip_compare to 0 */
4488     }
4489
4490     /* This forces all local boolean constants to 1 to make them stateblock independent */
4491     args->clip.boolclip.bools = shader->baseShader.reg_maps.local_bool_consts;
4492     /* TODO: Figure out if it would be better to store bool constants as bitmasks in the stateblock */
4493     for(i = 0; i < MAX_CONST_B; i++)
4494     {
4495         if(stateblock->vertexShaderConstantB[i]) args->clip.boolclip.bools |= ( 1 << i);
4496     }
4497
4498     args->vertex.samplers[0] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 0];
4499     args->vertex.samplers[1] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 1];
4500     args->vertex.samplers[2] = dev->texUnitMap[MAX_FRAGMENT_SAMPLERS + 2];
4501     args->vertex.samplers[3] = 0;
4502
4503     /* Skip if unused or local */
4504     int_skip = ~shader->baseShader.reg_maps.integer_constants | shader->baseShader.reg_maps.local_int_consts;
4505     /* This is about flow control, not clipping. */
4506     if (int_skip == 0xffff || gl_info->supported[NV_VERTEX_PROGRAM2_OPTION])
4507     {
4508         memset(&args->loop_ctrl, 0, sizeof(args->loop_ctrl));
4509         return;
4510     }
4511
4512     for(i = 0; i < MAX_CONST_I; i++)
4513     {
4514         if(int_skip & (1 << i))
4515         {
4516             args->loop_ctrl[i][0] = 0;
4517             args->loop_ctrl[i][1] = 0;
4518             args->loop_ctrl[i][2] = 0;
4519         }
4520         else
4521         {
4522             args->loop_ctrl[i][0] = stateblock->vertexShaderConstantI[i * 4];
4523             args->loop_ctrl[i][1] = stateblock->vertexShaderConstantI[i * 4 + 1];
4524             args->loop_ctrl[i][2] = stateblock->vertexShaderConstantI[i * 4 + 2];
4525         }
4526     }
4527 }
4528
4529 /* GL locking is done by the caller */
4530 static void shader_arb_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS)
4531 {
4532     IWineD3DDeviceImpl *This = context->swapchain->device;
4533     struct shader_arb_priv *priv = This->shader_priv;
4534     const struct wined3d_gl_info *gl_info = context->gl_info;
4535     int i;
4536
4537     /* Deal with pixel shaders first so the vertex shader arg function has the input signature ready */
4538     if (usePS) {
4539         struct arb_ps_compile_args compile_args;
4540         struct arb_ps_compiled_shader *compiled;
4541         IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This->stateBlock->pixelShader;
4542
4543         TRACE("Using pixel shader %p\n", This->stateBlock->pixelShader);
4544         find_arb_ps_compile_args(ps, This->stateBlock, &compile_args);
4545         compiled = find_arb_pshader(ps, &compile_args);
4546         priv->current_fprogram_id = compiled->prgId;
4547         priv->compiled_fprog = compiled;
4548
4549         /* Bind the fragment program */
4550         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
4551         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id);");
4552
4553         if(!priv->use_arbfp_fixed_func) {
4554             /* Enable OpenGL fragment programs */
4555             glEnable(GL_FRAGMENT_PROGRAM_ARB);
4556             checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB);");
4557         }
4558         TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
4559
4560         /* Pixel Shader 1.x constants are clamped to [-1;1], Pixel Shader 2.0 constants are not. If switching between
4561          * a 1.x and newer shader, reload the first 8 constants
4562          */
4563         if(priv->last_ps_const_clamped != ((struct arb_pshader_private *)ps->baseShader.backend_data)->clamp_consts)
4564         {
4565             priv->last_ps_const_clamped = ((struct arb_pshader_private *)ps->baseShader.backend_data)->clamp_consts;
4566             This->highest_dirty_ps_const = max(This->highest_dirty_ps_const, 8);
4567             for(i = 0; i < 8; i++)
4568             {
4569                 context->pshader_const_dirty[i] = 1;
4570             }
4571             /* Also takes care of loading local constants */
4572             shader_arb_load_constants(context, TRUE, FALSE);
4573         }
4574         else
4575         {
4576             shader_arb_ps_local_constants(This);
4577         }
4578
4579         /* Force constant reloading for the NP2 fixup (see comment in shader_glsl_select for more info) */
4580         if (compiled->np2fixup_info.super.active)
4581             shader_arb_load_np2fixup_constants((IWineD3DDevice *)This, usePS, useVS);
4582     }
4583     else if (gl_info->supported[ARB_FRAGMENT_PROGRAM] && !priv->use_arbfp_fixed_func)
4584     {
4585         /* Disable only if we're not using arbfp fixed function fragment processing. If this is used,
4586         * keep GL_FRAGMENT_PROGRAM_ARB enabled, and the fixed function pipeline will bind the fixed function
4587         * replacement shader
4588         */
4589         glDisable(GL_FRAGMENT_PROGRAM_ARB);
4590         checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
4591         priv->current_fprogram_id = 0;
4592     }
4593
4594     if (useVS) {
4595         struct arb_vs_compile_args compile_args;
4596         struct arb_vs_compiled_shader *compiled;
4597         IWineD3DVertexShaderImpl *vs = (IWineD3DVertexShaderImpl *) This->stateBlock->vertexShader;
4598
4599         TRACE("Using vertex shader %p\n", This->stateBlock->vertexShader);
4600         find_arb_vs_compile_args(vs, This->stateBlock, &compile_args);
4601         compiled = find_arb_vshader(vs, &compile_args);
4602         priv->current_vprogram_id = compiled->prgId;
4603         priv->compiled_vprog = compiled;
4604
4605         /* Bind the vertex program */
4606         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
4607         checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id);");
4608
4609         /* Enable OpenGL vertex programs */
4610         glEnable(GL_VERTEX_PROGRAM_ARB);
4611         checkGLcall("glEnable(GL_VERTEX_PROGRAM_ARB);");
4612         TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
4613         shader_arb_vs_local_constants(This);
4614
4615         if(priv->last_vs_color_unclamp != compiled->need_color_unclamp) {
4616             priv->last_vs_color_unclamp = compiled->need_color_unclamp;
4617
4618             if (gl_info->supported[ARB_COLOR_BUFFER_FLOAT])
4619             {
4620                 GL_EXTCALL(glClampColorARB(GL_CLAMP_VERTEX_COLOR_ARB, !compiled->need_color_unclamp));
4621                 checkGLcall("glClampColorARB");
4622             } else {
4623                 FIXME("vertex color clamp needs to be changed, but extension not supported.\n");
4624             }
4625         }
4626     }
4627     else if (gl_info->supported[ARB_VERTEX_PROGRAM])
4628     {
4629         priv->current_vprogram_id = 0;
4630         glDisable(GL_VERTEX_PROGRAM_ARB);
4631         checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
4632     }
4633 }
4634
4635 /* GL locking is done by the caller */
4636 static void shader_arb_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size)
4637 {
4638     const float mask[] = {0.0f, 0.0f, (float)ds_mask_size->cx, (float)ds_mask_size->cy};
4639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4640     BOOL masked = ds_mask_size->cx && ds_mask_size->cy;
4641     struct shader_arb_priv *priv = This->shader_priv;
4642     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4643     GLuint *blt_fprogram;
4644
4645     if (!priv->depth_blt_vprogram_id) priv->depth_blt_vprogram_id = create_arb_blt_vertex_program(gl_info);
4646     GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->depth_blt_vprogram_id));
4647     glEnable(GL_VERTEX_PROGRAM_ARB);
4648
4649     blt_fprogram = masked ? &priv->depth_blt_fprogram_id_masked[tex_type] : &priv->depth_blt_fprogram_id_full[tex_type];
4650     if (!*blt_fprogram) *blt_fprogram = create_arb_blt_fragment_program(gl_info, tex_type, masked);
4651     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, *blt_fprogram));
4652     if (masked) GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, mask));
4653     glEnable(GL_FRAGMENT_PROGRAM_ARB);
4654 }
4655
4656 /* GL locking is done by the caller */
4657 static void shader_arb_deselect_depth_blt(IWineD3DDevice *iface) {
4658     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4659     struct shader_arb_priv *priv = This->shader_priv;
4660     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4661
4662     if (priv->current_vprogram_id) {
4663         GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, priv->current_vprogram_id));
4664         checkGLcall("glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vertexShader->prgId);");
4665
4666         TRACE("(%p) : Bound vertex program %u and enabled GL_VERTEX_PROGRAM_ARB\n", This, priv->current_vprogram_id);
4667     } else {
4668         glDisable(GL_VERTEX_PROGRAM_ARB);
4669         checkGLcall("glDisable(GL_VERTEX_PROGRAM_ARB)");
4670     }
4671
4672     if (priv->current_fprogram_id) {
4673         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, priv->current_fprogram_id));
4674         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, pixelShader->prgId);");
4675
4676         TRACE("(%p) : Bound fragment program %u and enabled GL_FRAGMENT_PROGRAM_ARB\n", This, priv->current_fprogram_id);
4677     } else if(!priv->use_arbfp_fixed_func) {
4678         glDisable(GL_FRAGMENT_PROGRAM_ARB);
4679         checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
4680     }
4681 }
4682
4683 static void shader_arb_destroy(IWineD3DBaseShader *iface) {
4684     IWineD3DBaseShaderImpl *baseShader = (IWineD3DBaseShaderImpl *) iface;
4685     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)baseShader->baseShader.device;
4686     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
4687
4688     if (shader_is_pshader_version(baseShader->baseShader.reg_maps.shader_version.type))
4689     {
4690         struct arb_pshader_private *shader_data = baseShader->baseShader.backend_data;
4691         UINT i;
4692
4693         if(!shader_data) return; /* This can happen if a shader was never compiled */
4694
4695         if (shader_data->num_gl_shaders)
4696         {
4697             struct wined3d_context *context = context_acquire(device, NULL);
4698
4699             ENTER_GL();
4700             for (i = 0; i < shader_data->num_gl_shaders; ++i)
4701             {
4702                 GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
4703                 checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))");
4704             }
4705             LEAVE_GL();
4706
4707             context_release(context);
4708         }
4709
4710         HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
4711         HeapFree(GetProcessHeap(), 0, shader_data);
4712         baseShader->baseShader.backend_data = NULL;
4713     }
4714     else
4715     {
4716         struct arb_vshader_private *shader_data = baseShader->baseShader.backend_data;
4717         UINT i;
4718
4719         if(!shader_data) return; /* This can happen if a shader was never compiled */
4720
4721         if (shader_data->num_gl_shaders)
4722         {
4723             struct wined3d_context *context = context_acquire(device, NULL);
4724
4725             ENTER_GL();
4726             for (i = 0; i < shader_data->num_gl_shaders; ++i)
4727             {
4728                 GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId));
4729                 checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader_data->gl_shaders[i].prgId))");
4730             }
4731             LEAVE_GL();
4732
4733             context_release(context);
4734         }
4735
4736         HeapFree(GetProcessHeap(), 0, shader_data->gl_shaders);
4737         HeapFree(GetProcessHeap(), 0, shader_data);
4738         baseShader->baseShader.backend_data = NULL;
4739     }
4740 }
4741
4742 static int sig_tree_compare(const void *key, const struct wine_rb_entry *entry)
4743 {
4744     struct ps_signature *e = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
4745     return compare_sig(key, e->sig);
4746 }
4747
4748 static const struct wine_rb_functions sig_tree_functions =
4749 {
4750     wined3d_rb_alloc,
4751     wined3d_rb_realloc,
4752     wined3d_rb_free,
4753     sig_tree_compare
4754 };
4755
4756 static HRESULT shader_arb_alloc(IWineD3DDevice *iface) {
4757     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4758     struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv));
4759     if(wine_rb_init(&priv->signature_tree, &sig_tree_functions) == -1)
4760     {
4761         ERR("RB tree init failed\n");
4762         HeapFree(GetProcessHeap(), 0, priv);
4763         return E_OUTOFMEMORY;
4764     }
4765     This->shader_priv = priv;
4766     return WINED3D_OK;
4767 }
4768
4769 static void release_signature(struct wine_rb_entry *entry, void *context)
4770 {
4771     struct ps_signature *sig = WINE_RB_ENTRY_VALUE(entry, struct ps_signature, entry);
4772     int i;
4773     for(i = 0; i < MAX_REG_INPUT; i++)
4774     {
4775         HeapFree(GetProcessHeap(), 0, (char *) sig->sig[i].semantic_name);
4776     }
4777     HeapFree(GetProcessHeap(), 0, sig->sig);
4778     HeapFree(GetProcessHeap(), 0, sig);
4779 }
4780
4781 /* Context activation is done by the caller. */
4782 static void shader_arb_free(IWineD3DDevice *iface) {
4783     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4784     const struct wined3d_gl_info *gl_info = &This->adapter->gl_info;
4785     struct shader_arb_priv *priv = This->shader_priv;
4786     int i;
4787
4788     ENTER_GL();
4789     if(priv->depth_blt_vprogram_id) {
4790         GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_vprogram_id));
4791     }
4792     for (i = 0; i < tex_type_count; ++i)
4793     {
4794         if (priv->depth_blt_fprogram_id_full[i])
4795         {
4796             GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_full[i]));
4797         }
4798         if (priv->depth_blt_fprogram_id_masked[i])
4799         {
4800             GL_EXTCALL(glDeleteProgramsARB(1, &priv->depth_blt_fprogram_id_masked[i]));
4801         }
4802     }
4803     LEAVE_GL();
4804
4805     wine_rb_destroy(&priv->signature_tree, release_signature, NULL);
4806     HeapFree(GetProcessHeap(), 0, This->shader_priv);
4807 }
4808
4809 static BOOL shader_arb_dirty_const(IWineD3DDevice *iface) {
4810     return TRUE;
4811 }
4812
4813 static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *pCaps)
4814 {
4815     if (gl_info->supported[ARB_VERTEX_PROGRAM])
4816     {
4817         DWORD vs_consts;
4818
4819         /* 96 is the minimum allowed value of MAX_PROGRAM_ENV_PARAMETERS_ARB
4820          * for vertex programs. If the native limit is less than that it's
4821          * not very useful, and e.g. Mesa swrast returns 0, probably to
4822          * indicate it's a software implementation. */
4823         if (gl_info->limits.arb_vs_native_constants < 96)
4824             vs_consts = gl_info->limits.arb_vs_float_constants;
4825         else
4826             vs_consts = min(gl_info->limits.arb_vs_float_constants, gl_info->limits.arb_vs_native_constants);
4827
4828         if (gl_info->supported[NV_VERTEX_PROGRAM3])
4829         {
4830             pCaps->VertexShaderVersion = WINED3DVS_VERSION(3,0);
4831             TRACE_(d3d_caps)("Hardware vertex shader version 3.0 enabled (NV_VERTEX_PROGRAM3)\n");
4832         }
4833         else if (vs_consts >= 256)
4834         {
4835             /* Shader Model 2.0 requires at least 256 vertex shader constants */
4836             pCaps->VertexShaderVersion = WINED3DVS_VERSION(2,0);
4837             TRACE_(d3d_caps)("Hardware vertex shader version 2.0 enabled (ARB_PROGRAM)\n");
4838         }
4839         else
4840         {
4841             pCaps->VertexShaderVersion = WINED3DVS_VERSION(1,1);
4842             TRACE_(d3d_caps)("Hardware vertex shader version 1.1 enabled (ARB_PROGRAM)\n");
4843         }
4844         pCaps->MaxVertexShaderConst = vs_consts;
4845     }
4846     else
4847     {
4848         pCaps->VertexShaderVersion = 0;
4849         pCaps->MaxVertexShaderConst = 0;
4850     }
4851
4852     if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
4853     {
4854         DWORD ps_consts;
4855
4856         /* Similar as above for vertex programs, but the minimum for fragment
4857          * programs is 24. */
4858         if (gl_info->limits.arb_ps_native_constants < 24)
4859             ps_consts = gl_info->limits.arb_ps_float_constants;
4860         else
4861             ps_consts = min(gl_info->limits.arb_ps_float_constants, gl_info->limits.arb_ps_native_constants);
4862
4863         if (gl_info->supported[NV_FRAGMENT_PROGRAM2])
4864         {
4865             pCaps->PixelShaderVersion    = WINED3DPS_VERSION(3,0);
4866             TRACE_(d3d_caps)("Hardware pixel shader version 3.0 enabled (NV_FRAGMENT_PROGRAM2)\n");
4867         }
4868         else if (ps_consts >= 32)
4869         {
4870             /* Shader Model 2.0 requires at least 32 pixel shader constants */
4871             pCaps->PixelShaderVersion    = WINED3DPS_VERSION(2,0);
4872             TRACE_(d3d_caps)("Hardware pixel shader version 2.0 enabled (ARB_PROGRAM)\n");
4873         }
4874         else
4875         {
4876             pCaps->PixelShaderVersion    = WINED3DPS_VERSION(1,4);
4877             TRACE_(d3d_caps)("Hardware pixel shader version 1.4 enabled (ARB_PROGRAM)\n");
4878         }
4879         pCaps->PixelShader1xMaxValue = 8.0f;
4880         pCaps->MaxPixelShaderConst = ps_consts;
4881     }
4882     else
4883     {
4884         pCaps->PixelShaderVersion = 0;
4885         pCaps->PixelShader1xMaxValue = 0.0f;
4886         pCaps->MaxPixelShaderConst = 0;
4887     }
4888
4889     pCaps->VSClipping = use_nv_clip(gl_info);
4890 }
4891
4892 static BOOL shader_arb_color_fixup_supported(struct color_fixup_desc fixup)
4893 {
4894     if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
4895     {
4896         TRACE("Checking support for color_fixup:\n");
4897         dump_color_fixup_desc(fixup);
4898     }
4899
4900     /* We support everything except complex conversions. */
4901     if (!is_complex_fixup(fixup))
4902     {
4903         TRACE("[OK]\n");
4904         return TRUE;
4905     }
4906
4907     TRACE("[FAILED]\n");
4908     return FALSE;
4909 }
4910
4911 static void shader_arb_add_instruction_modifiers(const struct wined3d_shader_instruction *ins) {
4912     DWORD shift;
4913     char write_mask[20], regstr[50];
4914     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
4915     BOOL is_color = FALSE;
4916     const struct wined3d_shader_dst_param *dst;
4917
4918     if (!ins->dst_count) return;
4919
4920     dst = &ins->dst[0];
4921     shift = dst->shift;
4922     if(shift == 0) return; /* Saturate alone is handled by the instructions */
4923
4924     shader_arb_get_write_mask(ins, dst, write_mask);
4925     shader_arb_get_register_name(ins, &dst->reg, regstr, &is_color);
4926
4927     /* Generate a line that does the output modifier computation
4928      * FIXME: _SAT vs shift? _SAT alone is already handled in the instructions, if this
4929      * maps problems in e.g. _d4_sat modify shader_arb_get_modifier
4930      */
4931     shader_addline(buffer, "MUL%s %s%s, %s, %s;\n", shader_arb_get_modifier(ins),
4932                    regstr, write_mask, regstr, shift_tab[shift]);
4933 }
4934
4935 static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABLE_SIZE] =
4936 {
4937     /* WINED3DSIH_ABS           */ shader_hw_map2gl,
4938     /* WINED3DSIH_ADD           */ shader_hw_map2gl,
4939     /* WINED3DSIH_BEM           */ pshader_hw_bem,
4940     /* WINED3DSIH_BREAK         */ shader_hw_break,
4941     /* WINED3DSIH_BREAKC        */ shader_hw_breakc,
4942     /* WINED3DSIH_BREAKP        */ NULL,
4943     /* WINED3DSIH_CALL          */ shader_hw_call,
4944     /* WINED3DSIH_CALLNZ        */ NULL,
4945     /* WINED3DSIH_CMP           */ pshader_hw_cmp,
4946     /* WINED3DSIH_CND           */ pshader_hw_cnd,
4947     /* WINED3DSIH_CRS           */ shader_hw_map2gl,
4948     /* WINED3DSIH_CUT           */ NULL,
4949     /* WINED3DSIH_DCL           */ NULL,
4950     /* WINED3DSIH_DEF           */ NULL,
4951     /* WINED3DSIH_DEFB          */ NULL,
4952     /* WINED3DSIH_DEFI          */ NULL,
4953     /* WINED3DSIH_DP2ADD        */ pshader_hw_dp2add,
4954     /* WINED3DSIH_DP3           */ shader_hw_map2gl,
4955     /* WINED3DSIH_DP4           */ shader_hw_map2gl,
4956     /* WINED3DSIH_DST           */ shader_hw_map2gl,
4957     /* WINED3DSIH_DSX           */ shader_hw_map2gl,
4958     /* WINED3DSIH_DSY           */ shader_hw_dsy,
4959     /* WINED3DSIH_ELSE          */ shader_hw_else,
4960     /* WINED3DSIH_EMIT          */ NULL,
4961     /* WINED3DSIH_ENDIF         */ shader_hw_endif,
4962     /* WINED3DSIH_ENDLOOP       */ shader_hw_endloop,
4963     /* WINED3DSIH_ENDREP        */ shader_hw_endrep,
4964     /* WINED3DSIH_EXP           */ shader_hw_scalar_op,
4965     /* WINED3DSIH_EXPP          */ shader_hw_scalar_op,
4966     /* WINED3DSIH_FRC           */ shader_hw_map2gl,
4967     /* WINED3DSIH_IADD          */ NULL,
4968     /* WINED3DSIH_IF            */ NULL /* Hardcoded into the shader */,
4969     /* WINED3DSIH_IFC           */ shader_hw_ifc,
4970     /* WINED3DSIH_IGE           */ NULL,
4971     /* WINED3DSIH_LABEL         */ shader_hw_label,
4972     /* WINED3DSIH_LIT           */ shader_hw_map2gl,
4973     /* WINED3DSIH_LOG           */ shader_hw_log_pow,
4974     /* WINED3DSIH_LOGP          */ shader_hw_log_pow,
4975     /* WINED3DSIH_LOOP          */ shader_hw_loop,
4976     /* WINED3DSIH_LRP           */ shader_hw_lrp,
4977     /* WINED3DSIH_LT            */ NULL,
4978     /* WINED3DSIH_M3x2          */ shader_hw_mnxn,
4979     /* WINED3DSIH_M3x3          */ shader_hw_mnxn,
4980     /* WINED3DSIH_M3x4          */ shader_hw_mnxn,
4981     /* WINED3DSIH_M4x3          */ shader_hw_mnxn,
4982     /* WINED3DSIH_M4x4          */ shader_hw_mnxn,
4983     /* WINED3DSIH_MAD           */ shader_hw_map2gl,
4984     /* WINED3DSIH_MAX           */ shader_hw_map2gl,
4985     /* WINED3DSIH_MIN           */ shader_hw_map2gl,
4986     /* WINED3DSIH_MOV           */ shader_hw_mov,
4987     /* WINED3DSIH_MOVA          */ shader_hw_mov,
4988     /* WINED3DSIH_MUL           */ shader_hw_map2gl,
4989     /* WINED3DSIH_NOP           */ shader_hw_nop,
4990     /* WINED3DSIH_NRM           */ shader_hw_nrm,
4991     /* WINED3DSIH_PHASE         */ NULL,
4992     /* WINED3DSIH_POW           */ shader_hw_log_pow,
4993     /* WINED3DSIH_RCP           */ shader_hw_rcp,
4994     /* WINED3DSIH_REP           */ shader_hw_rep,
4995     /* WINED3DSIH_RET           */ shader_hw_ret,
4996     /* WINED3DSIH_RSQ           */ shader_hw_scalar_op,
4997     /* WINED3DSIH_SETP          */ NULL,
4998     /* WINED3DSIH_SGE           */ shader_hw_map2gl,
4999     /* WINED3DSIH_SGN           */ shader_hw_sgn,
5000     /* WINED3DSIH_SINCOS        */ shader_hw_sincos,
5001     /* WINED3DSIH_SLT           */ shader_hw_map2gl,
5002     /* WINED3DSIH_SUB           */ shader_hw_map2gl,
5003     /* WINED3DSIH_TEX           */ pshader_hw_tex,
5004     /* WINED3DSIH_TEXBEM        */ pshader_hw_texbem,
5005     /* WINED3DSIH_TEXBEML       */ pshader_hw_texbem,
5006     /* WINED3DSIH_TEXCOORD      */ pshader_hw_texcoord,
5007     /* WINED3DSIH_TEXDEPTH      */ pshader_hw_texdepth,
5008     /* WINED3DSIH_TEXDP3        */ pshader_hw_texdp3,
5009     /* WINED3DSIH_TEXDP3TEX     */ pshader_hw_texdp3tex,
5010     /* WINED3DSIH_TEXKILL       */ pshader_hw_texkill,
5011     /* WINED3DSIH_TEXLDD        */ shader_hw_texldd,
5012     /* WINED3DSIH_TEXLDL        */ shader_hw_texldl,
5013     /* WINED3DSIH_TEXM3x2DEPTH  */ pshader_hw_texm3x2depth,
5014     /* WINED3DSIH_TEXM3x2PAD    */ pshader_hw_texm3x2pad,
5015     /* WINED3DSIH_TEXM3x2TEX    */ pshader_hw_texm3x2tex,
5016     /* WINED3DSIH_TEXM3x3       */ pshader_hw_texm3x3,
5017     /* WINED3DSIH_TEXM3x3DIFF   */ NULL,
5018     /* WINED3DSIH_TEXM3x3PAD    */ pshader_hw_texm3x3pad,
5019     /* WINED3DSIH_TEXM3x3SPEC   */ pshader_hw_texm3x3spec,
5020     /* WINED3DSIH_TEXM3x3TEX    */ pshader_hw_texm3x3tex,
5021     /* WINED3DSIH_TEXM3x3VSPEC  */ pshader_hw_texm3x3vspec,
5022     /* WINED3DSIH_TEXREG2AR     */ pshader_hw_texreg2ar,
5023     /* WINED3DSIH_TEXREG2GB     */ pshader_hw_texreg2gb,
5024     /* WINED3DSIH_TEXREG2RGB    */ pshader_hw_texreg2rgb,
5025 };
5026
5027 static inline BOOL get_bool_const(const struct wined3d_shader_instruction *ins, IWineD3DBaseShaderImpl *This, DWORD idx)
5028 {
5029     BOOL vshader = shader_is_vshader_version(This->baseShader.reg_maps.shader_version.type);
5030     WORD bools = 0;
5031     WORD flag = (1 << idx);
5032     const local_constant *constant;
5033     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
5034
5035     if(This->baseShader.reg_maps.local_bool_consts & flag)
5036     {
5037         /* What good is a if(bool) with a hardcoded local constant? I don't know, but handle it */
5038         LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsB, local_constant, entry)
5039         {
5040             if (constant->idx == idx)
5041             {
5042                 return constant->value[0];
5043             }
5044         }
5045         ERR("Local constant not found\n");
5046         return FALSE;
5047     }
5048     else
5049     {
5050         if(vshader) bools = priv->cur_vs_args->clip.boolclip.bools;
5051         else bools = priv->cur_ps_args->bools;
5052         return bools & flag;
5053     }
5054 }
5055
5056 static void get_loop_control_const(const struct wined3d_shader_instruction *ins,
5057         IWineD3DBaseShaderImpl *This, UINT idx, struct wined3d_shader_loop_control *loop_control)
5058 {
5059     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
5060
5061     /* Integer constants can either be a local constant, or they can be stored in the shader
5062      * type specific compile args. */
5063     if (This->baseShader.reg_maps.local_int_consts & (1 << idx))
5064     {
5065         const local_constant *constant;
5066
5067         LIST_FOR_EACH_ENTRY(constant, &This->baseShader.constantsI, local_constant, entry)
5068         {
5069             if (constant->idx == idx)
5070             {
5071                 loop_control->count = constant->value[0];
5072                 loop_control->start = constant->value[1];
5073                 /* Step is signed. */
5074                 loop_control->step = (int)constant->value[2];
5075                 return;
5076             }
5077         }
5078         /* If this happens the flag was set incorrectly */
5079         ERR("Local constant not found\n");
5080         loop_control->count = 0;
5081         loop_control->start = 0;
5082         loop_control->step = 0;
5083         return;
5084     }
5085
5086     switch (This->baseShader.reg_maps.shader_version.type)
5087     {
5088         case WINED3D_SHADER_TYPE_VERTEX:
5089             /* Count and aL start value are unsigned */
5090             loop_control->count = priv->cur_vs_args->loop_ctrl[idx][0];
5091             loop_control->start = priv->cur_vs_args->loop_ctrl[idx][1];
5092             /* Step is signed. */
5093             loop_control->step = ((char)priv->cur_vs_args->loop_ctrl[idx][2]);
5094             break;
5095
5096         case WINED3D_SHADER_TYPE_PIXEL:
5097             loop_control->count = priv->cur_ps_args->loop_ctrl[idx][0];
5098             loop_control->start = priv->cur_ps_args->loop_ctrl[idx][1];
5099             loop_control->step = ((char)priv->cur_ps_args->loop_ctrl[idx][2]);
5100             break;
5101
5102         default:
5103             FIXME("Unhandled shader type %#x.\n", This->baseShader.reg_maps.shader_version.type);
5104             break;
5105     }
5106 }
5107
5108 static void record_instruction(struct list *list, const struct wined3d_shader_instruction *ins)
5109 {
5110     unsigned int i;
5111     struct wined3d_shader_dst_param *dst_param = NULL;
5112     struct wined3d_shader_src_param *src_param = NULL, *rel_addr = NULL;
5113     struct recorded_instruction *rec = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*rec));
5114     if(!rec)
5115     {
5116         ERR("Out of memory\n");
5117         return;
5118     }
5119
5120     rec->ins = *ins;
5121     dst_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param));
5122     if(!dst_param) goto free;
5123     *dst_param = *ins->dst;
5124     if(ins->dst->reg.rel_addr)
5125     {
5126         rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*dst_param->reg.rel_addr));
5127         if(!rel_addr) goto free;
5128         *rel_addr = *ins->dst->reg.rel_addr;
5129         dst_param->reg.rel_addr = rel_addr;
5130     }
5131     rec->ins.dst = dst_param;
5132
5133     src_param = HeapAlloc(GetProcessHeap(), 0, sizeof(*src_param) * ins->src_count);
5134     if(!src_param) goto free;
5135     for(i = 0; i < ins->src_count; i++)
5136     {
5137         src_param[i] = ins->src[i];
5138         if(ins->src[i].reg.rel_addr)
5139         {
5140             rel_addr = HeapAlloc(GetProcessHeap(), 0, sizeof(*rel_addr));
5141             if(!rel_addr) goto free;
5142             *rel_addr = *ins->src[i].reg.rel_addr;
5143             src_param[i].reg.rel_addr = rel_addr;
5144         }
5145     }
5146     rec->ins.src = src_param;
5147     list_add_tail(list, &rec->entry);
5148     return;
5149
5150 free:
5151     ERR("Out of memory\n");
5152     if(dst_param)
5153     {
5154         HeapFree(GetProcessHeap(), 0, (void *) dst_param->reg.rel_addr);
5155         HeapFree(GetProcessHeap(), 0, dst_param);
5156     }
5157     if(src_param)
5158     {
5159         for(i = 0; i < ins->src_count; i++)
5160         {
5161             HeapFree(GetProcessHeap(), 0, (void *) src_param[i].reg.rel_addr);
5162         }
5163         HeapFree(GetProcessHeap(), 0, src_param);
5164     }
5165     HeapFree(GetProcessHeap(), 0, rec);
5166 }
5167
5168 static void free_recorded_instruction(struct list *list)
5169 {
5170     struct recorded_instruction *rec_ins, *entry2;
5171     unsigned int i;
5172
5173     LIST_FOR_EACH_ENTRY_SAFE(rec_ins, entry2, list, struct recorded_instruction, entry)
5174     {
5175         list_remove(&rec_ins->entry);
5176         if(rec_ins->ins.dst)
5177         {
5178             HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.dst->reg.rel_addr);
5179             HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.dst);
5180         }
5181         if(rec_ins->ins.src)
5182         {
5183             for(i = 0; i < rec_ins->ins.src_count; i++)
5184             {
5185                 HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.src[i].reg.rel_addr);
5186             }
5187             HeapFree(GetProcessHeap(), 0, (void *) rec_ins->ins.src);
5188         }
5189         HeapFree(GetProcessHeap(), 0, rec_ins);
5190     }
5191 }
5192
5193 static void shader_arb_handle_instruction(const struct wined3d_shader_instruction *ins) {
5194     SHADER_HANDLER hw_fct;
5195     struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
5196     IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *)ins->ctx->shader;
5197     struct control_frame *control_frame;
5198     struct wined3d_shader_buffer *buffer = ins->ctx->buffer;
5199     BOOL bool_const;
5200
5201     if(ins->handler_idx == WINED3DSIH_LOOP || ins->handler_idx == WINED3DSIH_REP)
5202     {
5203         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
5204         list_add_head(&priv->control_frames, &control_frame->entry);
5205
5206         if(ins->handler_idx == WINED3DSIH_LOOP) control_frame->type = LOOP;
5207         if(ins->handler_idx == WINED3DSIH_REP) control_frame->type = REP;
5208
5209         if(priv->target_version >= NV2)
5210         {
5211             control_frame->no.loop = priv->num_loops++;
5212             priv->loop_depth++;
5213         }
5214         else
5215         {
5216             /* Don't bother recording when we're in a not used if branch */
5217             if(priv->muted)
5218             {
5219                 return;
5220             }
5221
5222             if(!priv->recording)
5223             {
5224                 list_init(&priv->record);
5225                 priv->recording = TRUE;
5226                 control_frame->outer_loop = TRUE;
5227                 get_loop_control_const(ins, This, ins->src[0].reg.idx, &control_frame->loop_control);
5228                 return; /* Instruction is handled */
5229             }
5230             /* Record this loop in the outer loop's recording */
5231         }
5232     }
5233     else if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP)
5234     {
5235         if(priv->target_version >= NV2)
5236         {
5237             /* Nothing to do. The control frame is popped after the HW instr handler */
5238         }
5239         else
5240         {
5241             struct list *e = list_head(&priv->control_frames);
5242             control_frame = LIST_ENTRY(e, struct control_frame, entry);
5243             list_remove(&control_frame->entry);
5244
5245             if(control_frame->outer_loop)
5246             {
5247                 unsigned int iteration;
5248                 int aL = 0;
5249                 struct list copy;
5250
5251                 /* Turn off recording before playback */
5252                 priv->recording = FALSE;
5253
5254                 /* Move the recorded instructions to a separate list and get them out of the private data
5255                  * structure. If there are nested loops, the shader_arb_handle_instruction below will
5256                  * be recorded again, thus priv->record might be overwritten
5257                  */
5258                 list_init(&copy);
5259                 list_move_tail(&copy, &priv->record);
5260                 list_init(&priv->record);
5261
5262                 if(ins->handler_idx == WINED3DSIH_ENDLOOP)
5263                 {
5264                     shader_addline(buffer, "#unrolling loop: %u iterations, aL=%u, inc %d\n",
5265                                    control_frame->loop_control.count, control_frame->loop_control.start,
5266                                    control_frame->loop_control.step);
5267                     aL = control_frame->loop_control.start;
5268                 }
5269                 else
5270                 {
5271                     shader_addline(buffer, "#unrolling rep: %u iterations\n", control_frame->loop_control.count);
5272                 }
5273
5274                 for (iteration = 0; iteration < control_frame->loop_control.count; ++iteration)
5275                 {
5276                     struct recorded_instruction *rec_ins;
5277                     if(ins->handler_idx == WINED3DSIH_ENDLOOP)
5278                     {
5279                         priv->aL = aL;
5280                         shader_addline(buffer, "#Iteration %u, aL=%d\n", iteration, aL);
5281                     }
5282                     else
5283                     {
5284                         shader_addline(buffer, "#Iteration %u\n", iteration);
5285                     }
5286
5287                     LIST_FOR_EACH_ENTRY(rec_ins, &copy, struct recorded_instruction, entry)
5288                     {
5289                         shader_arb_handle_instruction(&rec_ins->ins);
5290                     }
5291
5292                     if(ins->handler_idx == WINED3DSIH_ENDLOOP)
5293                     {
5294                         aL += control_frame->loop_control.step;
5295                     }
5296                 }
5297                 shader_addline(buffer, "#end loop/rep\n");
5298
5299                 free_recorded_instruction(&copy);
5300                 HeapFree(GetProcessHeap(), 0, control_frame);
5301                 return; /* Instruction is handled */
5302             }
5303             else
5304             {
5305                 /* This is a nested loop. Proceed to the normal recording function */
5306                 HeapFree(GetProcessHeap(), 0, control_frame);
5307             }
5308         }
5309     }
5310
5311     if(priv->recording)
5312     {
5313         record_instruction(&priv->record, ins);
5314         return;
5315     }
5316
5317     /* boolean if */
5318     if(ins->handler_idx == WINED3DSIH_IF)
5319     {
5320         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
5321         list_add_head(&priv->control_frames, &control_frame->entry);
5322         control_frame->type = IF;
5323
5324         bool_const = get_bool_const(ins, This, ins->src[0].reg.idx);
5325         if(ins->src[0].modifiers == WINED3DSPSM_NOT) bool_const = !bool_const;
5326         if(!priv->muted && bool_const == FALSE)
5327         {
5328             shader_addline(buffer, "#if(FALSE){\n");
5329             priv->muted = TRUE;
5330             control_frame->muting = TRUE;
5331         }
5332         else shader_addline(buffer, "#if(TRUE) {\n");
5333
5334         return; /* Instruction is handled */
5335     }
5336     else if(ins->handler_idx == WINED3DSIH_IFC)
5337     {
5338         /* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */
5339         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
5340         control_frame->type = IFC;
5341         control_frame->no.ifc = priv->num_ifcs++;
5342         list_add_head(&priv->control_frames, &control_frame->entry);
5343     }
5344     else if(ins->handler_idx == WINED3DSIH_ELSE)
5345     {
5346         struct list *e = list_head(&priv->control_frames);
5347         control_frame = LIST_ENTRY(e, struct control_frame, entry);
5348
5349         if(control_frame->type == IF)
5350         {
5351             shader_addline(buffer, "#} else {\n");
5352             if(!priv->muted && !control_frame->muting)
5353             {
5354                 priv->muted = TRUE;
5355                 control_frame->muting = TRUE;
5356             }
5357             else if(control_frame->muting) priv->muted = FALSE;
5358             return; /* Instruction is handled. */
5359         }
5360         /* In case of an ifc, generate a HW shader instruction */
5361     }
5362     else if(ins->handler_idx == WINED3DSIH_ENDIF)
5363     {
5364         struct list *e = list_head(&priv->control_frames);
5365         control_frame = LIST_ENTRY(e, struct control_frame, entry);
5366
5367         if(control_frame->type == IF)
5368         {
5369             shader_addline(buffer, "#} endif\n");
5370             if(control_frame->muting) priv->muted = FALSE;
5371             list_remove(&control_frame->entry);
5372             HeapFree(GetProcessHeap(), 0, control_frame);
5373             return; /* Instruction is handled */
5374         }
5375     }
5376
5377     if(priv->muted) return;
5378
5379     /* Select handler */
5380     hw_fct = shader_arb_instruction_handler_table[ins->handler_idx];
5381
5382     /* Unhandled opcode */
5383     if (!hw_fct)
5384     {
5385         FIXME("Backend can't handle opcode %#x\n", ins->handler_idx);
5386         return;
5387     }
5388     hw_fct(ins);
5389
5390     if(ins->handler_idx == WINED3DSIH_ENDLOOP || ins->handler_idx == WINED3DSIH_ENDREP)
5391     {
5392         struct list *e = list_head(&priv->control_frames);
5393         control_frame = LIST_ENTRY(e, struct control_frame, entry);
5394         list_remove(&control_frame->entry);
5395         HeapFree(GetProcessHeap(), 0, control_frame);
5396         priv->loop_depth--;
5397     }
5398     else if(ins->handler_idx == WINED3DSIH_ENDIF)
5399     {
5400         /* Non-ifc ENDIFs don't reach that place because of the return in the if block above */
5401         struct list *e = list_head(&priv->control_frames);
5402         control_frame = LIST_ENTRY(e, struct control_frame, entry);
5403         list_remove(&control_frame->entry);
5404         HeapFree(GetProcessHeap(), 0, control_frame);
5405     }
5406
5407
5408     shader_arb_add_instruction_modifiers(ins);
5409 }
5410
5411 const shader_backend_t arb_program_shader_backend = {
5412     shader_arb_handle_instruction,
5413     shader_arb_select,
5414     shader_arb_select_depth_blt,
5415     shader_arb_deselect_depth_blt,
5416     shader_arb_update_float_vertex_constants,
5417     shader_arb_update_float_pixel_constants,
5418     shader_arb_load_constants,
5419     shader_arb_load_np2fixup_constants,
5420     shader_arb_destroy,
5421     shader_arb_alloc,
5422     shader_arb_free,
5423     shader_arb_dirty_const,
5424     shader_arb_get_caps,
5425     shader_arb_color_fixup_supported,
5426 };
5427
5428 /* ARB_fragment_program fixed function pipeline replacement definitions */
5429 #define ARB_FFP_CONST_TFACTOR           0
5430 #define ARB_FFP_CONST_SPECULAR_ENABLE   ((ARB_FFP_CONST_TFACTOR) + 1)
5431 #define ARB_FFP_CONST_CONSTANT(i)       ((ARB_FFP_CONST_SPECULAR_ENABLE) + 1 + i)
5432 #define ARB_FFP_CONST_BUMPMAT(i)        ((ARB_FFP_CONST_CONSTANT(7)) + 1 + i)
5433 #define ARB_FFP_CONST_LUMINANCE(i)      ((ARB_FFP_CONST_BUMPMAT(7)) + 1 + i)
5434
5435 struct arbfp_ffp_desc
5436 {
5437     struct ffp_frag_desc parent;
5438     GLuint shader;
5439     unsigned int num_textures_used;
5440 };
5441
5442 /* Context activation is done by the caller. */
5443 static void arbfp_enable(IWineD3DDevice *iface, BOOL enable) {
5444     ENTER_GL();
5445     if(enable) {
5446         glEnable(GL_FRAGMENT_PROGRAM_ARB);
5447         checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
5448     } else {
5449         glDisable(GL_FRAGMENT_PROGRAM_ARB);
5450         checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
5451     }
5452     LEAVE_GL();
5453 }
5454
5455 static HRESULT arbfp_alloc(IWineD3DDevice *iface) {
5456     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5457     struct shader_arb_priv *priv;
5458     /* Share private data between the shader backend and the pipeline replacement, if both
5459      * are the arb implementation. This is needed to figure out whether ARBfp should be disabled
5460      * if no pixel shader is bound or not
5461      */
5462     if(This->shader_backend == &arb_program_shader_backend) {
5463         This->fragment_priv = This->shader_priv;
5464     } else {
5465         This->fragment_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_arb_priv));
5466         if(!This->fragment_priv) return E_OUTOFMEMORY;
5467     }
5468     priv = This->fragment_priv;
5469     if (wine_rb_init(&priv->fragment_shaders, &wined3d_ffp_frag_program_rb_functions) == -1)
5470     {
5471         ERR("Failed to initialize rbtree.\n");
5472         HeapFree(GetProcessHeap(), 0, This->fragment_priv);
5473         return E_OUTOFMEMORY;
5474     }
5475     priv->use_arbfp_fixed_func = TRUE;
5476     return WINED3D_OK;
5477 }
5478
5479 /* Context activation is done by the caller. */
5480 static void arbfp_free_ffpshader(struct wine_rb_entry *entry, void *context)
5481 {
5482     const struct wined3d_gl_info *gl_info = context;
5483     struct arbfp_ffp_desc *entry_arb = WINE_RB_ENTRY_VALUE(entry, struct arbfp_ffp_desc, parent.entry);
5484
5485     ENTER_GL();
5486     GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader));
5487     checkGLcall("glDeleteProgramsARB(1, &entry_arb->shader)");
5488     HeapFree(GetProcessHeap(), 0, entry_arb);
5489     LEAVE_GL();
5490 }
5491
5492 /* Context activation is done by the caller. */
5493 static void arbfp_free(IWineD3DDevice *iface) {
5494     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5495     struct shader_arb_priv *priv = This->fragment_priv;
5496
5497     wine_rb_destroy(&priv->fragment_shaders, arbfp_free_ffpshader, &This->adapter->gl_info);
5498     priv->use_arbfp_fixed_func = FALSE;
5499
5500     if(This->shader_backend != &arb_program_shader_backend) {
5501         HeapFree(GetProcessHeap(), 0, This->fragment_priv);
5502     }
5503 }
5504
5505 static void arbfp_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
5506 {
5507     caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
5508     caps->TextureOpCaps =  WINED3DTEXOPCAPS_DISABLE                     |
5509                            WINED3DTEXOPCAPS_SELECTARG1                  |
5510                            WINED3DTEXOPCAPS_SELECTARG2                  |
5511                            WINED3DTEXOPCAPS_MODULATE4X                  |
5512                            WINED3DTEXOPCAPS_MODULATE2X                  |
5513                            WINED3DTEXOPCAPS_MODULATE                    |
5514                            WINED3DTEXOPCAPS_ADDSIGNED2X                 |
5515                            WINED3DTEXOPCAPS_ADDSIGNED                   |
5516                            WINED3DTEXOPCAPS_ADD                         |
5517                            WINED3DTEXOPCAPS_SUBTRACT                    |
5518                            WINED3DTEXOPCAPS_ADDSMOOTH                   |
5519                            WINED3DTEXOPCAPS_BLENDCURRENTALPHA           |
5520                            WINED3DTEXOPCAPS_BLENDFACTORALPHA            |
5521                            WINED3DTEXOPCAPS_BLENDTEXTUREALPHA           |
5522                            WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA           |
5523                            WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM         |
5524                            WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR      |
5525                            WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA      |
5526                            WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA   |
5527                            WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR   |
5528                            WINED3DTEXOPCAPS_DOTPRODUCT3                 |
5529                            WINED3DTEXOPCAPS_MULTIPLYADD                 |
5530                            WINED3DTEXOPCAPS_LERP                        |
5531                            WINED3DTEXOPCAPS_BUMPENVMAP                  |
5532                            WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE;
5533
5534     /* TODO: Implement WINED3DTEXOPCAPS_PREMODULATE */
5535
5536     caps->MaxTextureBlendStages   = 8;
5537     caps->MaxSimultaneousTextures = min(gl_info->limits.fragment_samplers, 8);
5538 }
5539
5540 static void state_texfactor_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5541 {
5542     const struct wined3d_gl_info *gl_info = context->gl_info;
5543     IWineD3DDeviceImpl *device = stateblock->device;
5544     float col[4];
5545
5546     /* Don't load the parameter if we're using an arbfp pixel shader, otherwise we'll overwrite
5547      * application provided constants
5548      */
5549     if(device->shader_backend == &arb_program_shader_backend) {
5550         if (use_ps(stateblock)) return;
5551
5552         context->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
5553         device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1);
5554     }
5555
5556     D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
5557     GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col));
5558     checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_TFACTOR, col)");
5559
5560 }
5561
5562 static void state_arb_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5563 {
5564     const struct wined3d_gl_info *gl_info = context->gl_info;
5565     IWineD3DDeviceImpl *device = stateblock->device;
5566     float col[4];
5567
5568     /* Don't load the parameter if we're using an arbfp pixel shader, otherwise we'll overwrite
5569      * application provided constants
5570      */
5571     if(device->shader_backend == &arb_program_shader_backend) {
5572         if (use_ps(stateblock)) return;
5573
5574         context->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
5575         device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_SPECULAR_ENABLE + 1);
5576     }
5577
5578     if(stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
5579         /* The specular color has no alpha */
5580         col[0] = 1.0f; col[1] = 1.0f;
5581         col[2] = 1.0f; col[3] = 0.0f;
5582     } else {
5583         col[0] = 0.0f; col[1] = 0.0f;
5584         col[2] = 0.0f; col[3] = 0.0f;
5585     }
5586     GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_SPECULAR_ENABLE, col));
5587     checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_SPECULAR_ENABLE, col)");
5588 }
5589
5590 static void set_bumpmat_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5591 {
5592     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
5593     const struct wined3d_gl_info *gl_info = context->gl_info;
5594     IWineD3DDeviceImpl *device = stateblock->device;
5595     float mat[2][2];
5596
5597     if (use_ps(stateblock))
5598     {
5599         if (stage != 0
5600                 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.bumpmat & (1 << stage)))
5601         {
5602             /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
5603              * anyway
5604              */
5605             if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT))
5606                 stateblock_apply_state(STATE_PIXELSHADERCONSTANT, stateblock, context);
5607         }
5608
5609         if(device->shader_backend == &arb_program_shader_backend) {
5610             /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
5611             return;
5612         }
5613     } else if(device->shader_backend == &arb_program_shader_backend) {
5614         context->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1;
5615         device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1);
5616     }
5617
5618     mat[0][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT00]);
5619     mat[0][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT01]);
5620     mat[1][0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT10]);
5621     mat[1][1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVMAT11]);
5622
5623     GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0]));
5624     checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_BUMPMAT(stage), &mat[0][0])");
5625 }
5626
5627 static void tex_bumpenvlum_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
5628 {
5629     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
5630     const struct wined3d_gl_info *gl_info = context->gl_info;
5631     IWineD3DDeviceImpl *device = stateblock->device;
5632     float param[4];
5633
5634     if (use_ps(stateblock))
5635     {
5636         if (stage != 0
5637                 && (((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.reg_maps.luminanceparams & (1 << stage)))
5638         {
5639             /* The pixel shader has to know the luminance offset. Do a constants update if it
5640              * isn't scheduled anyway
5641              */
5642             if (!isStateDirty(context, STATE_PIXELSHADERCONSTANT))
5643                 stateblock_apply_state(STATE_PIXELSHADERCONSTANT, stateblock, context);
5644         }
5645
5646         if(device->shader_backend == &arb_program_shader_backend) {
5647             /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
5648             return;
5649         }
5650     } else if(device->shader_backend == &arb_program_shader_backend) {
5651         context->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1;
5652         device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_LUMINANCE(stage) + 1);
5653     }
5654
5655     param[0] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVLSCALE]);
5656     param[1] = *((float *) &stateblock->textureState[stage][WINED3DTSS_BUMPENVLOFFSET]);
5657     param[2] = 0.0f;
5658     param[3] = 0.0f;
5659
5660     GL_EXTCALL(glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_LUMINANCE(stage), param));
5661     checkGLcall("glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARB_FFP_CONST_LUMINANCE(stage), param)");
5662 }
5663
5664 static const char *get_argreg(struct wined3d_shader_buffer *buffer, DWORD argnum, unsigned int stage, DWORD arg)
5665 {
5666     const char *ret;
5667
5668     if(arg == ARG_UNUSED) return "unused"; /* This is the marker for unused registers */
5669
5670     switch(arg & WINED3DTA_SELECTMASK) {
5671         case WINED3DTA_DIFFUSE:
5672             ret = "fragment.color.primary"; break;
5673
5674         case WINED3DTA_CURRENT:
5675             if(stage == 0) ret = "fragment.color.primary";
5676             else ret = "ret";
5677             break;
5678
5679         case WINED3DTA_TEXTURE:
5680             switch(stage) {
5681                 case 0: ret = "tex0"; break;
5682                 case 1: ret = "tex1"; break;
5683                 case 2: ret = "tex2"; break;
5684                 case 3: ret = "tex3"; break;
5685                 case 4: ret = "tex4"; break;
5686                 case 5: ret = "tex5"; break;
5687                 case 6: ret = "tex6"; break;
5688                 case 7: ret = "tex7"; break;
5689                 default: ret = "unknown texture";
5690             }
5691             break;
5692
5693         case WINED3DTA_TFACTOR:
5694             ret = "tfactor"; break;
5695
5696         case WINED3DTA_SPECULAR:
5697             ret = "fragment.color.secondary"; break;
5698
5699         case WINED3DTA_TEMP:
5700             ret = "tempreg"; break;
5701
5702         case WINED3DTA_CONSTANT:
5703             FIXME("Implement perstage constants\n");
5704             switch(stage) {
5705                 case 0: ret = "const0"; break;
5706                 case 1: ret = "const1"; break;
5707                 case 2: ret = "const2"; break;
5708                 case 3: ret = "const3"; break;
5709                 case 4: ret = "const4"; break;
5710                 case 5: ret = "const5"; break;
5711                 case 6: ret = "const6"; break;
5712                 case 7: ret = "const7"; break;
5713                 default: ret = "unknown constant";
5714             }
5715             break;
5716
5717         default:
5718             return "unknown";
5719     }
5720
5721     if(arg & WINED3DTA_COMPLEMENT) {
5722         shader_addline(buffer, "SUB arg%u, const.x, %s;\n", argnum, ret);
5723         if(argnum == 0) ret = "arg0";
5724         if(argnum == 1) ret = "arg1";
5725         if(argnum == 2) ret = "arg2";
5726     }
5727     if(arg & WINED3DTA_ALPHAREPLICATE) {
5728         shader_addline(buffer, "MOV arg%u, %s.w;\n", argnum, ret);
5729         if(argnum == 0) ret = "arg0";
5730         if(argnum == 1) ret = "arg1";
5731         if(argnum == 2) ret = "arg2";
5732     }
5733     return ret;
5734 }
5735
5736 static void gen_ffp_instr(struct wined3d_shader_buffer *buffer, unsigned int stage, BOOL color,
5737         BOOL alpha, DWORD dst, DWORD op, DWORD dw_arg0, DWORD dw_arg1, DWORD dw_arg2)
5738 {
5739     const char *dstmask, *dstreg, *arg0, *arg1, *arg2;
5740     unsigned int mul = 1;
5741     BOOL mul_final_dest = FALSE;
5742
5743     if(color && alpha) dstmask = "";
5744     else if(color) dstmask = ".xyz";
5745     else dstmask = ".w";
5746
5747     if(dst == tempreg) dstreg = "tempreg";
5748     else dstreg = "ret";
5749
5750     arg0 = get_argreg(buffer, 0, stage, dw_arg0);
5751     arg1 = get_argreg(buffer, 1, stage, dw_arg1);
5752     arg2 = get_argreg(buffer, 2, stage, dw_arg2);
5753
5754     switch(op) {
5755         case WINED3DTOP_DISABLE:
5756             if(stage == 0) shader_addline(buffer, "MOV %s%s, fragment.color.primary;\n", dstreg, dstmask);
5757             break;
5758
5759         case WINED3DTOP_SELECTARG2:
5760             arg1 = arg2;
5761         case WINED3DTOP_SELECTARG1:
5762             shader_addline(buffer, "MOV %s%s, %s;\n", dstreg, dstmask, arg1);
5763             break;
5764
5765         case WINED3DTOP_MODULATE4X:
5766             mul = 2;
5767         case WINED3DTOP_MODULATE2X:
5768             mul *= 2;
5769             if(strcmp(dstreg, "result.color") == 0) {
5770                 dstreg = "ret";
5771                 mul_final_dest = TRUE;
5772             }
5773         case WINED3DTOP_MODULATE:
5774             shader_addline(buffer, "MUL %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2);
5775             break;
5776
5777         case WINED3DTOP_ADDSIGNED2X:
5778             mul = 2;
5779             if(strcmp(dstreg, "result.color") == 0) {
5780                 dstreg = "ret";
5781                 mul_final_dest = TRUE;
5782             }
5783         case WINED3DTOP_ADDSIGNED:
5784             shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2);
5785             arg2 = "arg2";
5786         case WINED3DTOP_ADD:
5787             shader_addline(buffer, "ADD_SAT %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2);
5788             break;
5789
5790         case WINED3DTOP_SUBTRACT:
5791             shader_addline(buffer, "SUB_SAT %s%s, %s, %s;\n", dstreg, dstmask, arg1, arg2);
5792             break;
5793
5794         case WINED3DTOP_ADDSMOOTH:
5795             shader_addline(buffer, "SUB arg1, const.x, %s;\n", arg1);
5796             shader_addline(buffer, "MAD_SAT %s%s, arg1, %s, %s;\n", dstreg, dstmask, arg2, arg1);
5797             break;
5798
5799         case WINED3DTOP_BLENDCURRENTALPHA:
5800             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_CURRENT);
5801             shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
5802             break;
5803         case WINED3DTOP_BLENDFACTORALPHA:
5804             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TFACTOR);
5805             shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
5806             break;
5807         case WINED3DTOP_BLENDTEXTUREALPHA:
5808             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
5809             shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
5810             break;
5811         case WINED3DTOP_BLENDDIFFUSEALPHA:
5812             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_DIFFUSE);
5813             shader_addline(buffer, "LRP %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
5814             break;
5815
5816         case WINED3DTOP_BLENDTEXTUREALPHAPM:
5817             arg0 = get_argreg(buffer, 0, stage, WINED3DTA_TEXTURE);
5818             shader_addline(buffer, "SUB arg0.w, const.x, %s.w;\n", arg0);
5819             shader_addline(buffer, "MAD_SAT %s%s, %s, arg0.w, %s;\n", dstreg, dstmask, arg2, arg1);
5820             break;
5821
5822         /* D3DTOP_PREMODULATE ???? */
5823
5824         case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
5825             shader_addline(buffer, "SUB arg0.w, const.x, %s;\n", arg1);
5826             shader_addline(buffer, "MAD_SAT %s%s, arg0.w, %s, %s;\n", dstreg, dstmask, arg2, arg1);
5827             break;
5828         case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
5829             shader_addline(buffer, "MAD_SAT %s%s, %s.w, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg1);
5830             break;
5831         case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
5832             shader_addline(buffer, "SUB arg0, const.x, %s;\n", arg1);
5833             shader_addline(buffer, "MAD_SAT %s%s, arg0, %s, %s.w;\n", dstreg, dstmask, arg2, arg1);
5834             break;
5835         case WINED3DTOP_MODULATECOLOR_ADDALPHA:
5836             shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s.w;\n", dstreg, dstmask, arg1, arg2, arg1);
5837             break;
5838
5839         case WINED3DTOP_DOTPRODUCT3:
5840             mul = 4;
5841             if(strcmp(dstreg, "result.color") == 0) {
5842                 dstreg = "ret";
5843                 mul_final_dest = TRUE;
5844             }
5845             shader_addline(buffer, "SUB arg1, %s, const.w;\n", arg1);
5846             shader_addline(buffer, "SUB arg2, %s, const.w;\n", arg2);
5847             shader_addline(buffer, "DP3_SAT %s%s, arg1, arg2;\n", dstreg, dstmask);
5848             break;
5849
5850         case WINED3DTOP_MULTIPLYADD:
5851             shader_addline(buffer, "MAD_SAT %s%s, %s, %s, %s;\n", dstreg, dstmask, arg1, arg2, arg0);
5852             break;
5853
5854         case WINED3DTOP_LERP:
5855             /* The msdn is not quite right here */
5856             shader_addline(buffer, "LRP %s%s, %s, %s, %s;\n", dstreg, dstmask, arg0, arg1, arg2);
5857             break;
5858
5859         case WINED3DTOP_BUMPENVMAP:
5860         case WINED3DTOP_BUMPENVMAPLUMINANCE:
5861             /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */
5862             break;
5863
5864         default:
5865             FIXME("Unhandled texture op %08x\n", op);
5866     }
5867
5868     if(mul == 2) {
5869         shader_addline(buffer, "MUL_SAT %s%s, %s, const.y;\n", mul_final_dest ? "result.color" : dstreg, dstmask, dstreg);
5870     } else if(mul == 4) {
5871         shader_addline(buffer, "MUL_SAT %s%s, %s, const.z;\n", mul_final_dest ? "result.color" : dstreg, dstmask, dstreg);
5872     }
5873 }
5874
5875 static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, IWineD3DStateBlockImpl *stateblock)
5876 {
5877     const struct wined3d_gl_info *gl_info = &stateblock->device->adapter->gl_info;
5878     unsigned int stage;
5879     struct wined3d_shader_buffer buffer;
5880     BOOL tex_read[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
5881     BOOL bump_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
5882     BOOL luminance_used[MAX_TEXTURES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};
5883     const char *textype;
5884     const char *instr, *sat;
5885     char colorcor_dst[8];
5886     GLuint ret;
5887     DWORD arg0, arg1, arg2;
5888     BOOL tempreg_used = FALSE, tfactor_used = FALSE;
5889     BOOL op_equal;
5890     const char *final_combiner_src = "ret";
5891     GLint pos;
5892
5893     /* Find out which textures are read */
5894     for(stage = 0; stage < MAX_TEXTURES; stage++) {
5895         if(settings->op[stage].cop == WINED3DTOP_DISABLE) break;
5896         arg0 = settings->op[stage].carg0 & WINED3DTA_SELECTMASK;
5897         arg1 = settings->op[stage].carg1 & WINED3DTA_SELECTMASK;
5898         arg2 = settings->op[stage].carg2 & WINED3DTA_SELECTMASK;
5899         if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
5900         if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
5901         if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
5902
5903         if(settings->op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHA) tex_read[stage] = TRUE;
5904         if(settings->op[stage].cop == WINED3DTOP_BLENDTEXTUREALPHAPM) tex_read[stage] = TRUE;
5905         if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAP) {
5906             bump_used[stage] = TRUE;
5907             tex_read[stage] = TRUE;
5908         }
5909         if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) {
5910             bump_used[stage] = TRUE;
5911             tex_read[stage] = TRUE;
5912             luminance_used[stage] = TRUE;
5913         } else if(settings->op[stage].cop == WINED3DTOP_BLENDFACTORALPHA) {
5914             tfactor_used = TRUE;
5915         }
5916
5917         if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) {
5918             tfactor_used = TRUE;
5919         }
5920
5921         if(settings->op[stage].dst == tempreg) tempreg_used = TRUE;
5922         if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) {
5923             tempreg_used = TRUE;
5924         }
5925
5926         if(settings->op[stage].aop == WINED3DTOP_DISABLE) continue;
5927         arg0 = settings->op[stage].aarg0 & WINED3DTA_SELECTMASK;
5928         arg1 = settings->op[stage].aarg1 & WINED3DTA_SELECTMASK;
5929         arg2 = settings->op[stage].aarg2 & WINED3DTA_SELECTMASK;
5930         if(arg0 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
5931         if(arg1 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
5932         if(arg2 == WINED3DTA_TEXTURE) tex_read[stage] = TRUE;
5933
5934         if(arg0 == WINED3DTA_TEMP || arg1 == WINED3DTA_TEMP || arg2 == WINED3DTA_TEMP) {
5935             tempreg_used = TRUE;
5936         }
5937         if(arg0 == WINED3DTA_TFACTOR || arg1 == WINED3DTA_TFACTOR || arg2 == WINED3DTA_TFACTOR) {
5938             tfactor_used = TRUE;
5939         }
5940     }
5941
5942     /* Shader header */
5943     if (!shader_buffer_init(&buffer))
5944     {
5945         ERR("Failed to initialize shader buffer.\n");
5946         return 0;
5947     }
5948
5949     shader_addline(&buffer, "!!ARBfp1.0\n");
5950
5951     switch(settings->fog) {
5952         case FOG_OFF:                                                         break;
5953         case FOG_LINEAR: shader_addline(&buffer, "OPTION ARB_fog_linear;\n"); break;
5954         case FOG_EXP:    shader_addline(&buffer, "OPTION ARB_fog_exp;\n");    break;
5955         case FOG_EXP2:   shader_addline(&buffer, "OPTION ARB_fog_exp2;\n");   break;
5956         default: FIXME("Unexpected fog setting %d\n", settings->fog);
5957     }
5958
5959     shader_addline(&buffer, "PARAM const = {1, 2, 4, 0.5};\n");
5960     shader_addline(&buffer, "TEMP TMP;\n");
5961     shader_addline(&buffer, "TEMP ret;\n");
5962     if(tempreg_used || settings->sRGB_write) shader_addline(&buffer, "TEMP tempreg;\n");
5963     shader_addline(&buffer, "TEMP arg0;\n");
5964     shader_addline(&buffer, "TEMP arg1;\n");
5965     shader_addline(&buffer, "TEMP arg2;\n");
5966     for(stage = 0; stage < MAX_TEXTURES; stage++) {
5967         if(!tex_read[stage]) continue;
5968         shader_addline(&buffer, "TEMP tex%u;\n", stage);
5969         if(!bump_used[stage]) continue;
5970         shader_addline(&buffer, "PARAM bumpmat%u = program.env[%u];\n", stage, ARB_FFP_CONST_BUMPMAT(stage));
5971         if(!luminance_used[stage]) continue;
5972         shader_addline(&buffer, "PARAM luminance%u = program.env[%u];\n", stage, ARB_FFP_CONST_LUMINANCE(stage));
5973     }
5974     if(tfactor_used) {
5975         shader_addline(&buffer, "PARAM tfactor = program.env[%u];\n", ARB_FFP_CONST_TFACTOR);
5976     }
5977         shader_addline(&buffer, "PARAM specular_enable = program.env[%u];\n", ARB_FFP_CONST_SPECULAR_ENABLE);
5978
5979     if(settings->sRGB_write) {
5980         shader_addline(&buffer, "PARAM srgb_consts1 = {%f, %f, %f, %f};\n",
5981                        srgb_mul_low, srgb_cmp, srgb_pow, srgb_mul_high);
5982         shader_addline(&buffer, "PARAM srgb_consts2 = {%f, %f, %f, %f};\n",
5983                        srgb_sub_high, 0.0, 0.0, 0.0);
5984     }
5985
5986     if(ffp_clip_emul(stateblock) && settings->emul_clipplanes) shader_addline(&buffer, "KIL fragment.texcoord[7];\n");
5987
5988     /* Generate texture sampling instructions) */
5989     for(stage = 0; stage < MAX_TEXTURES && settings->op[stage].cop != WINED3DTOP_DISABLE; stage++) {
5990         if(!tex_read[stage]) continue;
5991
5992         switch(settings->op[stage].tex_type) {
5993             case tex_1d:                    textype = "1D";     break;
5994             case tex_2d:                    textype = "2D";     break;
5995             case tex_3d:                    textype = "3D";     break;
5996             case tex_cube:                  textype = "CUBE";   break;
5997             case tex_rect:                  textype = "RECT";   break;
5998             default: textype = "unexpected_textype";   break;
5999         }
6000
6001         if(settings->op[stage].cop == WINED3DTOP_BUMPENVMAP ||
6002            settings->op[stage].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) {
6003             sat = "";
6004         } else {
6005             sat = "_SAT";
6006         }
6007
6008         if(settings->op[stage].projected == proj_none) {
6009             instr = "TEX";
6010         } else if(settings->op[stage].projected == proj_count4 ||
6011                   settings->op[stage].projected == proj_count3) {
6012             instr = "TXP";
6013         } else {
6014             FIXME("Unexpected projection mode %d\n", settings->op[stage].projected);
6015             instr = "TXP";
6016         }
6017
6018         if(stage > 0 &&
6019            (settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAP ||
6020             settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE)) {
6021             shader_addline(&buffer, "SWZ arg1, bumpmat%u, x, z, 0, 0;\n", stage - 1);
6022             shader_addline(&buffer, "DP3 ret.x, arg1, tex%u;\n", stage - 1);
6023             shader_addline(&buffer, "SWZ arg1, bumpmat%u, y, w, 0, 0;\n", stage - 1);
6024             shader_addline(&buffer, "DP3 ret.y, arg1, tex%u;\n", stage - 1);
6025
6026             /* with projective textures, texbem only divides the static texture coord, not the displacement,
6027              * so multiply the displacement with the dividing parameter before passing it to TXP
6028              */
6029             if (settings->op[stage].projected != proj_none) {
6030                 if(settings->op[stage].projected == proj_count4) {
6031                     shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].w;\n", stage);
6032                     shader_addline(&buffer, "MUL ret.xyz, ret, fragment.texcoord[%u].w, fragment.texcoord[%u];\n", stage, stage);
6033                 } else {
6034                     shader_addline(&buffer, "MOV ret.w, fragment.texcoord[%u].z;\n", stage);
6035                     shader_addline(&buffer, "MAD ret.xyz, ret, fragment.texcoord[%u].z, fragment.texcoord[%u];\n", stage, stage);
6036                 }
6037             } else {
6038                 shader_addline(&buffer, "ADD ret, ret, fragment.texcoord[%u];\n", stage);
6039             }
6040
6041             shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
6042                            instr, sat, stage, stage, textype);
6043             if(settings->op[stage - 1].cop == WINED3DTOP_BUMPENVMAPLUMINANCE) {
6044                 shader_addline(&buffer, "MAD_SAT ret.x, tex%u.z, luminance%u.x, luminance%u.y;\n",
6045                                stage - 1, stage - 1, stage - 1);
6046                 shader_addline(&buffer, "MUL tex%u, tex%u, ret.x;\n", stage, stage);
6047             }
6048         } else if(settings->op[stage].projected == proj_count3) {
6049             shader_addline(&buffer, "MOV ret, fragment.texcoord[%u];\n", stage);
6050             shader_addline(&buffer, "MOV ret.w, ret.z;\n");
6051             shader_addline(&buffer, "%s%s tex%u, ret, texture[%u], %s;\n",
6052                             instr, sat, stage, stage, textype);
6053         } else {
6054             shader_addline(&buffer, "%s%s tex%u, fragment.texcoord[%u], texture[%u], %s;\n",
6055                             instr, sat, stage, stage, stage, textype);
6056         }
6057
6058         sprintf(colorcor_dst, "tex%u", stage);
6059         gen_color_correction(&buffer, colorcor_dst, WINED3DSP_WRITEMASK_ALL, "const.x", "const.y",
6060                 settings->op[stage].color_fixup);
6061     }
6062
6063     /* Generate the main shader */
6064     for(stage = 0; stage < MAX_TEXTURES; stage++) {
6065         if(settings->op[stage].cop == WINED3DTOP_DISABLE) {
6066             if(stage == 0) {
6067                 final_combiner_src = "fragment.color.primary";
6068             }
6069             break;
6070         }
6071
6072         if(settings->op[stage].cop == WINED3DTOP_SELECTARG1 &&
6073            settings->op[stage].aop == WINED3DTOP_SELECTARG1) {
6074             op_equal = settings->op[stage].carg1 == settings->op[stage].aarg1;
6075         } else if(settings->op[stage].cop == WINED3DTOP_SELECTARG1 &&
6076                   settings->op[stage].aop == WINED3DTOP_SELECTARG2) {
6077             op_equal = settings->op[stage].carg1 == settings->op[stage].aarg2;
6078         } else if(settings->op[stage].cop == WINED3DTOP_SELECTARG2 &&
6079                   settings->op[stage].aop == WINED3DTOP_SELECTARG1) {
6080             op_equal = settings->op[stage].carg2 == settings->op[stage].aarg1;
6081         } else if(settings->op[stage].cop == WINED3DTOP_SELECTARG2 &&
6082                   settings->op[stage].aop == WINED3DTOP_SELECTARG2) {
6083             op_equal = settings->op[stage].carg2 == settings->op[stage].aarg2;
6084         } else {
6085             op_equal = settings->op[stage].aop   == settings->op[stage].cop &&
6086                        settings->op[stage].carg0 == settings->op[stage].aarg0 &&
6087                        settings->op[stage].carg1 == settings->op[stage].aarg1 &&
6088                        settings->op[stage].carg2 == settings->op[stage].aarg2;
6089         }
6090
6091         if(settings->op[stage].aop == WINED3DTOP_DISABLE) {
6092             gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst,
6093                           settings->op[stage].cop, settings->op[stage].carg0,
6094                           settings->op[stage].carg1, settings->op[stage].carg2);
6095             if(stage == 0) {
6096                 shader_addline(&buffer, "MOV ret.w, fragment.color.primary.w;\n");
6097             }
6098         } else if(op_equal) {
6099             gen_ffp_instr(&buffer, stage, TRUE, TRUE, settings->op[stage].dst,
6100                           settings->op[stage].cop, settings->op[stage].carg0,
6101                           settings->op[stage].carg1, settings->op[stage].carg2);
6102         } else {
6103             gen_ffp_instr(&buffer, stage, TRUE, FALSE, settings->op[stage].dst,
6104                           settings->op[stage].cop, settings->op[stage].carg0,
6105                           settings->op[stage].carg1, settings->op[stage].carg2);
6106             gen_ffp_instr(&buffer, stage, FALSE, TRUE, settings->op[stage].dst,
6107                           settings->op[stage].aop, settings->op[stage].aarg0,
6108                           settings->op[stage].aarg1, settings->op[stage].aarg2);
6109         }
6110     }
6111
6112     if(settings->sRGB_write) {
6113         shader_addline(&buffer, "MAD ret, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
6114         arbfp_add_sRGB_correction(&buffer, "ret", "arg0", "arg1", "arg2", "tempreg", FALSE);
6115         shader_addline(&buffer, "MOV result.color, ret;\n");
6116     } else {
6117         shader_addline(&buffer, "MAD result.color, fragment.color.secondary, specular_enable, %s;\n", final_combiner_src);
6118     }
6119
6120     /* Footer */
6121     shader_addline(&buffer, "END\n");
6122
6123     /* Generate the shader */
6124     GL_EXTCALL(glGenProgramsARB(1, &ret));
6125     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, ret));
6126     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
6127             strlen(buffer.buffer), buffer.buffer));
6128     checkGLcall("glProgramStringARB()");
6129
6130     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
6131     if (pos != -1)
6132     {
6133         FIXME("Fragment program error at position %d: %s\n\n", pos,
6134               debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
6135         shader_arb_dump_program_source(buffer.buffer);
6136     }
6137     else
6138     {
6139         GLint native;
6140
6141         GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
6142         checkGLcall("glGetProgramivARB()");
6143         if (!native) WARN("Program exceeds native resource limits.\n");
6144     }
6145
6146     shader_buffer_free(&buffer);
6147     return ret;
6148 }
6149
6150 static void fragment_prog_arbfp(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
6151 {
6152     const struct wined3d_gl_info *gl_info = context->gl_info;
6153     IWineD3DDeviceImpl *device = stateblock->device;
6154     struct shader_arb_priv *priv = device->fragment_priv;
6155     BOOL use_pshader = use_ps(stateblock);
6156     BOOL use_vshader = use_vs(stateblock);
6157     struct ffp_frag_settings settings;
6158     const struct arbfp_ffp_desc *desc;
6159     unsigned int i;
6160
6161     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
6162
6163     if(isStateDirty(context, STATE_RENDER(WINED3DRS_FOGENABLE))) {
6164         if(!use_pshader && device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) {
6165             /* Reload fixed function constants since they collide with the pixel shader constants */
6166             for(i = 0; i < MAX_TEXTURES; i++) {
6167                 set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context);
6168             }
6169             state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context);
6170             state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context);
6171         } else if(use_pshader && !isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
6172             device->shader_backend->shader_select(context, use_pshader, use_vshader);
6173         }
6174         return;
6175     }
6176
6177     if(!use_pshader) {
6178         /* Find or create a shader implementing the fixed function pipeline settings, then activate it */
6179         gen_ffp_frag_op(stateblock, &settings, FALSE);
6180         desc = (const struct arbfp_ffp_desc *)find_ffp_frag_shader(&priv->fragment_shaders, &settings);
6181         if(!desc) {
6182             struct arbfp_ffp_desc *new_desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_desc));
6183             if (!new_desc)
6184             {
6185                 ERR("Out of memory\n");
6186                 return;
6187             }
6188             new_desc->num_textures_used = 0;
6189             for (i = 0; i < gl_info->limits.texture_stages; ++i)
6190             {
6191                 if(settings.op[i].cop == WINED3DTOP_DISABLE) break;
6192                 new_desc->num_textures_used = i;
6193             }
6194
6195             memcpy(&new_desc->parent.settings, &settings, sizeof(settings));
6196             new_desc->shader = gen_arbfp_ffp_shader(&settings, stateblock);
6197             add_ffp_frag_shader(&priv->fragment_shaders, &new_desc->parent);
6198             TRACE("Allocated fixed function replacement shader descriptor %p\n", new_desc);
6199             desc = new_desc;
6200         }
6201
6202         /* Now activate the replacement program. GL_FRAGMENT_PROGRAM_ARB is already active(however, note the
6203          * comment above the shader_select call below). If e.g. GLSL is active, the shader_select call will
6204          * deactivate it.
6205          */
6206         GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader));
6207         checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, desc->shader)");
6208         priv->current_fprogram_id = desc->shader;
6209
6210         if(device->shader_backend == &arb_program_shader_backend && context->last_was_pshader) {
6211             /* Reload fixed function constants since they collide with the pixel shader constants */
6212             for(i = 0; i < MAX_TEXTURES; i++) {
6213                 set_bumpmat_arbfp(STATE_TEXTURESTAGE(i, WINED3DTSS_BUMPENVMAT00), stateblock, context);
6214             }
6215             state_texfactor_arbfp(STATE_RENDER(WINED3DRS_TEXTUREFACTOR), stateblock, context);
6216             state_arb_specularenable(STATE_RENDER(WINED3DRS_SPECULARENABLE), stateblock, context);
6217         }
6218         context->last_was_pshader = FALSE;
6219     } else {
6220         context->last_was_pshader = TRUE;
6221     }
6222
6223     /* Finally, select the shader. If a pixel shader is used, it will be set and enabled by the shader backend.
6224      * If this shader backend is arbfp(most likely), then it will simply overwrite the last fixed function replace-
6225      * ment shader. If the shader backend is not ARB, it currently is important that the opengl implementation
6226      * type overwrites GL_ARB_fragment_program. This is currently the case with GLSL. If we really want to use
6227      * atifs or nvrc pixel shaders with arb fragment programs we'd have to disable GL_FRAGMENT_PROGRAM_ARB here
6228      *
6229      * Don't call shader_select if the vertex shader is dirty, because it will be called later on by the vertex
6230      * shader handler
6231      */
6232     if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
6233         device->shader_backend->shader_select(context, use_pshader, use_vshader);
6234
6235         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader))
6236             stateblock_apply_state(STATE_VERTEXSHADERCONSTANT, stateblock, context);
6237     }
6238     if (use_pshader) stateblock_apply_state(STATE_PIXELSHADERCONSTANT, stateblock, context);
6239 }
6240
6241 /* We can't link the fog states to the fragment state directly since the vertex pipeline links them
6242  * to FOGENABLE. A different linking in different pipeline parts can't be expressed in the combined
6243  * state table, so we need to handle that with a forwarding function. The other invisible side effect
6244  * is that changing the fog start and fog end(which links to FOGENABLE in vertex) results in the
6245  * fragment_prog_arbfp function being called because FOGENABLE is dirty, which calls this function here
6246  */
6247 static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
6248 {
6249     enum fogsource new_source;
6250
6251     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
6252
6253     if(!isStateDirty(context, STATE_PIXELSHADER)) {
6254         fragment_prog_arbfp(state, stateblock, context);
6255     }
6256
6257     if(!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
6258
6259     if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
6260         if(use_vs(stateblock)) {
6261             new_source = FOGSOURCE_VS;
6262         } else {
6263             if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
6264                 new_source = FOGSOURCE_COORD;
6265             } else {
6266                 new_source = FOGSOURCE_FFP;
6267             }
6268         }
6269     } else {
6270         new_source = FOGSOURCE_FFP;
6271     }
6272     if(new_source != context->fog_source) {
6273         context->fog_source = new_source;
6274         state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
6275     }
6276 }
6277
6278 static void textransform(DWORD state, IWineD3DStateBlockImpl *stateblock, struct wined3d_context *context)
6279 {
6280     if(!isStateDirty(context, STATE_PIXELSHADER)) {
6281         fragment_prog_arbfp(state, stateblock, context);
6282     }
6283 }
6284
6285 static const struct StateEntryTemplate arbfp_fragmentstate_template[] = {
6286     {STATE_RENDER(WINED3DRS_TEXTUREFACTOR),               { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              state_texfactor_arbfp   }, WINED3D_GL_EXT_NONE             },
6287     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6288     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6289     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6290     {STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6291     {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6292     {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6293     {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6294     {STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6295     {STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6296     {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6297     {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6298     {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6299     {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6300     {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6301     {STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6302     {STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6303     {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6304     {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6305     {STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6306     {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6307     {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6308     {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6309     {STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6310     {STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6311     {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6312     {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6313     {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6314     {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6315     {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6316     {STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6317     {STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6318     {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6319     {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6320     {STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6321     {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6322     {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6323     {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6324     {STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6325     {STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6326     {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6327     {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6328     {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6329     {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6330     {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6331     {STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6332     {STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6333     {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6334     {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6335     {STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6336     {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6337     {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6338     {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6339     {STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6340     {STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6341     {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6342     {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6343     {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6344     {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6345     {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6346     {STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6347     {STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6348     {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6349     {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6350     {STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6351     {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6352     {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6353     {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6354     {STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6355     {STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6356     {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6357     {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6358     {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6359     {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6360     {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6361     {STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6362     {STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6363     {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6364     {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6365     {STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6366     {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6367     {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6368     {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6369     {STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6370     {STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6371     {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6372     {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6373     {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6374     {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6375     {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6376     {STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6377     {STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6378     {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6379     {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6380     {STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6381     {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6382     {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6383     {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6384     {STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6385     {STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6386     {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6387     {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6388     {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6389     {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6390     {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6391     {STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6392     {STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6393     {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6394     {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6395     {STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6396     {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),           { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6397     {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6398     {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6399     {STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6400     {STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG),         { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6401     {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),      { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     set_bumpmat_arbfp       }, WINED3D_GL_EXT_NONE             },
6402     {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01),      { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6403     {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10),      { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6404     {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11),      { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     NULL                    }, WINED3D_GL_EXT_NONE             },
6405     {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlum_arbfp    }, WINED3D_GL_EXT_NONE             },
6406     {STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET),    { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    NULL                    }, WINED3D_GL_EXT_NONE             },
6407     {STATE_SAMPLER(0),                                    { STATE_SAMPLER(0),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6408     {STATE_SAMPLER(1),                                    { STATE_SAMPLER(1),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6409     {STATE_SAMPLER(2),                                    { STATE_SAMPLER(2),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6410     {STATE_SAMPLER(3),                                    { STATE_SAMPLER(3),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6411     {STATE_SAMPLER(4),                                    { STATE_SAMPLER(4),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6412     {STATE_SAMPLER(5),                                    { STATE_SAMPLER(5),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6413     {STATE_SAMPLER(6),                                    { STATE_SAMPLER(6),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6414     {STATE_SAMPLER(7),                                    { STATE_SAMPLER(7),                                   sampler_texdim          }, WINED3D_GL_EXT_NONE             },
6415     {STATE_PIXELSHADER,                                   { STATE_PIXELSHADER,                                  fragment_prog_arbfp     }, WINED3D_GL_EXT_NONE             },
6416     {STATE_RENDER(WINED3DRS_FOGENABLE),                   { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_arbfp_fog         }, WINED3D_GL_EXT_NONE             },
6417     {STATE_RENDER(WINED3DRS_FOGTABLEMODE),                { STATE_RENDER(WINED3DRS_FOGENABLE),                  NULL                    }, WINED3D_GL_EXT_NONE             },
6418     {STATE_RENDER(WINED3DRS_FOGVERTEXMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  NULL                    }, WINED3D_GL_EXT_NONE             },
6419     {STATE_RENDER(WINED3DRS_FOGSTART),                    { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend       }, WINED3D_GL_EXT_NONE             },
6420     {STATE_RENDER(WINED3DRS_FOGEND),                      { STATE_RENDER(WINED3DRS_FOGSTART),                   NULL                    }, WINED3D_GL_EXT_NONE             },
6421     {STATE_RENDER(WINED3DRS_SRGBWRITEENABLE),             { STATE_PIXELSHADER,                                  NULL                    }, WINED3D_GL_EXT_NONE             },
6422     {STATE_RENDER(WINED3DRS_FOGCOLOR),                    { STATE_RENDER(WINED3DRS_FOGCOLOR),                   state_fogcolor          }, WINED3D_GL_EXT_NONE             },
6423     {STATE_RENDER(WINED3DRS_FOGDENSITY),                  { STATE_RENDER(WINED3DRS_FOGDENSITY),                 state_fogdensity        }, WINED3D_GL_EXT_NONE             },
6424     {STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6425     {STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6426     {STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6427     {STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6428     {STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6429     {STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6430     {STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6431     {STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7, WINED3DTSS_TEXTURETRANSFORMFLAGS), textransform      }, WINED3D_GL_EXT_NONE             },
6432     {STATE_RENDER(WINED3DRS_SPECULARENABLE),              { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_arb_specularenable}, WINED3D_GL_EXT_NONE             },
6433     {0 /* Terminate */,                                   { 0,                                                  0                       }, WINED3D_GL_EXT_NONE             },
6434 };
6435
6436 const struct fragment_pipeline arbfp_fragment_pipeline = {
6437     arbfp_enable,
6438     arbfp_get_caps,
6439     arbfp_alloc,
6440     arbfp_free,
6441     shader_arb_color_fixup_supported,
6442     arbfp_fragmentstate_template,
6443     TRUE /* We can disable projected textures */
6444 };
6445
6446 struct arbfp_blit_priv {
6447     GLenum yuy2_rect_shader, yuy2_2d_shader;
6448     GLenum uyvy_rect_shader, uyvy_2d_shader;
6449     GLenum yv12_rect_shader, yv12_2d_shader;
6450     GLenum p8_rect_shader, p8_2d_shader;
6451     GLuint palette_texture;
6452 };
6453
6454 static HRESULT arbfp_blit_alloc(IWineD3DDevice *iface) {
6455     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface;
6456     device->blit_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arbfp_blit_priv));
6457     if(!device->blit_priv) {
6458         ERR("Out of memory\n");
6459         return E_OUTOFMEMORY;
6460     }
6461     return WINED3D_OK;
6462 }
6463
6464 /* Context activation is done by the caller. */
6465 static void arbfp_blit_free(IWineD3DDevice *iface) {
6466     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface;
6467     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6468     struct arbfp_blit_priv *priv = device->blit_priv;
6469
6470     ENTER_GL();
6471     GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_rect_shader));
6472     GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_2d_shader));
6473     GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_rect_shader));
6474     GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_2d_shader));
6475     GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_rect_shader));
6476     GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_2d_shader));
6477     GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_rect_shader));
6478     GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_2d_shader));
6479     checkGLcall("Delete yuv and p8 programs");
6480
6481     if(priv->palette_texture) glDeleteTextures(1, &priv->palette_texture);
6482     LEAVE_GL();
6483
6484     HeapFree(GetProcessHeap(), 0, device->blit_priv);
6485     device->blit_priv = NULL;
6486 }
6487
6488 static BOOL gen_planar_yuv_read(struct wined3d_shader_buffer *buffer, enum complex_fixup fixup,
6489         GLenum textype, char *luminance)
6490 {
6491     char chroma;
6492     const char *tex, *texinstr;
6493
6494     if (fixup == COMPLEX_FIXUP_UYVY) {
6495         chroma = 'x';
6496         *luminance = 'w';
6497     } else {
6498         chroma = 'w';
6499         *luminance = 'x';
6500     }
6501     switch(textype) {
6502         case GL_TEXTURE_2D:             tex = "2D";     texinstr = "TXP"; break;
6503         case GL_TEXTURE_RECTANGLE_ARB:  tex = "RECT";   texinstr = "TEX"; break;
6504         default:
6505             /* This is more tricky than just replacing the texture type - we have to navigate
6506              * properly in the texture to find the correct chroma values
6507              */
6508             FIXME("Implement yuv correction for non-2d, non-rect textures\n");
6509             return FALSE;
6510     }
6511
6512     /* First we have to read the chroma values. This means we need at least two pixels(no filtering),
6513      * or 4 pixels(with filtering). To get the unmodified chromas, we have to rid ourselves of the
6514      * filtering when we sample the texture.
6515      *
6516      * These are the rules for reading the chroma:
6517      *
6518      * Even pixel: Cr
6519      * Even pixel: U
6520      * Odd pixel: V
6521      *
6522      * So we have to get the sampling x position in non-normalized coordinates in integers
6523      */
6524     if(textype != GL_TEXTURE_RECTANGLE_ARB) {
6525         shader_addline(buffer, "MUL texcrd.xy, fragment.texcoord[0], size.x;\n");
6526         shader_addline(buffer, "MOV texcrd.w, size.x;\n");
6527     } else {
6528         shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
6529     }
6530     /* We must not allow filtering between pixel x and x+1, this would mix U and V
6531      * Vertical filtering is ok. However, bear in mind that the pixel center is at
6532      * 0.5, so add 0.5.
6533      */
6534     shader_addline(buffer, "FLR texcrd.x, texcrd.x;\n");
6535     shader_addline(buffer, "ADD texcrd.x, texcrd.x, coef.y;\n");
6536
6537     /* Divide the x coordinate by 0.5 and get the fraction. This gives 0.25 and 0.75 for the
6538      * even and odd pixels respectively
6539      */
6540     shader_addline(buffer, "MUL texcrd2, texcrd, coef.y;\n");
6541     shader_addline(buffer, "FRC texcrd2, texcrd2;\n");
6542
6543     /* Sample Pixel 1 */
6544     shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex);
6545
6546     /* Put the value into either of the chroma values */
6547     shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
6548     shader_addline(buffer, "MUL chroma.x, luminance.%c, temp.x;\n", chroma);
6549     shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
6550     shader_addline(buffer, "MUL chroma.y, luminance.%c, temp.x;\n", chroma);
6551
6552     /* Sample pixel 2. If we read an even pixel(SLT above returned 1), sample
6553      * the pixel right to the current one. Otherwise, sample the left pixel.
6554      * Bias and scale the SLT result to -1;1 and add it to the texcrd.x.
6555      */
6556     shader_addline(buffer, "MAD temp.x, temp.x, coef.z, -coef.x;\n");
6557     shader_addline(buffer, "ADD texcrd.x, texcrd, temp.x;\n");
6558     shader_addline(buffer, "%s luminance, texcrd, texture[0], %s;\n", texinstr, tex);
6559
6560     /* Put the value into the other chroma */
6561     shader_addline(buffer, "SGE temp.x, texcrd2.x, coef.y;\n");
6562     shader_addline(buffer, "MAD chroma.y, luminance.%c, temp.x, chroma.y;\n", chroma);
6563     shader_addline(buffer, "SLT temp.x, texcrd2.x, coef.y;\n");
6564     shader_addline(buffer, "MAD chroma.x, luminance.%c, temp.x, chroma.x;\n", chroma);
6565
6566     /* TODO: If filtering is enabled, sample a 2nd pair of pixels left or right of
6567      * the current one and lerp the two U and V values
6568      */
6569
6570     /* This gives the correctly filtered luminance value */
6571     shader_addline(buffer, "TEX luminance, fragment.texcoord[0], texture[0], %s;\n", tex);
6572
6573     return TRUE;
6574 }
6575
6576 static BOOL gen_yv12_read(struct wined3d_shader_buffer *buffer, GLenum textype, char *luminance)
6577 {
6578     const char *tex;
6579
6580     switch(textype) {
6581         case GL_TEXTURE_2D:             tex = "2D";     break;
6582         case GL_TEXTURE_RECTANGLE_ARB:  tex = "RECT";   break;
6583         default:
6584             FIXME("Implement yv12 correction for non-2d, non-rect textures\n");
6585             return FALSE;
6586     }
6587
6588     /* YV12 surfaces contain a WxH sized luminance plane, followed by a (W/2)x(H/2)
6589      * V and a (W/2)x(H/2) U plane, each with 8 bit per pixel. So the effective
6590      * bitdepth is 12 bits per pixel. Since the U and V planes have only half the
6591      * pitch of the luminance plane, the packing into the gl texture is a bit
6592      * unfortunate. If the whole texture is interpreted as luminance data it looks
6593      * approximately like this:
6594      *
6595      *        +----------------------------------+----
6596      *        |                                  |
6597      *        |                                  |
6598      *        |                                  |
6599      *        |                                  |
6600      *        |                                  |   2
6601      *        |            LUMINANCE             |   -
6602      *        |                                  |   3
6603      *        |                                  |
6604      *        |                                  |
6605      *        |                                  |
6606      *        |                                  |
6607      *        +----------------+-----------------+----
6608      *        |                |                 |
6609      *        |  U even rows   |  U odd rows     |
6610      *        |                |                 |   1
6611      *        +----------------+------------------   -
6612      *        |                |                 |   3
6613      *        |  V even rows   |  V odd rows     |
6614      *        |                |                 |
6615      *        +----------------+-----------------+----
6616      *        |                |                 |
6617      *        |     0.5        |       0.5       |
6618      *
6619      * So it appears as if there are 4 chroma images, but in fact the odd rows
6620      * in the chroma images are in the same row as the even ones. So its is
6621      * kinda tricky to read
6622      *
6623      * When reading from rectangle textures, keep in mind that the input y coordinates
6624      * go from 0 to d3d_height, whereas the opengl texture height is 1.5 * d3d_height
6625      */
6626     shader_addline(buffer, "PARAM yv12_coef = {%f, %f, %f, %f};\n",
6627             2.0f / 3.0f, 1.0f / 6.0f, (2.0f / 3.0f) + (1.0f / 6.0f), 1.0f / 3.0f);
6628
6629     shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
6630     /* the chroma planes have only half the width */
6631     shader_addline(buffer, "MUL texcrd.x, texcrd.x, coef.y;\n");
6632
6633     /* The first value is between 2/3 and 5/6th of the texture's height, so scale+bias
6634      * the coordinate. Also read the right side of the image when reading odd lines
6635      *
6636      * Don't forget to clamp the y values in into the range, otherwise we'll get filtering
6637      * bleeding
6638      */
6639     if(textype == GL_TEXTURE_2D) {
6640
6641         shader_addline(buffer, "RCP chroma.w, size.y;\n");
6642
6643         shader_addline(buffer, "MUL texcrd2.y, texcrd.y, size.y;\n");
6644
6645         shader_addline(buffer, "FLR texcrd2.y, texcrd2.y;\n");
6646         shader_addline(buffer, "MAD texcrd.y, texcrd.y, yv12_coef.y, yv12_coef.x;\n");
6647
6648         /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
6649         shader_addline(buffer, "ADD texcrd2.x, texcrd2.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */
6650         shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
6651         shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
6652         shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, texcrd.x;\n");
6653
6654         /* clamp, keep the half pixel origin in mind */
6655         shader_addline(buffer, "MAD temp.y, coef.y, chroma.w, yv12_coef.x;\n");
6656         shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n");
6657         shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, yv12_coef.z;\n");
6658         shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
6659     } else {
6660         /* Read from [size - size+size/4] */
6661         shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");
6662         shader_addline(buffer, "MAD texcrd.y, texcrd.y, coef.w, size.y;\n");
6663
6664         /* Read odd lines from the right side(add size * 0.5 to the x coordinate */
6665         shader_addline(buffer, "ADD texcrd2.x, texcrd.y, yv12_coef.y;\n"); /* To avoid 0.5 == 0.5 comparisons */
6666         shader_addline(buffer, "FRC texcrd2.x, texcrd2.x;\n");
6667         shader_addline(buffer, "SGE texcrd2.x, texcrd2.x, coef.y;\n");
6668         shader_addline(buffer, "MUL texcrd2.x, texcrd2.x, size.x;\n");
6669         shader_addline(buffer, "MAD texcrd.x, texcrd2.x, coef.y, texcrd.x;\n");
6670
6671         /* Make sure to read exactly from the pixel center */
6672         shader_addline(buffer, "FLR texcrd.y, texcrd.y;\n");
6673         shader_addline(buffer, "ADD texcrd.y, texcrd.y, coef.y;\n");
6674
6675         /* Clamp */
6676         shader_addline(buffer, "MAD temp.y, size.y, coef.w, size.y;\n");
6677         shader_addline(buffer, "ADD temp.y, temp.y, -coef.y;\n");
6678         shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
6679         shader_addline(buffer, "ADD temp.y, size.y, -coef.y;\n");
6680         shader_addline(buffer, "MAX texcrd.y, temp.y, texcrd.y;\n");
6681     }
6682     /* Read the texture, put the result into the output register */
6683     shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
6684     shader_addline(buffer, "MOV chroma.x, temp.w;\n");
6685
6686     /* The other chroma value is 1/6th of the texture lower, from 5/6th to 6/6th
6687      * No need to clamp because we're just reusing the already clamped value from above
6688      */
6689     if(textype == GL_TEXTURE_2D) {
6690         shader_addline(buffer, "ADD texcrd.y, texcrd.y, yv12_coef.y;\n");
6691     } else {
6692         shader_addline(buffer, "MAD texcrd.y, size.y, coef.w, texcrd.y;\n");
6693     }
6694     shader_addline(buffer, "TEX temp, texcrd, texture[0], %s;\n", tex);
6695     shader_addline(buffer, "MOV chroma.y, temp.w;\n");
6696
6697     /* Sample the luminance value. It is in the top 2/3rd of the texture, so scale the y coordinate.
6698      * Clamp the y coordinate to prevent the chroma values from bleeding into the sampled luminance
6699      * values due to filtering
6700      */
6701     shader_addline(buffer, "MOV texcrd, fragment.texcoord[0];\n");
6702     if(textype == GL_TEXTURE_2D) {
6703         /* Multiply the y coordinate by 2/3 and clamp it */
6704         shader_addline(buffer, "MUL texcrd.y, texcrd.y, yv12_coef.x;\n");
6705         shader_addline(buffer, "MAD temp.y, -coef.y, chroma.w, yv12_coef.x;\n");
6706         shader_addline(buffer, "MIN texcrd.y, temp.y, texcrd.y;\n");
6707         shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
6708     } else {
6709         /* Reading from texture_rectangles is pretty straightforward, just use the unmodified
6710          * texture coordinate. It is still a good idea to clamp it though, since the opengl texture
6711          * is bigger
6712          */
6713         shader_addline(buffer, "ADD temp.x, size.y, -coef.y;\n");
6714         shader_addline(buffer, "MIN texcrd.y, texcrd.y, size.x;\n");
6715         shader_addline(buffer, "TEX luminance, texcrd, texture[0], %s;\n", tex);
6716     }
6717     *luminance = 'a';
6718
6719     return TRUE;
6720 }
6721
6722 static GLuint gen_p8_shader(IWineD3DDeviceImpl *device, GLenum textype)
6723 {
6724     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6725     GLenum shader;
6726     struct wined3d_shader_buffer buffer;
6727     struct arbfp_blit_priv *priv = device->blit_priv;
6728     GLint pos;
6729
6730     /* Shader header */
6731     if (!shader_buffer_init(&buffer))
6732     {
6733         ERR("Failed to initialize shader buffer.\n");
6734         return 0;
6735     }
6736
6737     ENTER_GL();
6738     GL_EXTCALL(glGenProgramsARB(1, &shader));
6739     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
6740     LEAVE_GL();
6741     if(!shader) {
6742         shader_buffer_free(&buffer);
6743         return 0;
6744     }
6745
6746     shader_addline(&buffer, "!!ARBfp1.0\n");
6747     shader_addline(&buffer, "TEMP index;\n");
6748
6749     /* { 255/256, 0.5/255*255/256, 0, 0 } */
6750     shader_addline(&buffer, "PARAM constants = { 0.996, 0.00195, 0, 0 };\n");
6751
6752     /* The alpha-component contains the palette index */
6753     if(textype == GL_TEXTURE_RECTANGLE_ARB)
6754         shader_addline(&buffer, "TXP index, fragment.texcoord[0], texture[0], RECT;\n");
6755     else
6756         shader_addline(&buffer, "TEX index, fragment.texcoord[0], texture[0], 2D;\n");
6757
6758     /* Scale the index by 255/256 and add a bias of '0.5' in order to sample in the middle */
6759     shader_addline(&buffer, "MAD index.a, index.a, constants.x, constants.y;\n");
6760
6761     /* Use the alpha-component as an index in the palette to get the final color */
6762     shader_addline(&buffer, "TEX result.color, index.a, texture[1], 1D;\n");
6763     shader_addline(&buffer, "END\n");
6764
6765     ENTER_GL();
6766     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
6767             strlen(buffer.buffer), buffer.buffer));
6768     checkGLcall("glProgramStringARB()");
6769
6770     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
6771     if (pos != -1)
6772     {
6773         FIXME("Fragment program error at position %d: %s\n\n", pos,
6774               debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
6775         shader_arb_dump_program_source(buffer.buffer);
6776     }
6777
6778     if (textype == GL_TEXTURE_RECTANGLE_ARB)
6779         priv->p8_rect_shader = shader;
6780     else
6781         priv->p8_2d_shader = shader;
6782
6783     shader_buffer_free(&buffer);
6784     LEAVE_GL();
6785
6786     return shader;
6787 }
6788
6789 /* Context activation is done by the caller. */
6790 static void upload_palette(IWineD3DSurfaceImpl *surface)
6791 {
6792     BYTE table[256][4];
6793     IWineD3DDeviceImpl *device = surface->resource.device;
6794     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6795     struct arbfp_blit_priv *priv = device->blit_priv;
6796     BOOL colorkey = (surface->CKeyFlags & WINEDDSD_CKSRCBLT) ? TRUE : FALSE;
6797
6798     d3dfmt_p8_init_palette(surface, table, colorkey);
6799
6800     ENTER_GL();
6801     if (!priv->palette_texture)
6802         glGenTextures(1, &priv->palette_texture);
6803
6804     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE1));
6805     glBindTexture(GL_TEXTURE_1D, priv->palette_texture);
6806
6807     glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
6808
6809     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
6810     /* Make sure we have discrete color levels. */
6811     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
6812     glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
6813     /* Upload the palette */
6814     /* TODO: avoid unneeed uploads in the future by adding some SFLAG_PALETTE_DIRTY mechanism */
6815     glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, 256, 0, GL_RGBA, GL_UNSIGNED_BYTE, table);
6816
6817     /* Switch back to unit 0 in which the 2D texture will be stored. */
6818     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0));
6819     LEAVE_GL();
6820 }
6821
6822 /* Context activation is done by the caller. */
6823 static GLuint gen_yuv_shader(IWineD3DDeviceImpl *device, enum complex_fixup yuv_fixup, GLenum textype)
6824 {
6825     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6826     GLenum shader;
6827     struct wined3d_shader_buffer buffer;
6828     char luminance_component;
6829     struct arbfp_blit_priv *priv = device->blit_priv;
6830     GLint pos;
6831
6832     /* Shader header */
6833     if (!shader_buffer_init(&buffer))
6834     {
6835         ERR("Failed to initialize shader buffer.\n");
6836         return 0;
6837     }
6838
6839     ENTER_GL();
6840     GL_EXTCALL(glGenProgramsARB(1, &shader));
6841     checkGLcall("GL_EXTCALL(glGenProgramsARB(1, &shader))");
6842     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
6843     checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
6844     LEAVE_GL();
6845     if(!shader) {
6846         shader_buffer_free(&buffer);
6847         return 0;
6848     }
6849
6850     /* The YUY2 and UYVY formats contain two pixels packed into a 32 bit macropixel,
6851      * giving effectively 16 bit per pixel. The color consists of a luminance(Y) and
6852      * two chroma(U and V) values. Each macropixel has two luminance values, one for
6853      * each single pixel it contains, and one U and one V value shared between both
6854      * pixels.
6855      *
6856      * The data is loaded into an A8L8 texture. With YUY2, the luminance component
6857      * contains the luminance and alpha the chroma. With UYVY it is vice versa. Thus
6858      * take the format into account when generating the read swizzles
6859      *
6860      * Reading the Y value is straightforward - just sample the texture. The hardware
6861      * takes care of filtering in the horizontal and vertical direction.
6862      *
6863      * Reading the U and V values is harder. We have to avoid filtering horizontally,
6864      * because that would mix the U and V values of one pixel or two adjacent pixels.
6865      * Thus floor the texture coordinate and add 0.5 to get an unfiltered read,
6866      * regardless of the filtering setting. Vertical filtering works automatically
6867      * though - the U and V values of two rows are mixed nicely.
6868      *
6869      * Appart of avoiding filtering issues, the code has to know which value it just
6870      * read, and where it can find the other one. To determine this, it checks if
6871      * it sampled an even or odd pixel, and shifts the 2nd read accordingly.
6872      *
6873      * Handling horizontal filtering of U and V values requires reading a 2nd pair
6874      * of pixels, extracting U and V and mixing them. This is not implemented yet.
6875      *
6876      * An alternative implementation idea is to load the texture as A8R8G8B8 texture,
6877      * with width / 2. This way one read gives all 3 values, finding U and V is easy
6878      * in an unfiltered situation. Finding the luminance on the other hand requires
6879      * finding out if it is an odd or even pixel. The real drawback of this approach
6880      * is filtering. This would have to be emulated completely in the shader, reading
6881      * up two 2 packed pixels in up to 2 rows and interpolating both horizontally and
6882      * vertically. Beyond that it would require adjustments to the texture handling
6883      * code to deal with the width scaling
6884      */
6885     shader_addline(&buffer, "!!ARBfp1.0\n");
6886     shader_addline(&buffer, "TEMP luminance;\n");
6887     shader_addline(&buffer, "TEMP temp;\n");
6888     shader_addline(&buffer, "TEMP chroma;\n");
6889     shader_addline(&buffer, "TEMP texcrd;\n");
6890     shader_addline(&buffer, "TEMP texcrd2;\n");
6891     shader_addline(&buffer, "PARAM coef = {1.0, 0.5, 2.0, 0.25};\n");
6892     shader_addline(&buffer, "PARAM yuv_coef = {1.403, 0.344, 0.714, 1.770};\n");
6893     shader_addline(&buffer, "PARAM size = program.local[0];\n");
6894
6895     switch (yuv_fixup)
6896     {
6897         case COMPLEX_FIXUP_UYVY:
6898         case COMPLEX_FIXUP_YUY2:
6899             if (!gen_planar_yuv_read(&buffer, yuv_fixup, textype, &luminance_component))
6900             {
6901                 shader_buffer_free(&buffer);
6902                 return 0;
6903             }
6904             break;
6905
6906         case COMPLEX_FIXUP_YV12:
6907             if (!gen_yv12_read(&buffer, textype, &luminance_component))
6908             {
6909                 shader_buffer_free(&buffer);
6910                 return 0;
6911             }
6912             break;
6913
6914         default:
6915             FIXME("Unsupported YUV fixup %#x\n", yuv_fixup);
6916             shader_buffer_free(&buffer);
6917             return 0;
6918     }
6919
6920     /* Calculate the final result. Formula is taken from
6921      * http://www.fourcc.org/fccyvrgb.php. Note that the chroma
6922      * ranges from -0.5 to 0.5
6923      */
6924     shader_addline(&buffer, "SUB chroma.xy, chroma, coef.y;\n");
6925
6926     shader_addline(&buffer, "MAD result.color.x, chroma.x, yuv_coef.x, luminance.%c;\n", luminance_component);
6927     shader_addline(&buffer, "MAD temp.x, -chroma.y, yuv_coef.y, luminance.%c;\n", luminance_component);
6928     shader_addline(&buffer, "MAD result.color.y, -chroma.x, yuv_coef.z, temp.x;\n");
6929     shader_addline(&buffer, "MAD result.color.z, chroma.y, yuv_coef.w, luminance.%c;\n", luminance_component);
6930     shader_addline(&buffer, "END\n");
6931
6932     ENTER_GL();
6933     GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
6934             strlen(buffer.buffer), buffer.buffer));
6935     checkGLcall("glProgramStringARB()");
6936
6937     glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
6938     if (pos != -1)
6939     {
6940         FIXME("Fragment program error at position %d: %s\n\n", pos,
6941               debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
6942         shader_arb_dump_program_source(buffer.buffer);
6943     }
6944     else
6945     {
6946         GLint native;
6947
6948         GL_EXTCALL(glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &native));
6949         checkGLcall("glGetProgramivARB()");
6950         if (!native) WARN("Program exceeds native resource limits.\n");
6951     }
6952
6953     shader_buffer_free(&buffer);
6954     LEAVE_GL();
6955
6956     switch (yuv_fixup)
6957     {
6958         case COMPLEX_FIXUP_YUY2:
6959             if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yuy2_rect_shader = shader;
6960             else priv->yuy2_2d_shader = shader;
6961             break;
6962
6963         case COMPLEX_FIXUP_UYVY:
6964             if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->uyvy_rect_shader = shader;
6965             else priv->uyvy_2d_shader = shader;
6966             break;
6967
6968         case COMPLEX_FIXUP_YV12:
6969             if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yv12_rect_shader = shader;
6970             else priv->yv12_2d_shader = shader;
6971             break;
6972         default:
6973             ERR("Unsupported complex fixup: %d\n", yuv_fixup);
6974     }
6975
6976     return shader;
6977 }
6978
6979 /* Context activation is done by the caller. */
6980 static HRESULT arbfp_blit_set(IWineD3DDevice *iface, IWineD3DSurfaceImpl *surface)
6981 {
6982     GLenum shader;
6983     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface;
6984     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
6985     float size[4] = {(float) surface->pow2Width, (float) surface->pow2Height, 1.0f, 1.0f};
6986     struct arbfp_blit_priv *priv = device->blit_priv;
6987     enum complex_fixup fixup;
6988     GLenum textype = surface->texture_target;
6989
6990     if (!is_complex_fixup(surface->resource.format_desc->color_fixup))
6991     {
6992         TRACE("Fixup:\n");
6993         dump_color_fixup_desc(surface->resource.format_desc->color_fixup);
6994         /* Don't bother setting up a shader for unconverted formats */
6995         ENTER_GL();
6996         glEnable(textype);
6997         checkGLcall("glEnable(textype)");
6998         LEAVE_GL();
6999         return WINED3D_OK;
7000     }
7001
7002     fixup = get_complex_fixup(surface->resource.format_desc->color_fixup);
7003
7004     switch(fixup)
7005     {
7006         case COMPLEX_FIXUP_YUY2:
7007             shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yuy2_rect_shader : priv->yuy2_2d_shader;
7008             break;
7009
7010         case COMPLEX_FIXUP_UYVY:
7011             shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->uyvy_rect_shader : priv->uyvy_2d_shader;
7012             break;
7013
7014         case COMPLEX_FIXUP_YV12:
7015             shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yv12_rect_shader : priv->yv12_2d_shader;
7016             break;
7017
7018         case COMPLEX_FIXUP_P8:
7019             shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->p8_rect_shader : priv->p8_2d_shader;
7020             if (!shader) shader = gen_p8_shader(device, textype);
7021
7022             upload_palette(surface);
7023             break;
7024
7025         default:
7026             FIXME("Unsupported complex fixup %#x, not setting a shader\n", fixup);
7027             ENTER_GL();
7028             glEnable(textype);
7029             checkGLcall("glEnable(textype)");
7030             LEAVE_GL();
7031             return E_NOTIMPL;
7032     }
7033
7034     if (!shader) shader = gen_yuv_shader(device, fixup, textype);
7035
7036     ENTER_GL();
7037     glEnable(GL_FRAGMENT_PROGRAM_ARB);
7038     checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
7039     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
7040     checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
7041     GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, size));
7042     checkGLcall("glProgramLocalParameter4fvARB");
7043     LEAVE_GL();
7044
7045     return WINED3D_OK;
7046 }
7047
7048 /* Context activation is done by the caller. */
7049 static void arbfp_blit_unset(IWineD3DDevice *iface) {
7050     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) iface;
7051     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
7052
7053     ENTER_GL();
7054     glDisable(GL_FRAGMENT_PROGRAM_ARB);
7055     checkGLcall("glDisable(GL_FRAGMENT_PROGRAM_ARB)");
7056     glDisable(GL_TEXTURE_2D);
7057     checkGLcall("glDisable(GL_TEXTURE_2D)");
7058     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
7059     {
7060         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
7061         checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
7062     }
7063     if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
7064     {
7065         glDisable(GL_TEXTURE_RECTANGLE_ARB);
7066         checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
7067     }
7068     LEAVE_GL();
7069 }
7070
7071 static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum blit_operation blit_op,
7072                                  const RECT *src_rect, DWORD src_usage, WINED3DPOOL src_pool,
7073                                  const struct wined3d_format_desc *src_format_desc,
7074                                  const RECT *dst_rect, DWORD dst_usage, WINED3DPOOL dst_pool,
7075                                  const struct wined3d_format_desc *dst_format_desc)
7076 {
7077     enum complex_fixup src_fixup;
7078
7079     if (blit_op != BLIT_OP_BLIT)
7080     {
7081         TRACE("Unsupported blit_op=%d\n", blit_op);
7082         return FALSE;
7083     }
7084
7085     src_fixup = get_complex_fixup(src_format_desc->color_fixup);
7086     if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
7087     {
7088         TRACE("Checking support for fixup:\n");
7089         dump_color_fixup_desc(src_format_desc->color_fixup);
7090     }
7091
7092     if (!is_identity_fixup(dst_format_desc->color_fixup))
7093     {
7094         TRACE("Destination fixups are not supported\n");
7095         return FALSE;
7096     }
7097
7098     if (is_identity_fixup(src_format_desc->color_fixup))
7099     {
7100         TRACE("[OK]\n");
7101         return TRUE;
7102     }
7103
7104      /* We only support YUV conversions. */
7105     if (!is_complex_fixup(src_format_desc->color_fixup))
7106     {
7107         TRACE("[FAILED]\n");
7108         return FALSE;
7109     }
7110
7111     switch(src_fixup)
7112     {
7113         case COMPLEX_FIXUP_YUY2:
7114         case COMPLEX_FIXUP_UYVY:
7115         case COMPLEX_FIXUP_YV12:
7116         case COMPLEX_FIXUP_P8:
7117             TRACE("[OK]\n");
7118             return TRUE;
7119
7120         default:
7121             FIXME("Unsupported YUV fixup %#x\n", src_fixup);
7122             TRACE("[FAILED]\n");
7123             return FALSE;
7124     }
7125 }
7126
7127 HRESULT arbfp_blit_surface(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *src_surface, const RECT *src_rect,
7128                            IWineD3DSurfaceImpl *dst_surface, const RECT *dst_rect_in, enum blit_operation blit_op,
7129                            DWORD Filter)
7130 {
7131     IWineD3DSwapChainImpl *dst_swapchain;
7132     struct wined3d_context *context;
7133     RECT dst_rect = *dst_rect_in;
7134
7135     /* Now load the surface */
7136     surface_internal_preload(src_surface, SRGB_RGB);
7137
7138     /* Activate the destination context, set it up for blitting */
7139     context = context_acquire(device, dst_surface);
7140     context_apply_blit_state(context, device);
7141
7142     /* The coordinates of the ddraw front buffer are always fullscreen ('screen coordinates',
7143      * while OpenGL coordinates are window relative.
7144      * Also beware of the origin difference(top left vs bottom left).
7145      * Also beware that the front buffer's surface size is screen width x screen height,
7146      * whereas the real gl drawable size is the size of the window. */
7147     dst_swapchain = dst_surface->container.type == WINED3D_CONTAINER_SWAPCHAIN
7148             ? dst_surface->container.u.swapchain : NULL;
7149     if (dst_swapchain && dst_surface == dst_swapchain->front_buffer)
7150         surface_translate_frontbuffer_coords(dst_surface, context->win_handle, &dst_rect);
7151
7152     arbfp_blit_set((IWineD3DDevice *)device, src_surface);
7153
7154     ENTER_GL();
7155
7156     /* Draw a textured quad */
7157     draw_textured_quad(src_surface, src_rect, &dst_rect, Filter);
7158
7159     LEAVE_GL();
7160
7161     /* Leave the opengl state valid for blitting */
7162     arbfp_blit_unset((IWineD3DDevice *)device);
7163
7164     if (wined3d_settings.strict_draw_ordering || (dst_swapchain
7165             && (dst_surface == dst_swapchain->front_buffer
7166             || dst_swapchain->num_contexts > 1)))
7167         wglFlush(); /* Flush to ensure ordering across contexts. */
7168
7169     context_release(context);
7170
7171     surface_modify_location(dst_surface, SFLAG_INDRAWABLE, TRUE);
7172     return WINED3D_OK;
7173 }
7174
7175 static HRESULT arbfp_blit_color_fill(IWineD3DDeviceImpl *device, IWineD3DSurfaceImpl *dst_surface,
7176         const RECT *dst_rect, const WINED3DCOLORVALUE *color)
7177 {
7178     FIXME("Color filling not implemented by arbfp_blit\n");
7179     return WINED3DERR_INVALIDCALL;
7180 }
7181
7182 const struct blit_shader arbfp_blit = {
7183     arbfp_blit_alloc,
7184     arbfp_blit_free,
7185     arbfp_blit_set,
7186     arbfp_blit_unset,
7187     arbfp_blit_supported,
7188     arbfp_blit_color_fill
7189 };