wined3d: Introduce a separate structure for stateblock states.
[wine] / dlls / wined3d / shader.c
1 /*
2  * Copyright 2002-2003 Jason Edmeades
3  * Copyright 2002-2003 Raphael Junqueira
4  * Copyright 2004 Christian Costa
5  * Copyright 2005 Oliver Stieber
6  * Copyright 2006 Ivan Gyurdiev
7  * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
8  * Copyright 2009 Henri Verbeet for CodeWeavers
9  *
10  * This library is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This library is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24
25 #include "config.h"
26
27 #include <math.h>
28 #include <stdio.h>
29 #include <string.h>
30
31 #include "wined3d_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
34 WINE_DECLARE_DEBUG_CHANNEL(d3d);
35
36 static const char * const shader_opcode_names[] =
37 {
38     /* WINED3DSIH_ABS           */ "abs",
39     /* WINED3DSIH_ADD           */ "add",
40     /* WINED3DSIH_BEM           */ "bem",
41     /* WINED3DSIH_BREAK         */ "break",
42     /* WINED3DSIH_BREAKC        */ "breakc",
43     /* WINED3DSIH_BREAKP        */ "breakp",
44     /* WINED3DSIH_CALL          */ "call",
45     /* WINED3DSIH_CALLNZ        */ "callnz",
46     /* WINED3DSIH_CMP           */ "cmp",
47     /* WINED3DSIH_CND           */ "cnd",
48     /* WINED3DSIH_CRS           */ "crs",
49     /* WINED3DSIH_CUT           */ "cut",
50     /* WINED3DSIH_DCL           */ "dcl",
51     /* WINED3DSIH_DEF           */ "def",
52     /* WINED3DSIH_DEFB          */ "defb",
53     /* WINED3DSIH_DEFI          */ "defi",
54     /* WINED3DSIH_DP2ADD        */ "dp2add",
55     /* WINED3DSIH_DP3           */ "dp3",
56     /* WINED3DSIH_DP4           */ "dp4",
57     /* WINED3DSIH_DST           */ "dst",
58     /* WINED3DSIH_DSX           */ "dsx",
59     /* WINED3DSIH_DSY           */ "dsy",
60     /* WINED3DSIH_ELSE          */ "else",
61     /* WINED3DSIH_EMIT          */ "emit",
62     /* WINED3DSIH_ENDIF         */ "endif",
63     /* WINED3DSIH_ENDLOOP       */ "endloop",
64     /* WINED3DSIH_ENDREP        */ "endrep",
65     /* WINED3DSIH_EXP           */ "exp",
66     /* WINED3DSIH_EXPP          */ "expp",
67     /* WINED3DSIH_FRC           */ "frc",
68     /* WINED3DSIH_IADD          */ "iadd",
69     /* WINED3DSIH_IF            */ "if",
70     /* WINED3DSIH_IFC           */ "ifc",
71     /* WINED3DSIH_IGE           */ "ige",
72     /* WINED3DSIH_LABEL         */ "label",
73     /* WINED3DSIH_LIT           */ "lit",
74     /* WINED3DSIH_LOG           */ "log",
75     /* WINED3DSIH_LOGP          */ "logp",
76     /* WINED3DSIH_LOOP          */ "loop",
77     /* WINED3DSIH_LRP           */ "lrp",
78     /* WINED3DSIH_LT            */ "lt",
79     /* WINED3DSIH_M3x2          */ "m3x2",
80     /* WINED3DSIH_M3x3          */ "m3x3",
81     /* WINED3DSIH_M3x4          */ "m3x4",
82     /* WINED3DSIH_M4x3          */ "m4x3",
83     /* WINED3DSIH_M4x4          */ "m4x4",
84     /* WINED3DSIH_MAD           */ "mad",
85     /* WINED3DSIH_MAX           */ "max",
86     /* WINED3DSIH_MIN           */ "min",
87     /* WINED3DSIH_MOV           */ "mov",
88     /* WINED3DSIH_MOVA          */ "mova",
89     /* WINED3DSIH_MUL           */ "mul",
90     /* WINED3DSIH_NOP           */ "nop",
91     /* WINED3DSIH_NRM           */ "nrm",
92     /* WINED3DSIH_PHASE         */ "phase",
93     /* WINED3DSIH_POW           */ "pow",
94     /* WINED3DSIH_RCP           */ "rcp",
95     /* WINED3DSIH_REP           */ "rep",
96     /* WINED3DSIH_RET           */ "ret",
97     /* WINED3DSIH_RSQ           */ "rsq",
98     /* WINED3DSIH_SETP          */ "setp",
99     /* WINED3DSIH_SGE           */ "sge",
100     /* WINED3DSIH_SGN           */ "sgn",
101     /* WINED3DSIH_SINCOS        */ "sincos",
102     /* WINED3DSIH_SLT           */ "slt",
103     /* WINED3DSIH_SUB           */ "sub",
104     /* WINED3DSIH_TEX           */ "texld",
105     /* WINED3DSIH_TEXBEM        */ "texbem",
106     /* WINED3DSIH_TEXBEML       */ "texbeml",
107     /* WINED3DSIH_TEXCOORD      */ "texcrd",
108     /* WINED3DSIH_TEXDEPTH      */ "texdepth",
109     /* WINED3DSIH_TEXDP3        */ "texdp3",
110     /* WINED3DSIH_TEXDP3TEX     */ "texdp3tex",
111     /* WINED3DSIH_TEXKILL       */ "texkill",
112     /* WINED3DSIH_TEXLDD        */ "texldd",
113     /* WINED3DSIH_TEXLDL        */ "texldl",
114     /* WINED3DSIH_TEXM3x2DEPTH  */ "texm3x2depth",
115     /* WINED3DSIH_TEXM3x2PAD    */ "texm3x2pad",
116     /* WINED3DSIH_TEXM3x2TEX    */ "texm3x2tex",
117     /* WINED3DSIH_TEXM3x3       */ "texm3x3",
118     /* WINED3DSIH_TEXM3x3DIFF   */ "texm3x3diff",
119     /* WINED3DSIH_TEXM3x3PAD    */ "texm3x3pad",
120     /* WINED3DSIH_TEXM3x3SPEC   */ "texm3x3spec",
121     /* WINED3DSIH_TEXM3x3TEX    */ "texm3x3tex",
122     /* WINED3DSIH_TEXM3x3VSPEC  */ "texm3x3vspec",
123     /* WINED3DSIH_TEXREG2AR     */ "texreg2ar",
124     /* WINED3DSIH_TEXREG2GB     */ "texreg2gb",
125     /* WINED3DSIH_TEXREG2RGB    */ "texreg2rgb",
126 };
127
128 static const char * const semantic_names[] =
129 {
130     /* WINED3DDECLUSAGE_POSITION        */ "SV_POSITION",
131     /* WINED3DDECLUSAGE_BLENDWEIGHT     */ "BLENDWEIGHT",
132     /* WINED3DDECLUSAGE_BLENDINDICES    */ "BLENDINDICES",
133     /* WINED3DDECLUSAGE_NORMAL          */ "NORMAL",
134     /* WINED3DDECLUSAGE_PSIZE           */ "PSIZE",
135     /* WINED3DDECLUSAGE_TEXCOORD        */ "TEXCOORD",
136     /* WINED3DDECLUSAGE_TANGENT         */ "TANGENT",
137     /* WINED3DDECLUSAGE_BINORMAL        */ "BINORMAL",
138     /* WINED3DDECLUSAGE_TESSFACTOR      */ "TESSFACTOR",
139     /* WINED3DDECLUSAGE_POSITIONT       */ "POSITIONT",
140     /* WINED3DDECLUSAGE_COLOR           */ "COLOR",
141     /* WINED3DDECLUSAGE_FOG             */ "FOG",
142     /* WINED3DDECLUSAGE_DEPTH           */ "DEPTH",
143     /* WINED3DDECLUSAGE_SAMPLE          */ "SAMPLE",
144 };
145
146 static const char *shader_semantic_name_from_usage(WINED3DDECLUSAGE usage)
147 {
148     if (usage >= sizeof(semantic_names) / sizeof(*semantic_names))
149     {
150         FIXME("Unrecognized usage %#x.\n", usage);
151         return "UNRECOGNIZED";
152     }
153
154     return semantic_names[usage];
155 }
156
157 static WINED3DDECLUSAGE shader_usage_from_semantic_name(const char *name)
158 {
159     unsigned int i;
160
161     for (i = 0; i < sizeof(semantic_names) / sizeof(*semantic_names); ++i)
162     {
163         if (!strcmp(name, semantic_names[i])) return i;
164     }
165
166     return ~0U;
167 }
168
169 BOOL shader_match_semantic(const char *semantic_name, WINED3DDECLUSAGE usage)
170 {
171     return !strcmp(semantic_name, shader_semantic_name_from_usage(usage));
172 }
173
174 static void shader_signature_from_semantic(struct wined3d_shader_signature_element *e,
175         const struct wined3d_shader_semantic *s)
176 {
177     e->semantic_name = shader_semantic_name_from_usage(s->usage);
178     e->semantic_idx = s->usage_idx;
179     e->sysval_semantic = 0;
180     e->component_type = 0;
181     e->register_idx = s->reg.reg.idx;
182     e->mask = s->reg.write_mask;
183 }
184
185 static void shader_signature_from_usage(struct wined3d_shader_signature_element *e,
186         WINED3DDECLUSAGE usage, UINT usage_idx, UINT reg_idx, DWORD write_mask)
187 {
188     e->semantic_name = shader_semantic_name_from_usage(usage);
189     e->semantic_idx = usage_idx;
190     e->sysval_semantic = 0;
191     e->component_type = 0;
192     e->register_idx = reg_idx;
193     e->mask = write_mask;
194 }
195
196 static const struct wined3d_shader_frontend *shader_select_frontend(DWORD version_token)
197 {
198     switch (version_token >> 16)
199     {
200         case WINED3D_SM1_VS:
201         case WINED3D_SM1_PS:
202             return &sm1_shader_frontend;
203
204         case WINED3D_SM4_PS:
205         case WINED3D_SM4_VS:
206         case WINED3D_SM4_GS:
207             return &sm4_shader_frontend;
208
209         default:
210             FIXME("Unrecognised version token %#x\n", version_token);
211             return NULL;
212     }
213 }
214
215 void shader_buffer_clear(struct wined3d_shader_buffer *buffer)
216 {
217     buffer->buffer[0] = '\0';
218     buffer->bsize = 0;
219     buffer->lineNo = 0;
220     buffer->newline = TRUE;
221 }
222
223 BOOL shader_buffer_init(struct wined3d_shader_buffer *buffer)
224 {
225     buffer->buffer = HeapAlloc(GetProcessHeap(), 0, SHADER_PGMSIZE);
226     if (!buffer->buffer)
227     {
228         ERR("Failed to allocate shader buffer memory.\n");
229         return FALSE;
230     }
231
232     shader_buffer_clear(buffer);
233     return TRUE;
234 }
235
236 void shader_buffer_free(struct wined3d_shader_buffer *buffer)
237 {
238     HeapFree(GetProcessHeap(), 0, buffer->buffer);
239 }
240
241 int shader_vaddline(struct wined3d_shader_buffer *buffer, const char *format, va_list args)
242 {
243     char *base = buffer->buffer + buffer->bsize;
244     int rc;
245
246     rc = vsnprintf(base, SHADER_PGMSIZE - 1 - buffer->bsize, format, args);
247
248     if (rc < 0 /* C89 */ || (unsigned int)rc > SHADER_PGMSIZE - 1 - buffer->bsize /* C99 */)
249     {
250         ERR("The buffer allocated for the shader program string "
251             "is too small at %d bytes.\n", SHADER_PGMSIZE);
252         buffer->bsize = SHADER_PGMSIZE - 1;
253         return -1;
254     }
255
256     if (buffer->newline)
257     {
258         TRACE("GL HW (%u, %u) : %s", buffer->lineNo + 1, buffer->bsize, base);
259         buffer->newline = FALSE;
260     }
261     else
262     {
263         TRACE("%s", base);
264     }
265
266     buffer->bsize += rc;
267     if (buffer->buffer[buffer->bsize-1] == '\n')
268     {
269         ++buffer->lineNo;
270         buffer->newline = TRUE;
271     }
272
273     return 0;
274 }
275
276 int shader_addline(struct wined3d_shader_buffer *buffer, const char *format, ...)
277 {
278     va_list args;
279     int ret;
280
281     va_start(args, format);
282     ret = shader_vaddline(buffer, format, args);
283     va_end(args);
284
285     return ret;
286 }
287
288 static void shader_init(struct IWineD3DBaseShaderClass *shader, IWineD3DDeviceImpl *device,
289         void *parent, const struct wined3d_parent_ops *parent_ops)
290 {
291     shader->ref = 1;
292     shader->device = (IWineD3DDevice *)device;
293     shader->parent = parent;
294     shader->parent_ops = parent_ops;
295     list_init(&shader->linked_programs);
296     list_add_head(&device->shaders, &shader->shader_list_entry);
297 }
298
299 /* Convert floating point offset relative to a register file to an absolute
300  * offset for float constants. */
301 static unsigned int shader_get_float_offset(WINED3DSHADER_PARAM_REGISTER_TYPE register_type, UINT register_idx)
302 {
303     switch (register_type)
304     {
305         case WINED3DSPR_CONST: return register_idx;
306         case WINED3DSPR_CONST2: return 2048 + register_idx;
307         case WINED3DSPR_CONST3: return 4096 + register_idx;
308         case WINED3DSPR_CONST4: return 6144 + register_idx;
309         default:
310             FIXME("Unsupported register type: %u.\n", register_type);
311             return register_idx;
312     }
313 }
314
315 static void shader_delete_constant_list(struct list *clist)
316 {
317     struct local_constant *constant;
318     struct list *ptr;
319
320     ptr = list_head(clist);
321     while (ptr)
322     {
323         constant = LIST_ENTRY(ptr, struct local_constant, entry);
324         ptr = list_next(clist, ptr);
325         HeapFree(GetProcessHeap(), 0, constant);
326     }
327     list_init(clist);
328 }
329
330 static inline void set_bitmap_bit(DWORD *bitmap, DWORD bit)
331 {
332     DWORD idx, shift;
333     idx = bit >> 5;
334     shift = bit & 0x1f;
335     bitmap[idx] |= (1 << shift);
336 }
337
338 static void shader_record_register_usage(IWineD3DBaseShaderImpl *shader, struct shader_reg_maps *reg_maps,
339         const struct wined3d_shader_register *reg, enum wined3d_shader_type shader_type)
340 {
341     switch (reg->type)
342     {
343         case WINED3DSPR_TEXTURE: /* WINED3DSPR_ADDR */
344             if (shader_type == WINED3D_SHADER_TYPE_PIXEL) reg_maps->texcoord |= 1 << reg->idx;
345             else reg_maps->address |= 1 << reg->idx;
346             break;
347
348         case WINED3DSPR_TEMP:
349             reg_maps->temporary |= 1 << reg->idx;
350             break;
351
352         case WINED3DSPR_INPUT:
353             if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
354             {
355                 if (reg->rel_addr)
356                 {
357                     /* If relative addressing is used, we must assume that all registers
358                      * are used. Even if it is a construct like v3[aL], we can't assume
359                      * that v0, v1 and v2 aren't read because aL can be negative */
360                     unsigned int i;
361                     for (i = 0; i < MAX_REG_INPUT; ++i)
362                     {
363                         ((IWineD3DPixelShaderImpl *)shader)->input_reg_used[i] = TRUE;
364                     }
365                 }
366                 else
367                 {
368                     ((IWineD3DPixelShaderImpl *)shader)->input_reg_used[reg->idx] = TRUE;
369                 }
370             }
371             else reg_maps->input_registers |= 1 << reg->idx;
372             break;
373
374         case WINED3DSPR_RASTOUT:
375             if (reg->idx == 1) reg_maps->fog = 1;
376             break;
377
378         case WINED3DSPR_MISCTYPE:
379             if (shader_type == WINED3D_SHADER_TYPE_PIXEL)
380             {
381                 if (!reg->idx) reg_maps->vpos = 1;
382                 else if (reg->idx == 1) reg_maps->usesfacing = 1;
383             }
384             break;
385
386         case WINED3DSPR_CONST:
387             if (reg->rel_addr)
388             {
389                 if (shader_type != WINED3D_SHADER_TYPE_PIXEL)
390                 {
391                     if (reg->idx < ((IWineD3DVertexShaderImpl *)shader)->min_rel_offset)
392                     {
393                         ((IWineD3DVertexShaderImpl *)shader)->min_rel_offset = reg->idx;
394                     }
395                     if (reg->idx > ((IWineD3DVertexShaderImpl *)shader)->max_rel_offset)
396                     {
397                         ((IWineD3DVertexShaderImpl *)shader)->max_rel_offset = reg->idx;
398                     }
399                 }
400                 reg_maps->usesrelconstF = TRUE;
401             }
402             else
403             {
404                 set_bitmap_bit(reg_maps->constf, reg->idx);
405             }
406             break;
407
408         case WINED3DSPR_CONSTINT:
409             reg_maps->integer_constants |= (1 << reg->idx);
410             break;
411
412         case WINED3DSPR_CONSTBOOL:
413             reg_maps->boolean_constants |= (1 << reg->idx);
414             break;
415
416         case WINED3DSPR_COLOROUT:
417             reg_maps->highest_render_target = max(reg_maps->highest_render_target, reg->idx);
418             break;
419
420         default:
421             TRACE("Not recording register of type %#x and idx %u\n", reg->type, reg->idx);
422             break;
423     }
424 }
425
426 static unsigned int get_instr_extra_regcount(enum WINED3D_SHADER_INSTRUCTION_HANDLER instr, unsigned int param)
427 {
428     switch (instr)
429     {
430         case WINED3DSIH_M4x4:
431         case WINED3DSIH_M3x4:
432             return param == 1 ? 3 : 0;
433
434         case WINED3DSIH_M4x3:
435         case WINED3DSIH_M3x3:
436             return param == 1 ? 2 : 0;
437
438         case WINED3DSIH_M3x2:
439             return param == 1 ? 1 : 0;
440
441         default:
442             return 0;
443     }
444 }
445
446 /* Note that this does not count the loop register as an address register. */
447 static HRESULT shader_get_registers_used(IWineD3DBaseShader *iface, const struct wined3d_shader_frontend *fe,
448         struct shader_reg_maps *reg_maps, struct wined3d_shader_signature_element *input_signature,
449         struct wined3d_shader_signature_element *output_signature, const DWORD *byte_code, DWORD constf_size)
450 {
451     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface;
452     unsigned int cur_loop_depth = 0, max_loop_depth = 0;
453     void *fe_data = shader->baseShader.frontend_data;
454     struct wined3d_shader_version shader_version;
455     const DWORD *ptr = byte_code;
456
457     memset(reg_maps, 0, sizeof(*reg_maps));
458
459     /* get_registers_used() is called on every compile on some 1.x shaders,
460      * which can result in stacking up a collection of local constants.
461      * Delete the old constants if existing. */
462     shader_delete_constant_list(&shader->baseShader.constantsF);
463     shader_delete_constant_list(&shader->baseShader.constantsB);
464     shader_delete_constant_list(&shader->baseShader.constantsI);
465
466     fe->shader_read_header(fe_data, &ptr, &shader_version);
467     reg_maps->shader_version = shader_version;
468
469     reg_maps->constf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
470             sizeof(*reg_maps->constf) * ((constf_size + 31) / 32));
471     if (!reg_maps->constf)
472     {
473         ERR("Failed to allocate constant map memory.\n");
474         return E_OUTOFMEMORY;
475     }
476
477     while (!fe->shader_is_end(fe_data, &ptr))
478     {
479         struct wined3d_shader_instruction ins;
480         const char *comment;
481         UINT comment_size;
482         UINT param_size;
483
484         /* Skip comments. */
485         fe->shader_read_comment(&ptr, &comment, &comment_size);
486         if (comment) continue;
487
488         /* Fetch opcode. */
489         fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
490
491         /* Unhandled opcode, and its parameters. */
492         if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
493         {
494             TRACE("Skipping unrecognized instruction.\n");
495             ptr += param_size;
496             continue;
497         }
498
499         /* Handle declarations. */
500         if (ins.handler_idx == WINED3DSIH_DCL)
501         {
502             struct wined3d_shader_semantic semantic;
503
504             fe->shader_read_semantic(&ptr, &semantic);
505
506             switch (semantic.reg.reg.type)
507             {
508                 /* Mark input registers used. */
509                 case WINED3DSPR_INPUT:
510                     reg_maps->input_registers |= 1 << semantic.reg.reg.idx;
511                     shader_signature_from_semantic(&input_signature[semantic.reg.reg.idx], &semantic);
512                     break;
513
514                 /* Vertex shader: mark 3.0 output registers used, save token. */
515                 case WINED3DSPR_OUTPUT:
516                     reg_maps->output_registers |= 1 << semantic.reg.reg.idx;
517                     shader_signature_from_semantic(&output_signature[semantic.reg.reg.idx], &semantic);
518                     if (semantic.usage == WINED3DDECLUSAGE_FOG) reg_maps->fog = 1;
519                     break;
520
521                 /* Save sampler usage token. */
522                 case WINED3DSPR_SAMPLER:
523                     reg_maps->sampler_type[semantic.reg.reg.idx] = semantic.sampler_type;
524                     break;
525
526                 default:
527                     TRACE("Not recording DCL register type %#x.\n", semantic.reg.reg.type);
528                     break;
529             }
530         }
531         else if (ins.handler_idx == WINED3DSIH_DEF)
532         {
533             struct wined3d_shader_src_param rel_addr;
534             struct wined3d_shader_dst_param dst;
535
536             local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
537             if (!lconst) return E_OUTOFMEMORY;
538
539             fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
540             lconst->idx = dst.reg.idx;
541
542             memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
543             ptr += 4;
544
545             /* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
546             if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
547             {
548                 float *value = (float *)lconst->value;
549                 if (value[0] < -1.0f) value[0] = -1.0f;
550                 else if (value[0] > 1.0f) value[0] = 1.0f;
551                 if (value[1] < -1.0f) value[1] = -1.0f;
552                 else if (value[1] > 1.0f) value[1] = 1.0f;
553                 if (value[2] < -1.0f) value[2] = -1.0f;
554                 else if (value[2] > 1.0f) value[2] = 1.0f;
555                 if (value[3] < -1.0f) value[3] = -1.0f;
556                 else if (value[3] > 1.0f) value[3] = 1.0f;
557             }
558
559             list_add_head(&shader->baseShader.constantsF, &lconst->entry);
560         }
561         else if (ins.handler_idx == WINED3DSIH_DEFI)
562         {
563             struct wined3d_shader_src_param rel_addr;
564             struct wined3d_shader_dst_param dst;
565
566             local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
567             if (!lconst) return E_OUTOFMEMORY;
568
569             fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
570             lconst->idx = dst.reg.idx;
571
572             memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
573             ptr += 4;
574
575             list_add_head(&shader->baseShader.constantsI, &lconst->entry);
576             reg_maps->local_int_consts |= (1 << dst.reg.idx);
577         }
578         else if (ins.handler_idx == WINED3DSIH_DEFB)
579         {
580             struct wined3d_shader_src_param rel_addr;
581             struct wined3d_shader_dst_param dst;
582
583             local_constant *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
584             if (!lconst) return E_OUTOFMEMORY;
585
586             fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
587             lconst->idx = dst.reg.idx;
588
589             memcpy(lconst->value, ptr, sizeof(DWORD));
590             ++ptr;
591
592             list_add_head(&shader->baseShader.constantsB, &lconst->entry);
593             reg_maps->local_bool_consts |= (1 << dst.reg.idx);
594         }
595         /* If there's a loop in the shader. */
596         else if (ins.handler_idx == WINED3DSIH_LOOP
597                 || ins.handler_idx == WINED3DSIH_REP)
598         {
599             struct wined3d_shader_src_param src, rel_addr;
600
601             fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
602
603             /* Rep and Loop always use an integer constant for the control parameters. */
604             if (ins.handler_idx == WINED3DSIH_REP)
605             {
606                 reg_maps->integer_constants |= 1 << src.reg.idx;
607             }
608             else
609             {
610                 fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
611                 reg_maps->integer_constants |= 1 << src.reg.idx;
612             }
613
614             cur_loop_depth++;
615             if (cur_loop_depth > max_loop_depth) max_loop_depth = cur_loop_depth;
616         }
617         else if (ins.handler_idx == WINED3DSIH_ENDLOOP
618                 || ins.handler_idx == WINED3DSIH_ENDREP)
619         {
620             cur_loop_depth--;
621         }
622         /* For subroutine prototypes. */
623         else if (ins.handler_idx == WINED3DSIH_LABEL)
624         {
625             struct wined3d_shader_src_param src, rel_addr;
626
627             fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
628             reg_maps->labels |= 1 << src.reg.idx;
629         }
630         /* Set texture, address, temporary registers. */
631         else
632         {
633             BOOL color0_mov = FALSE;
634             int i, limit;
635
636             /* This will loop over all the registers and try to
637              * make a bitmask of the ones we're interested in.
638              *
639              * Relative addressing tokens are ignored, but that's
640              * okay, since we'll catch any address registers when
641              * they are initialized (required by spec). */
642             if (ins.dst_count)
643             {
644                 struct wined3d_shader_src_param dst_rel_addr;
645                 struct wined3d_shader_dst_param dst_param;
646
647                 fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
648
649                 shader_record_register_usage(shader, reg_maps, &dst_param.reg, shader_version.type);
650
651                 /* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
652                  * is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
653                  * shaders because TECRDOUT isn't used in them, but future register types might cause issues */
654                 if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3)
655                 {
656                     UINT idx = dst_param.reg.idx;
657
658                     switch (dst_param.reg.type)
659                     {
660                         case WINED3DSPR_RASTOUT:
661                             switch (idx)
662                             {
663                                 case 0: /* oPos */
664                                     reg_maps->output_registers |= 1 << 10;
665                                     shader_signature_from_usage(&output_signature[10],
666                                             WINED3DDECLUSAGE_POSITION, 0, 10, WINED3DSP_WRITEMASK_ALL);
667                                     break;
668
669                                 case 1: /* oFog */
670                                     reg_maps->output_registers |= 1 << 11;
671                                     shader_signature_from_usage(&output_signature[11],
672                                             WINED3DDECLUSAGE_FOG, 0, 11, WINED3DSP_WRITEMASK_0);
673                                     break;
674
675                                 case 2: /* oPts */
676                                     reg_maps->output_registers |= 1 << 11;
677                                     shader_signature_from_usage(&output_signature[11],
678                                             WINED3DDECLUSAGE_PSIZE, 0, 11, WINED3DSP_WRITEMASK_1);
679                                     break;
680                             }
681                             break;
682
683                         case WINED3DSPR_ATTROUT:
684                             if (idx < 2)
685                             {
686                                 idx += 8;
687                                 if (reg_maps->output_registers & (1 << idx))
688                                 {
689                                     output_signature[idx].mask |= dst_param.write_mask;
690                                 }
691                                 else
692                                 {
693                                     reg_maps->output_registers |= 1 << idx;
694                                     shader_signature_from_usage(&output_signature[idx],
695                                             WINED3DDECLUSAGE_COLOR, idx - 8, idx, dst_param.write_mask);
696                                 }
697                             }
698                             break;
699
700                         case WINED3DSPR_TEXCRDOUT:
701
702                             reg_maps->texcoord_mask[idx] |= dst_param.write_mask;
703                             if (reg_maps->output_registers & (1 << idx))
704                             {
705                                 output_signature[idx].mask |= dst_param.write_mask;
706                             }
707                             else
708                             {
709                                 reg_maps->output_registers |= 1 << idx;
710                                 shader_signature_from_usage(&output_signature[idx],
711                                         WINED3DDECLUSAGE_TEXCOORD, idx, idx, dst_param.write_mask);
712                             }
713                             break;
714
715                         default:
716                             break;
717                     }
718                 }
719
720                 if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
721                 {
722                     IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)shader;
723
724                     if (dst_param.reg.type == WINED3DSPR_COLOROUT && !dst_param.reg.idx)
725                     {
726                     /* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to
727                      * COLOROUT 0. If we know this in advance, the ARB shader backend can skip
728                      * the mov and perform the sRGB write correction from the source register.
729                      *
730                      * However, if the mov is only partial, we can't do this, and if the write
731                      * comes from an instruction other than MOV it is hard to do as well. If
732                      * COLOROUT 0 is overwritten partially later, the marker is dropped again. */
733
734                         ps->color0_mov = FALSE;
735                         if (ins.handler_idx == WINED3DSIH_MOV
736                                 && dst_param.write_mask == WINED3DSP_WRITEMASK_ALL)
737                         {
738                             /* Used later when the source register is read. */
739                             color0_mov = TRUE;
740                         }
741                     }
742                     /* Also drop the MOV marker if the source register is overwritten prior to the shader
743                      * end
744                      */
745                     else if (dst_param.reg.type == WINED3DSPR_TEMP && dst_param.reg.idx == ps->color0_reg)
746                     {
747                         ps->color0_mov = FALSE;
748                     }
749                 }
750
751                 /* Declare 1.x samplers implicitly, based on the destination reg. number. */
752                 if (shader_version.major == 1
753                         && (ins.handler_idx == WINED3DSIH_TEX
754                             || ins.handler_idx == WINED3DSIH_TEXBEM
755                             || ins.handler_idx == WINED3DSIH_TEXBEML
756                             || ins.handler_idx == WINED3DSIH_TEXDP3TEX
757                             || ins.handler_idx == WINED3DSIH_TEXM3x2TEX
758                             || ins.handler_idx == WINED3DSIH_TEXM3x3SPEC
759                             || ins.handler_idx == WINED3DSIH_TEXM3x3TEX
760                             || ins.handler_idx == WINED3DSIH_TEXM3x3VSPEC
761                             || ins.handler_idx == WINED3DSIH_TEXREG2AR
762                             || ins.handler_idx == WINED3DSIH_TEXREG2GB
763                             || ins.handler_idx == WINED3DSIH_TEXREG2RGB))
764                 {
765                     /* Fake sampler usage, only set reserved bit and type. */
766                     DWORD sampler_code = dst_param.reg.idx;
767
768                     TRACE("Setting fake 2D sampler for 1.x pixelshader.\n");
769                     reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D;
770
771                     /* texbem is only valid with < 1.4 pixel shaders */
772                     if (ins.handler_idx == WINED3DSIH_TEXBEM
773                             || ins.handler_idx == WINED3DSIH_TEXBEML)
774                     {
775                         reg_maps->bumpmat |= 1 << dst_param.reg.idx;
776                         if (ins.handler_idx == WINED3DSIH_TEXBEML)
777                         {
778                             reg_maps->luminanceparams |= 1 << dst_param.reg.idx;
779                         }
780                     }
781                 }
782                 else if (ins.handler_idx == WINED3DSIH_BEM)
783                 {
784                     reg_maps->bumpmat |= 1 << dst_param.reg.idx;
785                 }
786             }
787
788             if (ins.handler_idx == WINED3DSIH_NRM) reg_maps->usesnrm = 1;
789             else if (ins.handler_idx == WINED3DSIH_DSY) reg_maps->usesdsy = 1;
790             else if (ins.handler_idx == WINED3DSIH_DSX) reg_maps->usesdsx = 1;
791             else if (ins.handler_idx == WINED3DSIH_TEXLDD) reg_maps->usestexldd = 1;
792             else if (ins.handler_idx == WINED3DSIH_TEXLDL) reg_maps->usestexldl = 1;
793             else if (ins.handler_idx == WINED3DSIH_MOVA) reg_maps->usesmova = 1;
794             else if (ins.handler_idx == WINED3DSIH_IFC) reg_maps->usesifc = 1;
795             else if (ins.handler_idx == WINED3DSIH_CALL) reg_maps->usescall = 1;
796             else if (ins.handler_idx == WINED3DSIH_RCP) reg_maps->usesrcp = 1;
797
798             limit = ins.src_count + (ins.predicate ? 1 : 0);
799             for (i = 0; i < limit; ++i)
800             {
801                 struct wined3d_shader_src_param src_param, src_rel_addr;
802                 unsigned int count;
803
804                 fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
805                 count = get_instr_extra_regcount(ins.handler_idx, i);
806
807                 shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
808                 while (count)
809                 {
810                     ++src_param.reg.idx;
811                     shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
812                     --count;
813                 }
814
815                 if (color0_mov)
816                 {
817                     IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *)shader;
818                     if (src_param.reg.type == WINED3DSPR_TEMP
819                             && src_param.swizzle == WINED3DSP_NOSWIZZLE)
820                     {
821                         ps->color0_mov = TRUE;
822                         ps->color0_reg = src_param.reg.idx;
823                     }
824                 }
825             }
826         }
827     }
828     reg_maps->loop_depth = max_loop_depth;
829
830     shader->baseShader.functionLength = ((const char *)ptr - (const char *)byte_code);
831
832     return WINED3D_OK;
833 }
834
835 unsigned int shader_find_free_input_register(const struct shader_reg_maps *reg_maps, unsigned int max)
836 {
837     DWORD map = 1 << max;
838     map |= map - 1;
839     map &= reg_maps->shader_version.major < 3 ? ~reg_maps->texcoord : ~reg_maps->input_registers;
840
841     return wined3d_log2i(map);
842 }
843
844 static void shader_dump_decl_usage(const struct wined3d_shader_semantic *semantic,
845         const struct wined3d_shader_version *shader_version)
846 {
847     TRACE("dcl");
848
849     if (semantic->reg.reg.type == WINED3DSPR_SAMPLER)
850     {
851         switch (semantic->sampler_type)
852         {
853             case WINED3DSTT_2D: TRACE("_2d"); break;
854             case WINED3DSTT_CUBE: TRACE("_cube"); break;
855             case WINED3DSTT_VOLUME: TRACE("_volume"); break;
856             default: TRACE("_unknown_ttype(0x%08x)", semantic->sampler_type);
857         }
858     }
859     else
860     {
861         /* Pixel shaders 3.0 don't have usage semantics. */
862         if (shader_version->major < 3 && shader_version->type == WINED3D_SHADER_TYPE_PIXEL) return;
863         else TRACE("_");
864
865         switch (semantic->usage)
866         {
867             case WINED3DDECLUSAGE_POSITION:
868                 TRACE("position%u", semantic->usage_idx);
869                 break;
870
871             case WINED3DDECLUSAGE_BLENDINDICES:
872                 TRACE("blend");
873                 break;
874
875             case WINED3DDECLUSAGE_BLENDWEIGHT:
876                 TRACE("weight");
877                 break;
878
879             case WINED3DDECLUSAGE_NORMAL:
880                 TRACE("normal%u", semantic->usage_idx);
881                 break;
882
883             case WINED3DDECLUSAGE_PSIZE:
884                 TRACE("psize");
885                 break;
886
887             case WINED3DDECLUSAGE_COLOR:
888                 if (!semantic->usage_idx) TRACE("color");
889                 else TRACE("specular%u", (semantic->usage_idx - 1));
890                 break;
891
892             case WINED3DDECLUSAGE_TEXCOORD:
893                 TRACE("texture%u", semantic->usage_idx);
894                 break;
895
896             case WINED3DDECLUSAGE_TANGENT:
897                 TRACE("tangent");
898                 break;
899
900             case WINED3DDECLUSAGE_BINORMAL:
901                 TRACE("binormal");
902                 break;
903
904             case WINED3DDECLUSAGE_TESSFACTOR:
905                 TRACE("tessfactor");
906                 break;
907
908             case WINED3DDECLUSAGE_POSITIONT:
909                 TRACE("positionT%u", semantic->usage_idx);
910                 break;
911
912             case WINED3DDECLUSAGE_FOG:
913                 TRACE("fog");
914                 break;
915
916             case WINED3DDECLUSAGE_DEPTH:
917                 TRACE("depth");
918                 break;
919
920             case WINED3DDECLUSAGE_SAMPLE:
921                 TRACE("sample");
922                 break;
923
924             default:
925                 FIXME("unknown_semantics(0x%08x)", semantic->usage);
926         }
927     }
928 }
929
930 static void shader_dump_register(const struct wined3d_shader_register *reg,
931         const struct wined3d_shader_version *shader_version)
932 {
933     static const char * const rastout_reg_names[] = {"oPos", "oFog", "oPts"};
934     static const char * const misctype_reg_names[] = {"vPos", "vFace"};
935     UINT offset = reg->idx;
936
937     switch (reg->type)
938     {
939         case WINED3DSPR_TEMP:
940             TRACE("r");
941             break;
942
943         case WINED3DSPR_INPUT:
944             TRACE("v");
945             break;
946
947         case WINED3DSPR_CONST:
948         case WINED3DSPR_CONST2:
949         case WINED3DSPR_CONST3:
950         case WINED3DSPR_CONST4:
951             TRACE("c");
952             offset = shader_get_float_offset(reg->type, reg->idx);
953             break;
954
955         case WINED3DSPR_TEXTURE: /* vs: case WINED3DSPR_ADDR */
956             TRACE("%c", shader_version->type == WINED3D_SHADER_TYPE_PIXEL ? 't' : 'a');
957             break;
958
959         case WINED3DSPR_RASTOUT:
960             TRACE("%s", rastout_reg_names[reg->idx]);
961             break;
962
963         case WINED3DSPR_COLOROUT:
964             TRACE("oC");
965             break;
966
967         case WINED3DSPR_DEPTHOUT:
968             TRACE("oDepth");
969             break;
970
971         case WINED3DSPR_ATTROUT:
972             TRACE("oD");
973             break;
974
975         case WINED3DSPR_TEXCRDOUT:
976             /* Vertex shaders >= 3.0 use general purpose output registers
977              * (WINED3DSPR_OUTPUT), which can include an address token. */
978             if (shader_version->major >= 3) TRACE("o");
979             else TRACE("oT");
980             break;
981
982         case WINED3DSPR_CONSTINT:
983             TRACE("i");
984             break;
985
986         case WINED3DSPR_CONSTBOOL:
987             TRACE("b");
988             break;
989
990         case WINED3DSPR_LABEL:
991             TRACE("l");
992             break;
993
994         case WINED3DSPR_LOOP:
995             TRACE("aL");
996             break;
997
998         case WINED3DSPR_SAMPLER:
999             TRACE("s");
1000             break;
1001
1002         case WINED3DSPR_MISCTYPE:
1003             if (reg->idx > 1) FIXME("Unhandled misctype register %u.\n", reg->idx);
1004             else TRACE("%s", misctype_reg_names[reg->idx]);
1005             break;
1006
1007         case WINED3DSPR_PREDICATE:
1008             TRACE("p");
1009             break;
1010
1011         case WINED3DSPR_IMMCONST:
1012             TRACE("l");
1013             break;
1014
1015         case WINED3DSPR_CONSTBUFFER:
1016             TRACE("cb");
1017             break;
1018
1019         default:
1020             TRACE("unhandled_rtype(%#x)", reg->type);
1021             break;
1022     }
1023
1024     if (reg->type == WINED3DSPR_IMMCONST)
1025     {
1026         TRACE("(");
1027         switch (reg->immconst_type)
1028         {
1029             case WINED3D_IMMCONST_FLOAT:
1030                 TRACE("%.8e", *(const float *)reg->immconst_data);
1031                 break;
1032
1033             case WINED3D_IMMCONST_FLOAT4:
1034                 TRACE("%.8e, %.8e, %.8e, %.8e",
1035                         *(const float *)&reg->immconst_data[0], *(const float *)&reg->immconst_data[1],
1036                         *(const float *)&reg->immconst_data[2], *(const float *)&reg->immconst_data[3]);
1037                 break;
1038
1039             default:
1040                 TRACE("<unhandled immconst_type %#x>", reg->immconst_type);
1041                 break;
1042         }
1043         TRACE(")");
1044     }
1045     else if (reg->type != WINED3DSPR_RASTOUT && reg->type != WINED3DSPR_MISCTYPE)
1046     {
1047         if (reg->array_idx != ~0U)
1048         {
1049             TRACE("%u[%u", offset, reg->array_idx);
1050             if (reg->rel_addr)
1051             {
1052                 TRACE(" + ");
1053                 shader_dump_src_param(reg->rel_addr, shader_version);
1054             }
1055             TRACE("]");
1056         }
1057         else
1058         {
1059             if (reg->rel_addr)
1060             {
1061                 TRACE("[");
1062                 shader_dump_src_param(reg->rel_addr, shader_version);
1063                 TRACE(" + ");
1064             }
1065             TRACE("%u", offset);
1066             if (reg->rel_addr) TRACE("]");
1067         }
1068     }
1069 }
1070
1071 void shader_dump_dst_param(const struct wined3d_shader_dst_param *param,
1072         const struct wined3d_shader_version *shader_version)
1073 {
1074     DWORD write_mask = param->write_mask;
1075
1076     shader_dump_register(&param->reg, shader_version);
1077
1078     if (write_mask != WINED3DSP_WRITEMASK_ALL)
1079     {
1080         static const char *write_mask_chars = "xyzw";
1081
1082         TRACE(".");
1083         if (write_mask & WINED3DSP_WRITEMASK_0) TRACE("%c", write_mask_chars[0]);
1084         if (write_mask & WINED3DSP_WRITEMASK_1) TRACE("%c", write_mask_chars[1]);
1085         if (write_mask & WINED3DSP_WRITEMASK_2) TRACE("%c", write_mask_chars[2]);
1086         if (write_mask & WINED3DSP_WRITEMASK_3) TRACE("%c", write_mask_chars[3]);
1087     }
1088 }
1089
1090 void shader_dump_src_param(const struct wined3d_shader_src_param *param,
1091         const struct wined3d_shader_version *shader_version)
1092 {
1093     DWORD src_modifier = param->modifiers;
1094     DWORD swizzle = param->swizzle;
1095
1096     if (src_modifier == WINED3DSPSM_NEG
1097             || src_modifier == WINED3DSPSM_BIASNEG
1098             || src_modifier == WINED3DSPSM_SIGNNEG
1099             || src_modifier == WINED3DSPSM_X2NEG
1100             || src_modifier == WINED3DSPSM_ABSNEG)
1101         TRACE("-");
1102     else if (src_modifier == WINED3DSPSM_COMP)
1103         TRACE("1-");
1104     else if (src_modifier == WINED3DSPSM_NOT)
1105         TRACE("!");
1106
1107     if (src_modifier == WINED3DSPSM_ABS || src_modifier == WINED3DSPSM_ABSNEG)
1108         TRACE("abs(");
1109
1110     shader_dump_register(&param->reg, shader_version);
1111
1112     if (src_modifier)
1113     {
1114         switch (src_modifier)
1115         {
1116             case WINED3DSPSM_NONE:    break;
1117             case WINED3DSPSM_NEG:     break;
1118             case WINED3DSPSM_NOT:     break;
1119             case WINED3DSPSM_BIAS:    TRACE("_bias"); break;
1120             case WINED3DSPSM_BIASNEG: TRACE("_bias"); break;
1121             case WINED3DSPSM_SIGN:    TRACE("_bx2"); break;
1122             case WINED3DSPSM_SIGNNEG: TRACE("_bx2"); break;
1123             case WINED3DSPSM_COMP:    break;
1124             case WINED3DSPSM_X2:      TRACE("_x2"); break;
1125             case WINED3DSPSM_X2NEG:   TRACE("_x2"); break;
1126             case WINED3DSPSM_DZ:      TRACE("_dz"); break;
1127             case WINED3DSPSM_DW:      TRACE("_dw"); break;
1128             case WINED3DSPSM_ABSNEG:  TRACE(")"); break;
1129             case WINED3DSPSM_ABS:     TRACE(")"); break;
1130             default:                  TRACE("_unknown_modifier(%#x)", src_modifier);
1131         }
1132     }
1133
1134     if (swizzle != WINED3DSP_NOSWIZZLE)
1135     {
1136         static const char *swizzle_chars = "xyzw";
1137         DWORD swizzle_x = swizzle & 0x03;
1138         DWORD swizzle_y = (swizzle >> 2) & 0x03;
1139         DWORD swizzle_z = (swizzle >> 4) & 0x03;
1140         DWORD swizzle_w = (swizzle >> 6) & 0x03;
1141
1142         if (swizzle_x == swizzle_y
1143                 && swizzle_x == swizzle_z
1144                 && swizzle_x == swizzle_w)
1145         {
1146             TRACE(".%c", swizzle_chars[swizzle_x]);
1147         }
1148         else
1149         {
1150             TRACE(".%c%c%c%c", swizzle_chars[swizzle_x], swizzle_chars[swizzle_y],
1151                     swizzle_chars[swizzle_z], swizzle_chars[swizzle_w]);
1152         }
1153     }
1154 }
1155
1156 /* Shared code in order to generate the bulk of the shader string.
1157  * NOTE: A description of how to parse tokens can be found on MSDN. */
1158 void shader_generate_main(IWineD3DBaseShader *iface, struct wined3d_shader_buffer *buffer,
1159         const shader_reg_maps *reg_maps, const DWORD *byte_code, void *backend_ctx)
1160 {
1161     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface;
1162     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
1163     const struct wined3d_shader_frontend *fe = shader->baseShader.frontend;
1164     void *fe_data = shader->baseShader.frontend_data;
1165     struct wined3d_shader_src_param src_rel_addr[4];
1166     struct wined3d_shader_src_param src_param[4];
1167     struct wined3d_shader_version shader_version;
1168     struct wined3d_shader_src_param dst_rel_addr;
1169     struct wined3d_shader_dst_param dst_param;
1170     struct wined3d_shader_instruction ins;
1171     struct wined3d_shader_context ctx;
1172     const DWORD *ptr = byte_code;
1173     DWORD i;
1174
1175     /* Initialize current parsing state. */
1176     ctx.shader = iface;
1177     ctx.gl_info = &device->adapter->gl_info;
1178     ctx.reg_maps = reg_maps;
1179     ctx.buffer = buffer;
1180     ctx.backend_data = backend_ctx;
1181
1182     ins.ctx = &ctx;
1183     ins.dst = &dst_param;
1184     ins.src = src_param;
1185     shader->baseShader.parse_state.current_row = 0;
1186
1187     fe->shader_read_header(fe_data, &ptr, &shader_version);
1188
1189     while (!fe->shader_is_end(fe_data, &ptr))
1190     {
1191         const char *comment;
1192         UINT comment_size;
1193         UINT param_size;
1194
1195         /* Skip comment tokens. */
1196         fe->shader_read_comment(&ptr, &comment, &comment_size);
1197         if (comment) continue;
1198
1199         /* Read opcode. */
1200         fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
1201
1202         /* Unknown opcode and its parameters. */
1203         if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
1204         {
1205             TRACE("Skipping unrecognized instruction.\n");
1206             ptr += param_size;
1207             continue;
1208         }
1209
1210         /* Nothing to do. */
1211         if (ins.handler_idx == WINED3DSIH_DCL
1212                 || ins.handler_idx == WINED3DSIH_NOP
1213                 || ins.handler_idx == WINED3DSIH_DEF
1214                 || ins.handler_idx == WINED3DSIH_DEFI
1215                 || ins.handler_idx == WINED3DSIH_DEFB
1216                 || ins.handler_idx == WINED3DSIH_PHASE)
1217         {
1218             ptr += param_size;
1219             continue;
1220         }
1221
1222         /* Destination token */
1223         if (ins.dst_count) fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
1224
1225         /* Predication token */
1226         if (ins.predicate)
1227         {
1228             FIXME("Predicates not implemented.\n");
1229             ins.predicate = *ptr++;
1230         }
1231
1232         /* Other source tokens */
1233         for (i = 0; i < ins.src_count; ++i)
1234         {
1235             fe->shader_read_src_param(fe_data, &ptr, &src_param[i], &src_rel_addr[i]);
1236         }
1237
1238         /* Call appropriate function for output target */
1239         device->shader_backend->shader_handle_instruction(&ins);
1240     }
1241 }
1242
1243 static void shader_dump_ins_modifiers(const struct wined3d_shader_dst_param *dst)
1244 {
1245     DWORD mmask = dst->modifiers;
1246
1247     switch (dst->shift)
1248     {
1249         case 0: break;
1250         case 13: TRACE("_d8"); break;
1251         case 14: TRACE("_d4"); break;
1252         case 15: TRACE("_d2"); break;
1253         case 1: TRACE("_x2"); break;
1254         case 2: TRACE("_x4"); break;
1255         case 3: TRACE("_x8"); break;
1256         default: TRACE("_unhandled_shift(%d)", dst->shift); break;
1257     }
1258
1259     if (mmask & WINED3DSPDM_SATURATE)         TRACE("_sat");
1260     if (mmask & WINED3DSPDM_PARTIALPRECISION) TRACE("_pp");
1261     if (mmask & WINED3DSPDM_MSAMPCENTROID)    TRACE("_centroid");
1262
1263     mmask &= ~(WINED3DSPDM_SATURATE | WINED3DSPDM_PARTIALPRECISION | WINED3DSPDM_MSAMPCENTROID);
1264     if (mmask) FIXME("_unrecognized_modifier(%#x)", mmask);
1265 }
1266
1267 static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe_data, const DWORD *byte_code)
1268 {
1269     struct wined3d_shader_version shader_version;
1270     const DWORD *ptr = byte_code;
1271     const char *type_prefix;
1272     DWORD i;
1273
1274     TRACE("Parsing %p.\n", byte_code);
1275
1276     fe->shader_read_header(fe_data, &ptr, &shader_version);
1277
1278     switch (shader_version.type)
1279     {
1280         case WINED3D_SHADER_TYPE_VERTEX:
1281             type_prefix = "vs";
1282             break;
1283
1284         case WINED3D_SHADER_TYPE_GEOMETRY:
1285             type_prefix = "gs";
1286             break;
1287
1288         case WINED3D_SHADER_TYPE_PIXEL:
1289             type_prefix = "ps";
1290             break;
1291
1292         default:
1293             FIXME("Unhandled shader type %#x.\n", shader_version.type);
1294             type_prefix = "unknown";
1295             break;
1296     }
1297
1298     TRACE("%s_%u_%u\n", type_prefix, shader_version.major, shader_version.minor);
1299
1300     while (!fe->shader_is_end(fe_data, &ptr))
1301     {
1302         struct wined3d_shader_instruction ins;
1303         const char *comment;
1304         UINT comment_size;
1305         UINT param_size;
1306
1307         /* comment */
1308         fe->shader_read_comment(&ptr, &comment, &comment_size);
1309         if (comment)
1310         {
1311             if (comment_size > 4 && *(const DWORD *)comment == WINEMAKEFOURCC('T', 'E', 'X', 'T'))
1312             {
1313                 const char *end = comment + comment_size;
1314                 const char *ptr = comment + 4;
1315                 const char *line = ptr;
1316
1317                 TRACE("// TEXT\n");
1318                 while (ptr != end)
1319                 {
1320                     if (*ptr == '\n')
1321                     {
1322                         UINT len = ptr - line;
1323                         if (len && *(ptr - 1) == '\r') --len;
1324                         TRACE("// %s\n", debugstr_an(line, len));
1325                         line = ++ptr;
1326                     }
1327                     else ++ptr;
1328                 }
1329                 if (line != ptr) TRACE("// %s\n", debugstr_an(line, ptr - line));
1330             }
1331             else TRACE("// %s\n", debugstr_an(comment, comment_size));
1332             continue;
1333         }
1334
1335         fe->shader_read_opcode(fe_data, &ptr, &ins, &param_size);
1336         if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
1337         {
1338             TRACE("Skipping unrecognized instruction.\n");
1339             ptr += param_size;
1340             continue;
1341         }
1342
1343         if (ins.handler_idx == WINED3DSIH_DCL)
1344         {
1345             struct wined3d_shader_semantic semantic;
1346
1347             fe->shader_read_semantic(&ptr, &semantic);
1348
1349             shader_dump_decl_usage(&semantic, &shader_version);
1350             shader_dump_ins_modifiers(&semantic.reg);
1351             TRACE(" ");
1352             shader_dump_dst_param(&semantic.reg, &shader_version);
1353         }
1354         else if (ins.handler_idx == WINED3DSIH_DEF)
1355         {
1356             struct wined3d_shader_src_param rel_addr;
1357             struct wined3d_shader_dst_param dst;
1358
1359             fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
1360
1361             TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(dst.reg.type, dst.reg.idx),
1362                     *(const float *)(ptr),
1363                     *(const float *)(ptr + 1),
1364                     *(const float *)(ptr + 2),
1365                     *(const float *)(ptr + 3));
1366             ptr += 4;
1367         }
1368         else if (ins.handler_idx == WINED3DSIH_DEFI)
1369         {
1370             struct wined3d_shader_src_param rel_addr;
1371             struct wined3d_shader_dst_param dst;
1372
1373             fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
1374
1375             TRACE("defi i%u = %d, %d, %d, %d", dst.reg.idx,
1376                     *(ptr),
1377                     *(ptr + 1),
1378                     *(ptr + 2),
1379                     *(ptr + 3));
1380             ptr += 4;
1381         }
1382         else if (ins.handler_idx == WINED3DSIH_DEFB)
1383         {
1384             struct wined3d_shader_src_param rel_addr;
1385             struct wined3d_shader_dst_param dst;
1386
1387             fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
1388
1389             TRACE("defb b%u = %s", dst.reg.idx, *ptr ? "true" : "false");
1390             ++ptr;
1391         }
1392         else
1393         {
1394             struct wined3d_shader_src_param dst_rel_addr, src_rel_addr;
1395             struct wined3d_shader_dst_param dst_param;
1396             struct wined3d_shader_src_param src_param;
1397
1398             if (ins.dst_count)
1399             {
1400                 fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
1401             }
1402
1403             /* Print out predication source token first - it follows
1404              * the destination token. */
1405             if (ins.predicate)
1406             {
1407                 fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
1408                 TRACE("(");
1409                 shader_dump_src_param(&src_param, &shader_version);
1410                 TRACE(") ");
1411             }
1412
1413             /* PixWin marks instructions with the coissue flag with a '+' */
1414             if (ins.coissue) TRACE("+");
1415
1416             TRACE("%s", shader_opcode_names[ins.handler_idx]);
1417
1418             if (ins.handler_idx == WINED3DSIH_IFC
1419                     || ins.handler_idx == WINED3DSIH_BREAKC)
1420             {
1421                 switch (ins.flags)
1422                 {
1423                     case COMPARISON_GT: TRACE("_gt"); break;
1424                     case COMPARISON_EQ: TRACE("_eq"); break;
1425                     case COMPARISON_GE: TRACE("_ge"); break;
1426                     case COMPARISON_LT: TRACE("_lt"); break;
1427                     case COMPARISON_NE: TRACE("_ne"); break;
1428                     case COMPARISON_LE: TRACE("_le"); break;
1429                     default: TRACE("_(%u)", ins.flags);
1430                 }
1431             }
1432             else if (ins.handler_idx == WINED3DSIH_TEX
1433                     && shader_version.major >= 2
1434                     && (ins.flags & WINED3DSI_TEXLD_PROJECT))
1435             {
1436                 TRACE("p");
1437             }
1438
1439             /* We already read the destination token, print it. */
1440             if (ins.dst_count)
1441             {
1442                 shader_dump_ins_modifiers(&dst_param);
1443                 TRACE(" ");
1444                 shader_dump_dst_param(&dst_param, &shader_version);
1445             }
1446
1447             /* Other source tokens */
1448             for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i)
1449             {
1450                 fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
1451                 TRACE(!i ? " " : ", ");
1452                 shader_dump_src_param(&src_param, &shader_version);
1453             }
1454         }
1455         TRACE("\n");
1456     }
1457 }
1458
1459 static void shader_cleanup(IWineD3DBaseShader *iface)
1460 {
1461     IWineD3DBaseShaderImpl *shader = (IWineD3DBaseShaderImpl *)iface;
1462
1463     ((IWineD3DDeviceImpl *)shader->baseShader.device)->shader_backend->shader_destroy(iface);
1464     HeapFree(GetProcessHeap(), 0, shader->baseShader.reg_maps.constf);
1465     HeapFree(GetProcessHeap(), 0, shader->baseShader.function);
1466     shader_delete_constant_list(&shader->baseShader.constantsF);
1467     shader_delete_constant_list(&shader->baseShader.constantsB);
1468     shader_delete_constant_list(&shader->baseShader.constantsI);
1469     list_remove(&shader->baseShader.shader_list_entry);
1470
1471     if (shader->baseShader.frontend && shader->baseShader.frontend_data)
1472     {
1473         shader->baseShader.frontend->shader_free(shader->baseShader.frontend_data);
1474     }
1475 }
1476
1477 static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {}
1478 static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {}
1479 static void shader_none_select_depth_blt(IWineD3DDevice *iface, enum tex_types tex_type, const SIZE *ds_mask_size) {}
1480 static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
1481 static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
1482 static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
1483 static void shader_none_load_constants(const struct wined3d_context *context, char usePS, char useVS) {}
1484 static void shader_none_load_np2fixup_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
1485 static void shader_none_destroy(IWineD3DBaseShader *iface) {}
1486 static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
1487 static void shader_none_free(IWineD3DDevice *iface) {}
1488 static BOOL shader_none_dirty_const(IWineD3DDevice *iface) {return FALSE;}
1489
1490 static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
1491 {
1492     /* Set the shader caps to 0 for the none shader backend */
1493     caps->VertexShaderVersion = 0;
1494     caps->MaxVertexShaderConst = 0;
1495     caps->PixelShaderVersion = 0;
1496     caps->PixelShader1xMaxValue = 0.0f;
1497     caps->MaxPixelShaderConst = 0;
1498     caps->VSClipping = FALSE;
1499 }
1500
1501 static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup)
1502 {
1503     if (TRACE_ON(d3d_shader) && TRACE_ON(d3d))
1504     {
1505         TRACE("Checking support for fixup:\n");
1506         dump_color_fixup_desc(fixup);
1507     }
1508
1509     /* Faked to make some apps happy. */
1510     if (!is_complex_fixup(fixup))
1511     {
1512         TRACE("[OK]\n");
1513         return TRUE;
1514     }
1515
1516     TRACE("[FAILED]\n");
1517     return FALSE;
1518 }
1519
1520 const shader_backend_t none_shader_backend = {
1521     shader_none_handle_instruction,
1522     shader_none_select,
1523     shader_none_select_depth_blt,
1524     shader_none_deselect_depth_blt,
1525     shader_none_update_float_vertex_constants,
1526     shader_none_update_float_pixel_constants,
1527     shader_none_load_constants,
1528     shader_none_load_np2fixup_constants,
1529     shader_none_destroy,
1530     shader_none_alloc,
1531     shader_none_free,
1532     shader_none_dirty_const,
1533     shader_none_get_caps,
1534     shader_none_color_fixup_supported,
1535 };
1536
1537 static HRESULT shader_get_function(IWineD3DBaseShaderImpl *shader, void *data, UINT *data_size)
1538 {
1539     if (!data)
1540     {
1541         *data_size = shader->baseShader.functionLength;
1542         return WINED3D_OK;
1543     }
1544
1545     if (*data_size < shader->baseShader.functionLength)
1546     {
1547         /* MSDN claims (for d3d8 at least) that if *pSizeOfData is smaller
1548          * than the required size we should write the required size and
1549          * return D3DERR_MOREDATA. That's not actually true. */
1550         return WINED3DERR_INVALIDCALL;
1551     }
1552
1553     memcpy(data, shader->baseShader.function, shader->baseShader.functionLength);
1554
1555     return WINED3D_OK;
1556 }
1557
1558 static HRESULT shader_set_function(IWineD3DBaseShaderImpl *shader, const DWORD *byte_code,
1559         const struct wined3d_shader_signature *output_signature, DWORD float_const_count)
1560 {
1561     struct shader_reg_maps *reg_maps = &shader->baseShader.reg_maps;
1562     const struct wined3d_shader_frontend *fe;
1563     HRESULT hr;
1564
1565     TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u.\n",
1566             shader, byte_code, output_signature, float_const_count);
1567
1568     fe = shader_select_frontend(*byte_code);
1569     if (!fe)
1570     {
1571         FIXME("Unable to find frontend for shader.\n");
1572         return WINED3DERR_INVALIDCALL;
1573     }
1574     shader->baseShader.frontend = fe;
1575     shader->baseShader.frontend_data = fe->shader_init(byte_code, output_signature);
1576     if (!shader->baseShader.frontend_data)
1577     {
1578         FIXME("Failed to initialize frontend.\n");
1579         return WINED3DERR_INVALIDCALL;
1580     }
1581
1582     /* First pass: trace shader. */
1583     if (TRACE_ON(d3d_shader)) shader_trace_init(fe, shader->baseShader.frontend_data, byte_code);
1584
1585     /* Initialize immediate constant lists. */
1586     list_init(&shader->baseShader.constantsF);
1587     list_init(&shader->baseShader.constantsB);
1588     list_init(&shader->baseShader.constantsI);
1589
1590     /* Second pass: figure out which registers are used, what the semantics are, etc. */
1591     hr = shader_get_registers_used((IWineD3DBaseShader *)shader, fe,
1592             reg_maps, shader->baseShader.input_signature, shader->baseShader.output_signature,
1593             byte_code, float_const_count);
1594     if (FAILED(hr)) return hr;
1595
1596     shader->baseShader.function = HeapAlloc(GetProcessHeap(), 0, shader->baseShader.functionLength);
1597     if (!shader->baseShader.function) return E_OUTOFMEMORY;
1598     memcpy(shader->baseShader.function, byte_code, shader->baseShader.functionLength);
1599
1600     return WINED3D_OK;
1601 }
1602
1603 static HRESULT STDMETHODCALLTYPE vertexshader_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, void **object)
1604 {
1605     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1606
1607     if (IsEqualGUID(riid, &IID_IWineD3DVertexShader)
1608             || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1609             || IsEqualGUID(riid, &IID_IWineD3DBase)
1610             || IsEqualGUID(riid, &IID_IUnknown))
1611     {
1612         IUnknown_AddRef(iface);
1613         *object = iface;
1614         return S_OK;
1615     }
1616
1617     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1618
1619     *object = NULL;
1620     return E_NOINTERFACE;
1621 }
1622
1623 static ULONG STDMETHODCALLTYPE vertexshader_AddRef(IWineD3DVertexShader *iface)
1624 {
1625     IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
1626     ULONG refcount = InterlockedIncrement(&shader->baseShader.ref);
1627
1628     TRACE("%p increasing refcount to %u.\n", shader, refcount);
1629
1630     return refcount;
1631 }
1632
1633 /* Do not call while under the GL lock. */
1634 static ULONG STDMETHODCALLTYPE vertexshader_Release(IWineD3DVertexShader *iface)
1635 {
1636     IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
1637     ULONG refcount = InterlockedDecrement(&shader->baseShader.ref);
1638
1639     TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1640
1641     if (!refcount)
1642     {
1643         shader_cleanup((IWineD3DBaseShader *)iface);
1644         shader->baseShader.parent_ops->wined3d_object_destroyed(shader->baseShader.parent);
1645         HeapFree(GetProcessHeap(), 0, shader);
1646     }
1647
1648     return refcount;
1649 }
1650
1651 static void * STDMETHODCALLTYPE vertexshader_GetParent(IWineD3DVertexShader *iface)
1652 {
1653     TRACE("iface %p.\n", iface);
1654
1655     return ((IWineD3DBaseShaderImpl *)iface)->baseShader.parent;
1656 }
1657
1658 static HRESULT STDMETHODCALLTYPE vertexshader_GetFunction(IWineD3DVertexShader *iface, void *data, UINT *data_size)
1659 {
1660     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
1661
1662     return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
1663 }
1664
1665 /* Set local constants for d3d8 shaders. */
1666 static HRESULT STDMETHODCALLTYPE vertexshader_SetLocalConstantsF(IWineD3DVertexShader *iface,
1667         UINT start_idx, const float *src_data, UINT count)
1668 {
1669     IWineD3DVertexShaderImpl *shader =(IWineD3DVertexShaderImpl *)iface;
1670     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
1671     UINT i, end_idx;
1672
1673     TRACE("iface %p, start_idx %u, src_data %p, count %u.\n", iface, start_idx, src_data, count);
1674
1675     end_idx = start_idx + count;
1676     if (end_idx > device->d3d_vshader_constantF)
1677     {
1678         WARN("end_idx %u > float constants limit %u.\n", end_idx, device->d3d_vshader_constantF);
1679         end_idx = device->d3d_vshader_constantF;
1680     }
1681
1682     for (i = start_idx; i < end_idx; ++i)
1683     {
1684         local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
1685         if (!lconst) return E_OUTOFMEMORY;
1686
1687         lconst->idx = i;
1688         memcpy(lconst->value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float));
1689         list_add_head(&shader->baseShader.constantsF, &lconst->entry);
1690     }
1691
1692     return WINED3D_OK;
1693 }
1694
1695 static const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1696 {
1697     /* IUnknown methods */
1698     vertexshader_QueryInterface,
1699     vertexshader_AddRef,
1700     vertexshader_Release,
1701     /* IWineD3DBase methods */
1702     vertexshader_GetParent,
1703     /* IWineD3DBaseShader methods */
1704     vertexshader_GetFunction,
1705     /* IWineD3DVertexShader methods */
1706     vertexshader_SetLocalConstantsF,
1707 };
1708
1709 void find_vs_compile_args(IWineD3DVertexShaderImpl *shader,
1710         IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args)
1711 {
1712     args->fog_src = stateblock->state.render_states[WINED3DRS_FOGTABLEMODE]
1713             == WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
1714     args->clip_enabled = stateblock->state.render_states[WINED3DRS_CLIPPING]
1715             && stateblock->state.render_states[WINED3DRS_CLIPPLANEENABLE];
1716     args->swizzle_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.swizzle_map;
1717 }
1718
1719 static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
1720 {
1721     if (usage_idx1 != usage_idx2) return FALSE;
1722     if (usage1 == usage2) return TRUE;
1723     if (usage1 == WINED3DDECLUSAGE_POSITION && usage2 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
1724     if (usage2 == WINED3DDECLUSAGE_POSITION && usage1 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
1725
1726     return FALSE;
1727 }
1728
1729 BOOL vshader_get_input(IWineD3DVertexShader *iface, BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum)
1730 {
1731     IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
1732     WORD map = shader->baseShader.reg_maps.input_registers;
1733     unsigned int i;
1734
1735     for (i = 0; map; map >>= 1, ++i)
1736     {
1737         if (!(map & 1)) continue;
1738
1739         if (match_usage(shader->attributes[i].usage,
1740                 shader->attributes[i].usage_idx, usage_req, usage_idx_req))
1741         {
1742             *regnum = i;
1743             return TRUE;
1744         }
1745     }
1746     return FALSE;
1747 }
1748
1749 static void vertexshader_set_limits(IWineD3DVertexShaderImpl *shader)
1750 {
1751     DWORD shader_version = WINED3D_SHADER_VERSION(shader->baseShader.reg_maps.shader_version.major,
1752             shader->baseShader.reg_maps.shader_version.minor);
1753     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
1754
1755     shader->baseShader.limits.texcoord = 0;
1756     shader->baseShader.limits.attributes = 16;
1757     shader->baseShader.limits.packed_input = 0;
1758
1759     switch (shader_version)
1760     {
1761         case WINED3D_SHADER_VERSION(1, 0):
1762         case WINED3D_SHADER_VERSION(1, 1):
1763             shader->baseShader.limits.temporary = 12;
1764             shader->baseShader.limits.constant_bool = 0;
1765             shader->baseShader.limits.constant_int = 0;
1766             shader->baseShader.limits.address = 1;
1767             shader->baseShader.limits.packed_output = 12;
1768             shader->baseShader.limits.sampler = 0;
1769             shader->baseShader.limits.label = 0;
1770             /* TODO: vs_1_1 has a minimum of 96 constants. What happens when
1771              * a vs_1_1 shader is used on a vs_3_0 capable card that has 256
1772              * constants? */
1773             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1774             break;
1775
1776         case WINED3D_SHADER_VERSION(2, 0):
1777         case WINED3D_SHADER_VERSION(2, 1):
1778             shader->baseShader.limits.temporary = 12;
1779             shader->baseShader.limits.constant_bool = 16;
1780             shader->baseShader.limits.constant_int = 16;
1781             shader->baseShader.limits.address = 1;
1782             shader->baseShader.limits.packed_output = 12;
1783             shader->baseShader.limits.sampler = 0;
1784             shader->baseShader.limits.label = 16;
1785             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1786             break;
1787
1788         case WINED3D_SHADER_VERSION(4, 0):
1789             FIXME("Using 3.0 limits for 4.0 shader.\n");
1790             /* Fall through. */
1791
1792         case WINED3D_SHADER_VERSION(3, 0):
1793             shader->baseShader.limits.temporary = 32;
1794             shader->baseShader.limits.constant_bool = 32;
1795             shader->baseShader.limits.constant_int = 32;
1796             shader->baseShader.limits.address = 1;
1797             shader->baseShader.limits.packed_output = 12;
1798             shader->baseShader.limits.sampler = 4;
1799             shader->baseShader.limits.label = 16; /* FIXME: 2048 */
1800             /* DX10 cards on Windows advertise a d3d9 constant limit of 256
1801              * even though they are capable of supporting much more (GL
1802              * drivers advertise 1024). d3d9.dll and d3d8.dll clamp the
1803              * wined3d-advertised maximum. Clamp the constant limit for <= 3.0
1804              * shaders to 256. */
1805             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1806             break;
1807
1808         default:
1809             shader->baseShader.limits.temporary = 12;
1810             shader->baseShader.limits.constant_bool = 16;
1811             shader->baseShader.limits.constant_int = 16;
1812             shader->baseShader.limits.address = 1;
1813             shader->baseShader.limits.packed_output = 12;
1814             shader->baseShader.limits.sampler = 0;
1815             shader->baseShader.limits.label = 16;
1816             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1817             FIXME("Unrecognized vertex shader version \"%u.%u\".\n",
1818                     shader->baseShader.reg_maps.shader_version.major,
1819                     shader->baseShader.reg_maps.shader_version.minor);
1820     }
1821 }
1822
1823 HRESULT vertexshader_init(IWineD3DVertexShaderImpl *shader, IWineD3DDeviceImpl *device,
1824         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
1825         void *parent, const struct wined3d_parent_ops *parent_ops)
1826 {
1827     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1828     struct shader_reg_maps *reg_maps = &shader->baseShader.reg_maps;
1829     unsigned int i;
1830     HRESULT hr;
1831     WORD map;
1832
1833     if (!byte_code) return WINED3DERR_INVALIDCALL;
1834
1835     shader->lpVtbl = &IWineD3DVertexShader_Vtbl;
1836     shader_init(&shader->baseShader, device, parent, parent_ops);
1837
1838     hr = shader_set_function((IWineD3DBaseShaderImpl *)shader, byte_code,
1839             output_signature, device->d3d_vshader_constantF);
1840     if (FAILED(hr))
1841     {
1842         WARN("Failed to set function, hr %#x.\n", hr);
1843         shader_cleanup((IWineD3DBaseShader *)shader);
1844         return hr;
1845     }
1846
1847     map = shader->baseShader.reg_maps.input_registers;
1848     for (i = 0; map; map >>= 1, ++i)
1849     {
1850         if (!(map & 1) || !shader->baseShader.input_signature[i].semantic_name) continue;
1851
1852         shader->attributes[i].usage =
1853                 shader_usage_from_semantic_name(shader->baseShader.input_signature[i].semantic_name);
1854         shader->attributes[i].usage_idx = shader->baseShader.input_signature[i].semantic_idx;
1855     }
1856
1857     if (output_signature)
1858     {
1859         for (i = 0; i < output_signature->element_count; ++i)
1860         {
1861             struct wined3d_shader_signature_element *e = &output_signature->elements[i];
1862             reg_maps->output_registers |= 1 << e->register_idx;
1863             shader->baseShader.output_signature[e->register_idx] = *e;
1864         }
1865     }
1866
1867     vertexshader_set_limits(shader);
1868
1869     if (device->vs_selected_mode == SHADER_ARB
1870             && (gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT)
1871             && shader->min_rel_offset <= shader->max_rel_offset)
1872     {
1873         if (shader->max_rel_offset - shader->min_rel_offset > 127)
1874         {
1875             FIXME("The difference between the minimum and maximum relative offset is > 127.\n");
1876             FIXME("Which this OpenGL implementation does not support. Try using GLSL.\n");
1877             FIXME("Min: %d, Max: %d.\n", shader->min_rel_offset, shader->max_rel_offset);
1878         }
1879         else if (shader->max_rel_offset - shader->min_rel_offset > 63)
1880         {
1881             shader->rel_offset = shader->min_rel_offset + 63;
1882         }
1883         else if (shader->max_rel_offset > 63)
1884         {
1885             shader->rel_offset = shader->min_rel_offset;
1886         }
1887         else
1888         {
1889             shader->rel_offset = 0;
1890         }
1891     }
1892
1893     shader->baseShader.load_local_constsF = shader->baseShader.reg_maps.usesrelconstF
1894             && !list_empty(&shader->baseShader.constantsF);
1895
1896     return WINED3D_OK;
1897 }
1898
1899 static HRESULT STDMETHODCALLTYPE geometryshader_QueryInterface(IWineD3DGeometryShader *iface,
1900         REFIID riid, void **object)
1901 {
1902     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1903
1904     if (IsEqualGUID(riid, &IID_IWineD3DGeometryShader)
1905             || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1906             || IsEqualGUID(riid, &IID_IWineD3DBase)
1907             || IsEqualGUID(riid, &IID_IUnknown))
1908     {
1909         IUnknown_AddRef(iface);
1910         *object = iface;
1911         return S_OK;
1912     }
1913
1914     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1915
1916     *object = NULL;
1917     return E_NOINTERFACE;
1918 }
1919
1920 static ULONG STDMETHODCALLTYPE geometryshader_AddRef(IWineD3DGeometryShader *iface)
1921 {
1922     struct wined3d_geometryshader *shader = (struct wined3d_geometryshader *)iface;
1923     ULONG refcount = InterlockedIncrement(&shader->base_shader.ref);
1924
1925     TRACE("%p increasing refcount to %u.\n", shader, refcount);
1926
1927     return refcount;
1928 }
1929
1930 /* Do not call while under the GL lock. */
1931 static ULONG STDMETHODCALLTYPE geometryshader_Release(IWineD3DGeometryShader *iface)
1932 {
1933     struct wined3d_geometryshader *shader = (struct wined3d_geometryshader *)iface;
1934     ULONG refcount = InterlockedDecrement(&shader->base_shader.ref);
1935
1936     TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1937
1938     if (!refcount)
1939     {
1940         shader_cleanup((IWineD3DBaseShader *)iface);
1941         shader->base_shader.parent_ops->wined3d_object_destroyed(shader->base_shader.parent);
1942         HeapFree(GetProcessHeap(), 0, shader);
1943     }
1944
1945     return refcount;
1946 }
1947
1948 static void * STDMETHODCALLTYPE geometryshader_GetParent(IWineD3DGeometryShader *iface)
1949 {
1950     TRACE("iface %p.\n", iface);
1951
1952     return ((IWineD3DBaseShaderImpl *)iface)->baseShader.parent;
1953 }
1954
1955 static HRESULT STDMETHODCALLTYPE geometryshader_GetFunction(IWineD3DGeometryShader *iface, void *data, UINT *data_size)
1956 {
1957     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
1958
1959     return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
1960 }
1961
1962 static const IWineD3DGeometryShaderVtbl wined3d_geometryshader_vtbl =
1963 {
1964     /* IUnknown methods */
1965     geometryshader_QueryInterface,
1966     geometryshader_AddRef,
1967     geometryshader_Release,
1968     /* IWineD3DBase methods */
1969     geometryshader_GetParent,
1970     /* IWineD3DBaseShader methods */
1971     geometryshader_GetFunction,
1972 };
1973
1974 HRESULT geometryshader_init(struct wined3d_geometryshader *shader, IWineD3DDeviceImpl *device,
1975         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
1976         void *parent, const struct wined3d_parent_ops *parent_ops)
1977 {
1978     HRESULT hr;
1979
1980     shader->vtbl = &wined3d_geometryshader_vtbl;
1981     shader_init(&shader->base_shader, device, parent, parent_ops);
1982
1983     hr = shader_set_function((IWineD3DBaseShaderImpl *)shader, byte_code, output_signature, 0);
1984     if (FAILED(hr))
1985     {
1986         WARN("Failed to set function, hr %#x.\n", hr);
1987         shader_cleanup((IWineD3DBaseShader *)shader);
1988         return hr;
1989     }
1990
1991     shader->base_shader.load_local_constsF = FALSE;
1992
1993     return WINED3D_OK;
1994 }
1995
1996 static HRESULT STDMETHODCALLTYPE pixelshader_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, void **object)
1997 {
1998     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1999
2000     if (IsEqualGUID(riid, &IID_IWineD3DPixelShader)
2001             || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
2002             || IsEqualGUID(riid, &IID_IWineD3DBase)
2003             || IsEqualGUID(riid, &IID_IUnknown))
2004     {
2005         IUnknown_AddRef(iface);
2006         *object = iface;
2007         return S_OK;
2008     }
2009
2010     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
2011
2012     *object = NULL;
2013     return E_NOINTERFACE;
2014 }
2015
2016 static ULONG STDMETHODCALLTYPE pixelshader_AddRef(IWineD3DPixelShader *iface)
2017 {
2018     IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)iface;
2019     ULONG refcount = InterlockedIncrement(&shader->baseShader.ref);
2020
2021     TRACE("%p increasing refcount to %u.\n", shader, refcount);
2022
2023     return refcount;
2024 }
2025
2026 /* Do not call while under the GL lock. */
2027 static ULONG STDMETHODCALLTYPE pixelshader_Release(IWineD3DPixelShader *iface)
2028 {
2029     IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)iface;
2030     ULONG refcount = InterlockedDecrement(&shader->baseShader.ref);
2031
2032     TRACE("%p decreasing refcount to %u.\n", shader, refcount);
2033
2034     if (!refcount)
2035     {
2036         shader_cleanup((IWineD3DBaseShader *)iface);
2037         shader->baseShader.parent_ops->wined3d_object_destroyed(shader->baseShader.parent);
2038         HeapFree(GetProcessHeap(), 0, shader);
2039     }
2040
2041     return refcount;
2042 }
2043
2044 static void * STDMETHODCALLTYPE pixelshader_GetParent(IWineD3DPixelShader *iface)
2045 {
2046     TRACE("iface %p.\n", iface);
2047
2048     return ((IWineD3DBaseShaderImpl *)iface)->baseShader.parent;
2049 }
2050
2051 static HRESULT STDMETHODCALLTYPE pixelshader_GetFunction(IWineD3DPixelShader *iface, void *data, UINT *data_size)
2052 {
2053     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
2054
2055     return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
2056 }
2057
2058 static const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
2059 {
2060     /* IUnknown methods */
2061     pixelshader_QueryInterface,
2062     pixelshader_AddRef,
2063     pixelshader_Release,
2064     /* IWineD3DBase methods */
2065     pixelshader_GetParent,
2066     /* IWineD3DBaseShader methods */
2067     pixelshader_GetFunction
2068 };
2069
2070 void find_ps_compile_args(IWineD3DPixelShaderImpl *shader,
2071         IWineD3DStateBlockImpl *stateblock, struct ps_compile_args *args)
2072 {
2073     IWineD3DBaseTextureImpl *texture;
2074     IWineD3DDeviceImpl *device = stateblock->device;
2075     UINT i;
2076
2077     memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */
2078     if (stateblock->state.render_states[WINED3DRS_SRGBWRITEENABLE])
2079     {
2080         IWineD3DSurfaceImpl *rt = device->render_targets[0];
2081         if(rt->resource.format->Flags & WINED3DFMT_FLAG_SRGB_WRITE) args->srgb_correction = 1;
2082     }
2083
2084     args->np2_fixup = 0;
2085
2086     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
2087     {
2088         if (!shader->baseShader.reg_maps.sampler_type[i]) continue;
2089         texture = (IWineD3DBaseTextureImpl *)stateblock->textures[i];
2090         if (!texture)
2091         {
2092             args->color_fixup[i] = COLOR_FIXUP_IDENTITY;
2093             continue;
2094         }
2095         args->color_fixup[i] = texture->resource.format->color_fixup;
2096
2097         if (texture->resource.format->Flags & WINED3DFMT_FLAG_SHADOW)
2098             args->shadow |= 1 << i;
2099
2100         /* Flag samplers that need NP2 texcoord fixup. */
2101         if (!texture->baseTexture.pow2Matrix_identity)
2102         {
2103             args->np2_fixup |= (1 << i);
2104         }
2105     }
2106     if (shader->baseShader.reg_maps.shader_version.major >= 3)
2107     {
2108         if (device->strided_streams.position_transformed)
2109         {
2110             args->vp_mode = pretransformed;
2111         }
2112         else if (use_vs(stateblock))
2113         {
2114             args->vp_mode = vertexshader;
2115         }
2116         else
2117         {
2118             args->vp_mode = fixedfunction;
2119         }
2120         args->fog = FOG_OFF;
2121     }
2122     else
2123     {
2124         args->vp_mode = vertexshader;
2125         if (stateblock->state.render_states[WINED3DRS_FOGENABLE])
2126         {
2127             switch (stateblock->state.render_states[WINED3DRS_FOGTABLEMODE])
2128             {
2129                 case WINED3DFOG_NONE:
2130                     if (device->strided_streams.position_transformed || use_vs(stateblock))
2131                     {
2132                         args->fog = FOG_LINEAR;
2133                         break;
2134                     }
2135
2136                     switch (stateblock->state.render_states[WINED3DRS_FOGVERTEXMODE])
2137                     {
2138                         case WINED3DFOG_NONE: /* Fall through. */
2139                         case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
2140                         case WINED3DFOG_EXP:    args->fog = FOG_EXP;    break;
2141                         case WINED3DFOG_EXP2:   args->fog = FOG_EXP2;   break;
2142                     }
2143                     break;
2144
2145                 case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
2146                 case WINED3DFOG_EXP:    args->fog = FOG_EXP;    break;
2147                 case WINED3DFOG_EXP2:   args->fog = FOG_EXP2;   break;
2148             }
2149         }
2150         else
2151         {
2152             args->fog = FOG_OFF;
2153         }
2154     }
2155 }
2156
2157 static void pixelshader_set_limits(IWineD3DPixelShaderImpl *shader)
2158 {
2159     DWORD shader_version = WINED3D_SHADER_VERSION(shader->baseShader.reg_maps.shader_version.major,
2160             shader->baseShader.reg_maps.shader_version.minor);
2161
2162     shader->baseShader.limits.attributes = 0;
2163     shader->baseShader.limits.address = 0;
2164     shader->baseShader.limits.packed_output = 0;
2165
2166     switch (shader_version)
2167     {
2168         case WINED3D_SHADER_VERSION(1, 0):
2169         case WINED3D_SHADER_VERSION(1, 1):
2170         case WINED3D_SHADER_VERSION(1, 2):
2171         case WINED3D_SHADER_VERSION(1, 3):
2172             shader->baseShader.limits.temporary = 2;
2173             shader->baseShader.limits.constant_float = 8;
2174             shader->baseShader.limits.constant_int = 0;
2175             shader->baseShader.limits.constant_bool = 0;
2176             shader->baseShader.limits.texcoord = 4;
2177             shader->baseShader.limits.sampler = 4;
2178             shader->baseShader.limits.packed_input = 0;
2179             shader->baseShader.limits.label = 0;
2180             break;
2181
2182         case WINED3D_SHADER_VERSION(1, 4):
2183             shader->baseShader.limits.temporary = 6;
2184             shader->baseShader.limits.constant_float = 8;
2185             shader->baseShader.limits.constant_int = 0;
2186             shader->baseShader.limits.constant_bool = 0;
2187             shader->baseShader.limits.texcoord = 6;
2188             shader->baseShader.limits.sampler = 6;
2189             shader->baseShader.limits.packed_input = 0;
2190             shader->baseShader.limits.label = 0;
2191             break;
2192
2193         /* FIXME: Temporaries must match D3DPSHADERCAPS2_0.NumTemps. */
2194         case WINED3D_SHADER_VERSION(2, 0):
2195             shader->baseShader.limits.temporary = 32;
2196             shader->baseShader.limits.constant_float = 32;
2197             shader->baseShader.limits.constant_int = 16;
2198             shader->baseShader.limits.constant_bool = 16;
2199             shader->baseShader.limits.texcoord = 8;
2200             shader->baseShader.limits.sampler = 16;
2201             shader->baseShader.limits.packed_input = 0;
2202             break;
2203
2204         case WINED3D_SHADER_VERSION(2, 1):
2205             shader->baseShader.limits.temporary = 32;
2206             shader->baseShader.limits.constant_float = 32;
2207             shader->baseShader.limits.constant_int = 16;
2208             shader->baseShader.limits.constant_bool = 16;
2209             shader->baseShader.limits.texcoord = 8;
2210             shader->baseShader.limits.sampler = 16;
2211             shader->baseShader.limits.packed_input = 0;
2212             shader->baseShader.limits.label = 16;
2213             break;
2214
2215         case WINED3D_SHADER_VERSION(4, 0):
2216             FIXME("Using 3.0 limits for 4.0 shader.\n");
2217             /* Fall through. */
2218
2219         case WINED3D_SHADER_VERSION(3, 0):
2220             shader->baseShader.limits.temporary = 32;
2221             shader->baseShader.limits.constant_float = 224;
2222             shader->baseShader.limits.constant_int = 16;
2223             shader->baseShader.limits.constant_bool = 16;
2224             shader->baseShader.limits.texcoord = 0;
2225             shader->baseShader.limits.sampler = 16;
2226             shader->baseShader.limits.packed_input = 12;
2227             shader->baseShader.limits.label = 16; /* FIXME: 2048 */
2228             break;
2229
2230         default:
2231             shader->baseShader.limits.temporary = 32;
2232             shader->baseShader.limits.constant_float = 32;
2233             shader->baseShader.limits.constant_int = 16;
2234             shader->baseShader.limits.constant_bool = 16;
2235             shader->baseShader.limits.texcoord = 8;
2236             shader->baseShader.limits.sampler = 16;
2237             shader->baseShader.limits.packed_input = 0;
2238             shader->baseShader.limits.label = 0;
2239             FIXME("Unrecognized pixel shader version %u.%u\n",
2240                     shader->baseShader.reg_maps.shader_version.major,
2241                     shader->baseShader.reg_maps.shader_version.minor);
2242     }
2243 }
2244
2245 HRESULT pixelshader_init(IWineD3DPixelShaderImpl *shader, IWineD3DDeviceImpl *device,
2246         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
2247         void *parent, const struct wined3d_parent_ops *parent_ops)
2248 {
2249     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
2250     unsigned int i, highest_reg_used = 0, num_regs_used = 0;
2251     HRESULT hr;
2252
2253     if (!byte_code) return WINED3DERR_INVALIDCALL;
2254
2255     shader->lpVtbl = &IWineD3DPixelShader_Vtbl;
2256     shader_init(&shader->baseShader, device, parent, parent_ops);
2257
2258     hr = shader_set_function((IWineD3DBaseShaderImpl *)shader, byte_code,
2259             output_signature, device->d3d_pshader_constantF);
2260     if (FAILED(hr))
2261     {
2262         WARN("Failed to set function, hr %#x.\n", hr);
2263         shader_cleanup((IWineD3DBaseShader *)shader);
2264         return hr;
2265     }
2266
2267     pixelshader_set_limits(shader);
2268
2269     for (i = 0; i < MAX_REG_INPUT; ++i)
2270     {
2271         if (shader->input_reg_used[i])
2272         {
2273             ++num_regs_used;
2274             highest_reg_used = i;
2275         }
2276     }
2277
2278     /* Don't do any register mapping magic if it is not needed, or if we can't
2279      * achieve anything anyway */
2280     if (highest_reg_used < (gl_info->limits.glsl_varyings / 4)
2281             || num_regs_used > (gl_info->limits.glsl_varyings / 4))
2282     {
2283         if (num_regs_used > (gl_info->limits.glsl_varyings / 4))
2284         {
2285             /* This happens with relative addressing. The input mapper function
2286              * warns about this if the higher registers are declared too, so
2287              * don't write a FIXME here */
2288             WARN("More varying registers used than supported\n");
2289         }
2290
2291         for (i = 0; i < MAX_REG_INPUT; ++i)
2292         {
2293             shader->input_reg_map[i] = i;
2294         }
2295
2296         shader->declared_in_count = highest_reg_used + 1;
2297     }
2298     else
2299     {
2300         shader->declared_in_count = 0;
2301         for (i = 0; i < MAX_REG_INPUT; ++i)
2302         {
2303             if (shader->input_reg_used[i]) shader->input_reg_map[i] = shader->declared_in_count++;
2304             else shader->input_reg_map[i] = ~0U;
2305         }
2306     }
2307
2308     shader->baseShader.load_local_constsF = FALSE;
2309
2310     return WINED3D_OK;
2311 }
2312
2313 void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD3DBaseTexture * const *textures)
2314 {
2315     WINED3DSAMPLER_TEXTURE_TYPE *sampler_type = reg_maps->sampler_type;
2316     unsigned int i;
2317
2318     if (reg_maps->shader_version.major != 1) return;
2319
2320     for (i = 0; i < max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS); ++i)
2321     {
2322         /* We don't sample from this sampler. */
2323         if (!sampler_type[i]) continue;
2324
2325         if (!textures[i])
2326         {
2327             WARN("No texture bound to sampler %u, using 2D.\n", i);
2328             sampler_type[i] = WINED3DSTT_2D;
2329             continue;
2330         }
2331
2332         switch (IWineD3DBaseTexture_GetTextureDimensions(textures[i]))
2333         {
2334             case GL_TEXTURE_RECTANGLE_ARB:
2335             case GL_TEXTURE_2D:
2336                 /* We have to select between texture rectangles and 2D
2337                  * textures later because 2.0 and 3.0 shaders only have
2338                  * WINED3DSTT_2D as well. */
2339                 sampler_type[i] = WINED3DSTT_2D;
2340                 break;
2341
2342             case GL_TEXTURE_3D:
2343                 sampler_type[i] = WINED3DSTT_VOLUME;
2344                 break;
2345
2346             case GL_TEXTURE_CUBE_MAP_ARB:
2347                 sampler_type[i] = WINED3DSTT_CUBE;
2348                 break;
2349
2350             default:
2351                 FIXME("Unrecognized texture type %#x, using 2D.\n",
2352                         IWineD3DBaseTexture_GetTextureDimensions(textures[i]));
2353                 sampler_type[i] = WINED3DSTT_2D;
2354         }
2355     }
2356 }