wined3d: The stateblock doesn't have a parent.
[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 *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 *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         IUnknown *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 == 0) 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 == 0)
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 == 0) 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 void shader_get_parent(IWineD3DBaseShaderImpl *shader, IUnknown **parent)
1538 {
1539     *parent = shader->baseShader.parent;
1540     IUnknown_AddRef(*parent);
1541     TRACE("shader %p, returning %p.\n", shader, *parent);
1542 }
1543
1544 static HRESULT shader_get_function(IWineD3DBaseShaderImpl *shader, void *data, UINT *data_size)
1545 {
1546     if (!data)
1547     {
1548         *data_size = shader->baseShader.functionLength;
1549         return WINED3D_OK;
1550     }
1551
1552     if (*data_size < shader->baseShader.functionLength)
1553     {
1554         /* MSDN claims (for d3d8 at least) that if *pSizeOfData is smaller
1555          * than the required size we should write the required size and
1556          * return D3DERR_MOREDATA. That's not actually true. */
1557         return WINED3DERR_INVALIDCALL;
1558     }
1559
1560     memcpy(data, shader->baseShader.function, shader->baseShader.functionLength);
1561
1562     return WINED3D_OK;
1563 }
1564
1565 static HRESULT shader_set_function(IWineD3DBaseShaderImpl *shader, const DWORD *byte_code,
1566         const struct wined3d_shader_signature *output_signature, DWORD float_const_count)
1567 {
1568     struct shader_reg_maps *reg_maps = &shader->baseShader.reg_maps;
1569     const struct wined3d_shader_frontend *fe;
1570     HRESULT hr;
1571
1572     TRACE("shader %p, byte_code %p, output_signature %p, float_const_count %u.\n",
1573             shader, byte_code, output_signature, float_const_count);
1574
1575     fe = shader_select_frontend(*byte_code);
1576     if (!fe)
1577     {
1578         FIXME("Unable to find frontend for shader.\n");
1579         return WINED3DERR_INVALIDCALL;
1580     }
1581     shader->baseShader.frontend = fe;
1582     shader->baseShader.frontend_data = fe->shader_init(byte_code, output_signature);
1583     if (!shader->baseShader.frontend_data)
1584     {
1585         FIXME("Failed to initialize frontend.\n");
1586         return WINED3DERR_INVALIDCALL;
1587     }
1588
1589     /* First pass: trace shader. */
1590     if (TRACE_ON(d3d_shader)) shader_trace_init(fe, shader->baseShader.frontend_data, byte_code);
1591
1592     /* Initialize immediate constant lists. */
1593     list_init(&shader->baseShader.constantsF);
1594     list_init(&shader->baseShader.constantsB);
1595     list_init(&shader->baseShader.constantsI);
1596
1597     /* Second pass: figure out which registers are used, what the semantics are, etc. */
1598     hr = shader_get_registers_used((IWineD3DBaseShader *)shader, fe,
1599             reg_maps, shader->baseShader.input_signature, shader->baseShader.output_signature,
1600             byte_code, float_const_count);
1601     if (FAILED(hr)) return hr;
1602
1603     shader->baseShader.function = HeapAlloc(GetProcessHeap(), 0, shader->baseShader.functionLength);
1604     if (!shader->baseShader.function) return E_OUTOFMEMORY;
1605     memcpy(shader->baseShader.function, byte_code, shader->baseShader.functionLength);
1606
1607     return WINED3D_OK;
1608 }
1609
1610 static HRESULT STDMETHODCALLTYPE vertexshader_QueryInterface(IWineD3DVertexShader *iface, REFIID riid, void **object)
1611 {
1612     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1613
1614     if (IsEqualGUID(riid, &IID_IWineD3DVertexShader)
1615             || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1616             || IsEqualGUID(riid, &IID_IWineD3DBase)
1617             || IsEqualGUID(riid, &IID_IUnknown))
1618     {
1619         IUnknown_AddRef(iface);
1620         *object = iface;
1621         return S_OK;
1622     }
1623
1624     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1625
1626     *object = NULL;
1627     return E_NOINTERFACE;
1628 }
1629
1630 static ULONG STDMETHODCALLTYPE vertexshader_AddRef(IWineD3DVertexShader *iface)
1631 {
1632     IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
1633     ULONG refcount = InterlockedIncrement(&shader->baseShader.ref);
1634
1635     TRACE("%p increasing refcount to %u.\n", shader, refcount);
1636
1637     return refcount;
1638 }
1639
1640 static ULONG STDMETHODCALLTYPE vertexshader_Release(IWineD3DVertexShader *iface)
1641 {
1642     IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
1643     ULONG refcount = InterlockedDecrement(&shader->baseShader.ref);
1644
1645     TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1646
1647     if (!refcount)
1648     {
1649         shader_cleanup((IWineD3DBaseShader *)iface);
1650         shader->baseShader.parent_ops->wined3d_object_destroyed(shader->baseShader.parent);
1651         HeapFree(GetProcessHeap(), 0, shader);
1652     }
1653
1654     return refcount;
1655 }
1656
1657 static HRESULT STDMETHODCALLTYPE vertexshader_GetParent(IWineD3DVertexShader *iface, IUnknown **parent)
1658 {
1659     TRACE("iface %p, parent %p.\n", iface, parent);
1660
1661     shader_get_parent((IWineD3DBaseShaderImpl *)iface, parent);
1662
1663     return WINED3D_OK;
1664 }
1665
1666 static HRESULT STDMETHODCALLTYPE vertexshader_GetFunction(IWineD3DVertexShader *iface, void *data, UINT *data_size)
1667 {
1668     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
1669
1670     return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
1671 }
1672
1673 /* Set local constants for d3d8 shaders. */
1674 static HRESULT STDMETHODCALLTYPE vertexshader_SetLocalConstantsF(IWineD3DVertexShader *iface,
1675         UINT start_idx, const float *src_data, UINT count)
1676 {
1677     IWineD3DVertexShaderImpl *shader =(IWineD3DVertexShaderImpl *)iface;
1678     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
1679     UINT i, end_idx;
1680
1681     TRACE("iface %p, start_idx %u, src_data %p, count %u.\n", iface, start_idx, src_data, count);
1682
1683     end_idx = start_idx + count;
1684     if (end_idx > device->d3d_vshader_constantF)
1685     {
1686         WARN("end_idx %u > float constants limit %u.\n", end_idx, device->d3d_vshader_constantF);
1687         end_idx = device->d3d_vshader_constantF;
1688     }
1689
1690     for (i = start_idx; i < end_idx; ++i)
1691     {
1692         local_constant* lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(local_constant));
1693         if (!lconst) return E_OUTOFMEMORY;
1694
1695         lconst->idx = i;
1696         memcpy(lconst->value, src_data + (i - start_idx) * 4 /* 4 components */, 4 * sizeof(float));
1697         list_add_head(&shader->baseShader.constantsF, &lconst->entry);
1698     }
1699
1700     return WINED3D_OK;
1701 }
1702
1703 static const IWineD3DVertexShaderVtbl IWineD3DVertexShader_Vtbl =
1704 {
1705     /* IUnknown methods */
1706     vertexshader_QueryInterface,
1707     vertexshader_AddRef,
1708     vertexshader_Release,
1709     /* IWineD3DBase methods */
1710     vertexshader_GetParent,
1711     /* IWineD3DBaseShader methods */
1712     vertexshader_GetFunction,
1713     /* IWineD3DVertexShader methods */
1714     vertexshader_SetLocalConstantsF,
1715 };
1716
1717 void find_vs_compile_args(IWineD3DVertexShaderImpl *shader,
1718         IWineD3DStateBlockImpl *stateblock, struct vs_compile_args *args)
1719 {
1720     args->fog_src = stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE ? VS_FOG_COORD : VS_FOG_Z;
1721     args->clip_enabled = stateblock->renderState[WINED3DRS_CLIPPING]
1722             && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
1723     args->swizzle_map = ((IWineD3DDeviceImpl *)shader->baseShader.device)->strided_streams.swizzle_map;
1724 }
1725
1726 static BOOL match_usage(BYTE usage1, BYTE usage_idx1, BYTE usage2, BYTE usage_idx2)
1727 {
1728     if (usage_idx1 != usage_idx2) return FALSE;
1729     if (usage1 == usage2) return TRUE;
1730     if (usage1 == WINED3DDECLUSAGE_POSITION && usage2 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
1731     if (usage2 == WINED3DDECLUSAGE_POSITION && usage1 == WINED3DDECLUSAGE_POSITIONT) return TRUE;
1732
1733     return FALSE;
1734 }
1735
1736 BOOL vshader_get_input(IWineD3DVertexShader *iface, BYTE usage_req, BYTE usage_idx_req, unsigned int *regnum)
1737 {
1738     IWineD3DVertexShaderImpl *shader = (IWineD3DVertexShaderImpl *)iface;
1739     WORD map = shader->baseShader.reg_maps.input_registers;
1740     unsigned int i;
1741
1742     for (i = 0; map; map >>= 1, ++i)
1743     {
1744         if (!(map & 1)) continue;
1745
1746         if (match_usage(shader->attributes[i].usage,
1747                 shader->attributes[i].usage_idx, usage_req, usage_idx_req))
1748         {
1749             *regnum = i;
1750             return TRUE;
1751         }
1752     }
1753     return FALSE;
1754 }
1755
1756 static void vertexshader_set_limits(IWineD3DVertexShaderImpl *shader)
1757 {
1758     DWORD shader_version = WINED3D_SHADER_VERSION(shader->baseShader.reg_maps.shader_version.major,
1759             shader->baseShader.reg_maps.shader_version.minor);
1760     IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *)shader->baseShader.device;
1761
1762     shader->baseShader.limits.texcoord = 0;
1763     shader->baseShader.limits.attributes = 16;
1764     shader->baseShader.limits.packed_input = 0;
1765
1766     switch (shader_version)
1767     {
1768         case WINED3D_SHADER_VERSION(1, 0):
1769         case WINED3D_SHADER_VERSION(1, 1):
1770             shader->baseShader.limits.temporary = 12;
1771             shader->baseShader.limits.constant_bool = 0;
1772             shader->baseShader.limits.constant_int = 0;
1773             shader->baseShader.limits.address = 1;
1774             shader->baseShader.limits.packed_output = 12;
1775             shader->baseShader.limits.sampler = 0;
1776             shader->baseShader.limits.label = 0;
1777             /* TODO: vs_1_1 has a minimum of 96 constants. What happens when
1778              * a vs_1_1 shader is used on a vs_3_0 capable card that has 256
1779              * constants? */
1780             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1781             break;
1782
1783         case WINED3D_SHADER_VERSION(2, 0):
1784         case WINED3D_SHADER_VERSION(2, 1):
1785             shader->baseShader.limits.temporary = 12;
1786             shader->baseShader.limits.constant_bool = 16;
1787             shader->baseShader.limits.constant_int = 16;
1788             shader->baseShader.limits.address = 1;
1789             shader->baseShader.limits.packed_output = 12;
1790             shader->baseShader.limits.sampler = 0;
1791             shader->baseShader.limits.label = 16;
1792             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1793             break;
1794
1795         case WINED3D_SHADER_VERSION(4, 0):
1796             FIXME("Using 3.0 limits for 4.0 shader.\n");
1797             /* Fall through. */
1798
1799         case WINED3D_SHADER_VERSION(3, 0):
1800             shader->baseShader.limits.temporary = 32;
1801             shader->baseShader.limits.constant_bool = 32;
1802             shader->baseShader.limits.constant_int = 32;
1803             shader->baseShader.limits.address = 1;
1804             shader->baseShader.limits.packed_output = 12;
1805             shader->baseShader.limits.sampler = 4;
1806             shader->baseShader.limits.label = 16; /* FIXME: 2048 */
1807             /* DX10 cards on Windows advertise a d3d9 constant limit of 256
1808              * even though they are capable of supporting much more (GL
1809              * drivers advertise 1024). d3d9.dll and d3d8.dll clamp the
1810              * wined3d-advertised maximum. Clamp the constant limit for <= 3.0
1811              * shaders to 256. */
1812             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1813             break;
1814
1815         default:
1816             shader->baseShader.limits.temporary = 12;
1817             shader->baseShader.limits.constant_bool = 16;
1818             shader->baseShader.limits.constant_int = 16;
1819             shader->baseShader.limits.address = 1;
1820             shader->baseShader.limits.packed_output = 12;
1821             shader->baseShader.limits.sampler = 0;
1822             shader->baseShader.limits.label = 16;
1823             shader->baseShader.limits.constant_float = min(256, device->d3d_vshader_constantF);
1824             FIXME("Unrecognized vertex shader version \"%u.%u\".\n",
1825                     shader->baseShader.reg_maps.shader_version.major,
1826                     shader->baseShader.reg_maps.shader_version.minor);
1827     }
1828 }
1829
1830 HRESULT vertexshader_init(IWineD3DVertexShaderImpl *shader, IWineD3DDeviceImpl *device,
1831         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
1832         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1833 {
1834     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
1835     struct shader_reg_maps *reg_maps = &shader->baseShader.reg_maps;
1836     unsigned int i;
1837     HRESULT hr;
1838     WORD map;
1839
1840     if (!byte_code) return WINED3DERR_INVALIDCALL;
1841
1842     shader->lpVtbl = &IWineD3DVertexShader_Vtbl;
1843     shader_init(&shader->baseShader, device, parent, parent_ops);
1844
1845     hr = shader_set_function((IWineD3DBaseShaderImpl *)shader, byte_code,
1846             output_signature, device->d3d_vshader_constantF);
1847     if (FAILED(hr))
1848     {
1849         WARN("Failed to set function, hr %#x.\n", hr);
1850         shader_cleanup((IWineD3DBaseShader *)shader);
1851         return hr;
1852     }
1853
1854     map = shader->baseShader.reg_maps.input_registers;
1855     for (i = 0; map; map >>= 1, ++i)
1856     {
1857         if (!(map & 1) || !shader->baseShader.input_signature[i].semantic_name) continue;
1858
1859         shader->attributes[i].usage =
1860                 shader_usage_from_semantic_name(shader->baseShader.input_signature[i].semantic_name);
1861         shader->attributes[i].usage_idx = shader->baseShader.input_signature[i].semantic_idx;
1862     }
1863
1864     if (output_signature)
1865     {
1866         for (i = 0; i < output_signature->element_count; ++i)
1867         {
1868             struct wined3d_shader_signature_element *e = &output_signature->elements[i];
1869             reg_maps->output_registers |= 1 << e->register_idx;
1870             shader->baseShader.output_signature[e->register_idx] = *e;
1871         }
1872     }
1873
1874     vertexshader_set_limits(shader);
1875
1876     if (device->vs_selected_mode == SHADER_ARB
1877             && (gl_info->quirks & WINED3D_QUIRK_ARB_VS_OFFSET_LIMIT)
1878             && shader->min_rel_offset <= shader->max_rel_offset)
1879     {
1880         if (shader->max_rel_offset - shader->min_rel_offset > 127)
1881         {
1882             FIXME("The difference between the minimum and maximum relative offset is > 127.\n");
1883             FIXME("Which this OpenGL implementation does not support. Try using GLSL.\n");
1884             FIXME("Min: %d, Max: %d.\n", shader->min_rel_offset, shader->max_rel_offset);
1885         }
1886         else if (shader->max_rel_offset - shader->min_rel_offset > 63)
1887         {
1888             shader->rel_offset = shader->min_rel_offset + 63;
1889         }
1890         else if (shader->max_rel_offset > 63)
1891         {
1892             shader->rel_offset = shader->min_rel_offset;
1893         }
1894         else
1895         {
1896             shader->rel_offset = 0;
1897         }
1898     }
1899
1900     shader->baseShader.load_local_constsF = shader->baseShader.reg_maps.usesrelconstF
1901             && !list_empty(&shader->baseShader.constantsF);
1902
1903     return WINED3D_OK;
1904 }
1905
1906 static HRESULT STDMETHODCALLTYPE geometryshader_QueryInterface(IWineD3DGeometryShader *iface,
1907         REFIID riid, void **object)
1908 {
1909     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
1910
1911     if (IsEqualGUID(riid, &IID_IWineD3DGeometryShader)
1912             || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
1913             || IsEqualGUID(riid, &IID_IWineD3DBase)
1914             || IsEqualGUID(riid, &IID_IUnknown))
1915     {
1916         IUnknown_AddRef(iface);
1917         *object = iface;
1918         return S_OK;
1919     }
1920
1921     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
1922
1923     *object = NULL;
1924     return E_NOINTERFACE;
1925 }
1926
1927 static ULONG STDMETHODCALLTYPE geometryshader_AddRef(IWineD3DGeometryShader *iface)
1928 {
1929     struct wined3d_geometryshader *shader = (struct wined3d_geometryshader *)iface;
1930     ULONG refcount = InterlockedIncrement(&shader->base_shader.ref);
1931
1932     TRACE("%p increasing refcount to %u.\n", shader, refcount);
1933
1934     return refcount;
1935 }
1936
1937 static ULONG STDMETHODCALLTYPE geometryshader_Release(IWineD3DGeometryShader *iface)
1938 {
1939     struct wined3d_geometryshader *shader = (struct wined3d_geometryshader *)iface;
1940     ULONG refcount = InterlockedDecrement(&shader->base_shader.ref);
1941
1942     TRACE("%p decreasing refcount to %u.\n", shader, refcount);
1943
1944     if (!refcount)
1945     {
1946         shader_cleanup((IWineD3DBaseShader *)iface);
1947         shader->base_shader.parent_ops->wined3d_object_destroyed(shader->base_shader.parent);
1948         HeapFree(GetProcessHeap(), 0, shader);
1949     }
1950
1951     return refcount;
1952 }
1953
1954 static HRESULT STDMETHODCALLTYPE geometryshader_GetParent(IWineD3DGeometryShader *iface, IUnknown **parent)
1955 {
1956     TRACE("iface %p, parent %p.\n", iface, parent);
1957
1958     shader_get_parent((IWineD3DBaseShaderImpl *)iface, parent);
1959
1960     return WINED3D_OK;
1961 }
1962
1963 static HRESULT STDMETHODCALLTYPE geometryshader_GetFunction(IWineD3DGeometryShader *iface, void *data, UINT *data_size)
1964 {
1965     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
1966
1967     return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
1968 }
1969
1970 static const IWineD3DGeometryShaderVtbl wined3d_geometryshader_vtbl =
1971 {
1972     /* IUnknown methods */
1973     geometryshader_QueryInterface,
1974     geometryshader_AddRef,
1975     geometryshader_Release,
1976     /* IWineD3DBase methods */
1977     geometryshader_GetParent,
1978     /* IWineD3DBaseShader methods */
1979     geometryshader_GetFunction,
1980 };
1981
1982 HRESULT geometryshader_init(struct wined3d_geometryshader *shader, IWineD3DDeviceImpl *device,
1983         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
1984         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
1985 {
1986     HRESULT hr;
1987
1988     shader->vtbl = &wined3d_geometryshader_vtbl;
1989     shader_init(&shader->base_shader, device, parent, parent_ops);
1990
1991     hr = shader_set_function((IWineD3DBaseShaderImpl *)shader, byte_code, output_signature, 0);
1992     if (FAILED(hr))
1993     {
1994         WARN("Failed to set function, hr %#x.\n", hr);
1995         shader_cleanup((IWineD3DBaseShader *)shader);
1996         return hr;
1997     }
1998
1999     shader->base_shader.load_local_constsF = FALSE;
2000
2001     return WINED3D_OK;
2002 }
2003
2004 static HRESULT STDMETHODCALLTYPE pixelshader_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, void **object)
2005 {
2006     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
2007
2008     if (IsEqualGUID(riid, &IID_IWineD3DPixelShader)
2009             || IsEqualGUID(riid, &IID_IWineD3DBaseShader)
2010             || IsEqualGUID(riid, &IID_IWineD3DBase)
2011             || IsEqualGUID(riid, &IID_IUnknown))
2012     {
2013         IUnknown_AddRef(iface);
2014         *object = iface;
2015         return S_OK;
2016     }
2017
2018     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
2019
2020     *object = NULL;
2021     return E_NOINTERFACE;
2022 }
2023
2024 static ULONG STDMETHODCALLTYPE pixelshader_AddRef(IWineD3DPixelShader *iface)
2025 {
2026     IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)iface;
2027     ULONG refcount = InterlockedIncrement(&shader->baseShader.ref);
2028
2029     TRACE("%p increasing refcount to %u.\n", shader, refcount);
2030
2031     return refcount;
2032 }
2033
2034 static ULONG STDMETHODCALLTYPE pixelshader_Release(IWineD3DPixelShader *iface)
2035 {
2036     IWineD3DPixelShaderImpl *shader = (IWineD3DPixelShaderImpl *)iface;
2037     ULONG refcount = InterlockedDecrement(&shader->baseShader.ref);
2038
2039     TRACE("%p decreasing refcount to %u.\n", shader, refcount);
2040
2041     if (!refcount)
2042     {
2043         shader_cleanup((IWineD3DBaseShader *)iface);
2044         shader->baseShader.parent_ops->wined3d_object_destroyed(shader->baseShader.parent);
2045         HeapFree(GetProcessHeap(), 0, shader);
2046     }
2047
2048     return refcount;
2049 }
2050
2051 static HRESULT STDMETHODCALLTYPE pixelshader_GetParent(IWineD3DPixelShader *iface, IUnknown **parent)
2052 {
2053     TRACE("iface %p, parent %p.\n", iface, parent);
2054
2055     shader_get_parent((IWineD3DBaseShaderImpl *)iface, parent);
2056
2057     return WINED3D_OK;
2058 }
2059
2060 static HRESULT STDMETHODCALLTYPE pixelshader_GetFunction(IWineD3DPixelShader *iface, void *data, UINT *data_size)
2061 {
2062     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
2063
2064     return shader_get_function((IWineD3DBaseShaderImpl *)iface, data, data_size);
2065 }
2066
2067 static const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
2068 {
2069     /* IUnknown methods */
2070     pixelshader_QueryInterface,
2071     pixelshader_AddRef,
2072     pixelshader_Release,
2073     /* IWineD3DBase methods */
2074     pixelshader_GetParent,
2075     /* IWineD3DBaseShader methods */
2076     pixelshader_GetFunction
2077 };
2078
2079 void find_ps_compile_args(IWineD3DPixelShaderImpl *shader,
2080         IWineD3DStateBlockImpl *stateblock, struct ps_compile_args *args)
2081 {
2082     IWineD3DBaseTextureImpl *texture;
2083     IWineD3DDeviceImpl *device = stateblock->device;
2084     UINT i;
2085
2086     memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set. */
2087     if (stateblock->renderState[WINED3DRS_SRGBWRITEENABLE])
2088     {
2089         IWineD3DSurfaceImpl *rt = device->render_targets[0];
2090         if(rt->resource.format_desc->Flags & WINED3DFMT_FLAG_SRGB_WRITE) args->srgb_correction = 1;
2091     }
2092
2093     args->np2_fixup = 0;
2094
2095     for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
2096     {
2097         if (!shader->baseShader.reg_maps.sampler_type[i]) continue;
2098         texture = (IWineD3DBaseTextureImpl *)stateblock->textures[i];
2099         if (!texture)
2100         {
2101             args->color_fixup[i] = COLOR_FIXUP_IDENTITY;
2102             continue;
2103         }
2104         args->color_fixup[i] = texture->resource.format_desc->color_fixup;
2105
2106         if (texture->resource.format_desc->Flags & WINED3DFMT_FLAG_SHADOW)
2107             args->shadow |= 1 << i;
2108
2109         /* Flag samplers that need NP2 texcoord fixup. */
2110         if (!texture->baseTexture.pow2Matrix_identity)
2111         {
2112             args->np2_fixup |= (1 << i);
2113         }
2114     }
2115     if (shader->baseShader.reg_maps.shader_version.major >= 3)
2116     {
2117         if (device->strided_streams.position_transformed)
2118         {
2119             args->vp_mode = pretransformed;
2120         }
2121         else if (use_vs(stateblock))
2122         {
2123             args->vp_mode = vertexshader;
2124         }
2125         else
2126         {
2127             args->vp_mode = fixedfunction;
2128         }
2129         args->fog = FOG_OFF;
2130     }
2131     else
2132     {
2133         args->vp_mode = vertexshader;
2134         if (stateblock->renderState[WINED3DRS_FOGENABLE])
2135         {
2136             switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE])
2137             {
2138                 case WINED3DFOG_NONE:
2139                     if (device->strided_streams.position_transformed || use_vs(stateblock))
2140                     {
2141                         args->fog = FOG_LINEAR;
2142                         break;
2143                     }
2144
2145                     switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE])
2146                     {
2147                         case WINED3DFOG_NONE: /* Fall through. */
2148                         case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
2149                         case WINED3DFOG_EXP:    args->fog = FOG_EXP;    break;
2150                         case WINED3DFOG_EXP2:   args->fog = FOG_EXP2;   break;
2151                     }
2152                     break;
2153
2154                 case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
2155                 case WINED3DFOG_EXP:    args->fog = FOG_EXP;    break;
2156                 case WINED3DFOG_EXP2:   args->fog = FOG_EXP2;   break;
2157             }
2158         }
2159         else
2160         {
2161             args->fog = FOG_OFF;
2162         }
2163     }
2164 }
2165
2166 static void pixelshader_set_limits(IWineD3DPixelShaderImpl *shader)
2167 {
2168     DWORD shader_version = WINED3D_SHADER_VERSION(shader->baseShader.reg_maps.shader_version.major,
2169             shader->baseShader.reg_maps.shader_version.minor);
2170
2171     shader->baseShader.limits.attributes = 0;
2172     shader->baseShader.limits.address = 0;
2173     shader->baseShader.limits.packed_output = 0;
2174
2175     switch (shader_version)
2176     {
2177         case WINED3D_SHADER_VERSION(1, 0):
2178         case WINED3D_SHADER_VERSION(1, 1):
2179         case WINED3D_SHADER_VERSION(1, 2):
2180         case WINED3D_SHADER_VERSION(1, 3):
2181             shader->baseShader.limits.temporary = 2;
2182             shader->baseShader.limits.constant_float = 8;
2183             shader->baseShader.limits.constant_int = 0;
2184             shader->baseShader.limits.constant_bool = 0;
2185             shader->baseShader.limits.texcoord = 4;
2186             shader->baseShader.limits.sampler = 4;
2187             shader->baseShader.limits.packed_input = 0;
2188             shader->baseShader.limits.label = 0;
2189             break;
2190
2191         case WINED3D_SHADER_VERSION(1, 4):
2192             shader->baseShader.limits.temporary = 6;
2193             shader->baseShader.limits.constant_float = 8;
2194             shader->baseShader.limits.constant_int = 0;
2195             shader->baseShader.limits.constant_bool = 0;
2196             shader->baseShader.limits.texcoord = 6;
2197             shader->baseShader.limits.sampler = 6;
2198             shader->baseShader.limits.packed_input = 0;
2199             shader->baseShader.limits.label = 0;
2200             break;
2201
2202         /* FIXME: Temporaries must match D3DPSHADERCAPS2_0.NumTemps. */
2203         case WINED3D_SHADER_VERSION(2, 0):
2204             shader->baseShader.limits.temporary = 32;
2205             shader->baseShader.limits.constant_float = 32;
2206             shader->baseShader.limits.constant_int = 16;
2207             shader->baseShader.limits.constant_bool = 16;
2208             shader->baseShader.limits.texcoord = 8;
2209             shader->baseShader.limits.sampler = 16;
2210             shader->baseShader.limits.packed_input = 0;
2211             break;
2212
2213         case WINED3D_SHADER_VERSION(2, 1):
2214             shader->baseShader.limits.temporary = 32;
2215             shader->baseShader.limits.constant_float = 32;
2216             shader->baseShader.limits.constant_int = 16;
2217             shader->baseShader.limits.constant_bool = 16;
2218             shader->baseShader.limits.texcoord = 8;
2219             shader->baseShader.limits.sampler = 16;
2220             shader->baseShader.limits.packed_input = 0;
2221             shader->baseShader.limits.label = 16;
2222             break;
2223
2224         case WINED3D_SHADER_VERSION(4, 0):
2225             FIXME("Using 3.0 limits for 4.0 shader.\n");
2226             /* Fall through. */
2227
2228         case WINED3D_SHADER_VERSION(3, 0):
2229             shader->baseShader.limits.temporary = 32;
2230             shader->baseShader.limits.constant_float = 224;
2231             shader->baseShader.limits.constant_int = 16;
2232             shader->baseShader.limits.constant_bool = 16;
2233             shader->baseShader.limits.texcoord = 0;
2234             shader->baseShader.limits.sampler = 16;
2235             shader->baseShader.limits.packed_input = 12;
2236             shader->baseShader.limits.label = 16; /* FIXME: 2048 */
2237             break;
2238
2239         default:
2240             shader->baseShader.limits.temporary = 32;
2241             shader->baseShader.limits.constant_float = 32;
2242             shader->baseShader.limits.constant_int = 16;
2243             shader->baseShader.limits.constant_bool = 16;
2244             shader->baseShader.limits.texcoord = 8;
2245             shader->baseShader.limits.sampler = 16;
2246             shader->baseShader.limits.packed_input = 0;
2247             shader->baseShader.limits.label = 0;
2248             FIXME("Unrecognized pixel shader version %u.%u\n",
2249                     shader->baseShader.reg_maps.shader_version.major,
2250                     shader->baseShader.reg_maps.shader_version.minor);
2251     }
2252 }
2253
2254 HRESULT pixelshader_init(IWineD3DPixelShaderImpl *shader, IWineD3DDeviceImpl *device,
2255         const DWORD *byte_code, const struct wined3d_shader_signature *output_signature,
2256         IUnknown *parent, const struct wined3d_parent_ops *parent_ops)
2257 {
2258     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
2259     unsigned int i, highest_reg_used = 0, num_regs_used = 0;
2260     HRESULT hr;
2261
2262     if (!byte_code) return WINED3DERR_INVALIDCALL;
2263
2264     shader->lpVtbl = &IWineD3DPixelShader_Vtbl;
2265     shader_init(&shader->baseShader, device, parent, parent_ops);
2266
2267     hr = shader_set_function((IWineD3DBaseShaderImpl *)shader, byte_code,
2268             output_signature, device->d3d_pshader_constantF);
2269     if (FAILED(hr))
2270     {
2271         WARN("Failed to set function, hr %#x.\n", hr);
2272         shader_cleanup((IWineD3DBaseShader *)shader);
2273         return hr;
2274     }
2275
2276     pixelshader_set_limits(shader);
2277
2278     for (i = 0; i < MAX_REG_INPUT; ++i)
2279     {
2280         if (shader->input_reg_used[i])
2281         {
2282             ++num_regs_used;
2283             highest_reg_used = i;
2284         }
2285     }
2286
2287     /* Don't do any register mapping magic if it is not needed, or if we can't
2288      * achieve anything anyway */
2289     if (highest_reg_used < (gl_info->limits.glsl_varyings / 4)
2290             || num_regs_used > (gl_info->limits.glsl_varyings / 4))
2291     {
2292         if (num_regs_used > (gl_info->limits.glsl_varyings / 4))
2293         {
2294             /* This happens with relative addressing. The input mapper function
2295              * warns about this if the higher registers are declared too, so
2296              * don't write a FIXME here */
2297             WARN("More varying registers used than supported\n");
2298         }
2299
2300         for (i = 0; i < MAX_REG_INPUT; ++i)
2301         {
2302             shader->input_reg_map[i] = i;
2303         }
2304
2305         shader->declared_in_count = highest_reg_used + 1;
2306     }
2307     else
2308     {
2309         shader->declared_in_count = 0;
2310         for (i = 0; i < MAX_REG_INPUT; ++i)
2311         {
2312             if (shader->input_reg_used[i]) shader->input_reg_map[i] = shader->declared_in_count++;
2313             else shader->input_reg_map[i] = ~0U;
2314         }
2315     }
2316
2317     shader->baseShader.load_local_constsF = FALSE;
2318
2319     return WINED3D_OK;
2320 }
2321
2322 void pixelshader_update_samplers(struct shader_reg_maps *reg_maps, IWineD3DBaseTexture * const *textures)
2323 {
2324     WINED3DSAMPLER_TEXTURE_TYPE *sampler_type = reg_maps->sampler_type;
2325     unsigned int i;
2326
2327     if (reg_maps->shader_version.major != 1) return;
2328
2329     for (i = 0; i < max(MAX_FRAGMENT_SAMPLERS, MAX_VERTEX_SAMPLERS); ++i)
2330     {
2331         /* We don't sample from this sampler. */
2332         if (!sampler_type[i]) continue;
2333
2334         if (!textures[i])
2335         {
2336             WARN("No texture bound to sampler %u, using 2D.\n", i);
2337             sampler_type[i] = WINED3DSTT_2D;
2338             continue;
2339         }
2340
2341         switch (IWineD3DBaseTexture_GetTextureDimensions(textures[i]))
2342         {
2343             case GL_TEXTURE_RECTANGLE_ARB:
2344             case GL_TEXTURE_2D:
2345                 /* We have to select between texture rectangles and 2D
2346                  * textures later because 2.0 and 3.0 shaders only have
2347                  * WINED3DSTT_2D as well. */
2348                 sampler_type[i] = WINED3DSTT_2D;
2349                 break;
2350
2351             case GL_TEXTURE_3D:
2352                 sampler_type[i] = WINED3DSTT_VOLUME;
2353                 break;
2354
2355             case GL_TEXTURE_CUBE_MAP_ARB:
2356                 sampler_type[i] = WINED3DSTT_CUBE;
2357                 break;
2358
2359             default:
2360                 FIXME("Unrecognized texture type %#x, using 2D.\n",
2361                         IWineD3DBaseTexture_GetTextureDimensions(textures[i]));
2362                 sampler_type[i] = WINED3DSTT_2D;
2363         }
2364     }
2365 }