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