po: Update French translation.
[wine] / dlls / d3dcompiler_43 / utils.c
1 /*
2  * Copyright 2008 Stefan Dösinger
3  * Copyright 2009 Matteo Bruni
4  * Copyright 2008-2009 Henri Verbeet for CodeWeavers
5  * Copyright 2010 Rico Schüller
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  *
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdio.h>
27
28 #include "d3dcompiler_private.h"
29
30 WINE_DEFAULT_DEBUG_CHANNEL(d3dcompiler);
31
32 #define WINE_D3DCOMPILER_TO_STR(x) case x: return #x
33
34 const char *debug_d3dcompiler_shader_variable_class(D3D_SHADER_VARIABLE_CLASS c)
35 {
36     switch (c)
37     {
38         WINE_D3DCOMPILER_TO_STR(D3D_SVC_SCALAR);
39         WINE_D3DCOMPILER_TO_STR(D3D_SVC_VECTOR);
40         WINE_D3DCOMPILER_TO_STR(D3D_SVC_MATRIX_ROWS);
41         WINE_D3DCOMPILER_TO_STR(D3D_SVC_MATRIX_COLUMNS);
42         WINE_D3DCOMPILER_TO_STR(D3D_SVC_OBJECT);
43         WINE_D3DCOMPILER_TO_STR(D3D_SVC_STRUCT);
44         WINE_D3DCOMPILER_TO_STR(D3D_SVC_INTERFACE_CLASS);
45         WINE_D3DCOMPILER_TO_STR(D3D_SVC_INTERFACE_POINTER);
46         default:
47             FIXME("Unrecognized D3D_SHADER_VARIABLE_CLASS %#x.\n", c);
48             return "unrecognized";
49     }
50 }
51
52 const char *debug_d3dcompiler_shader_variable_type(D3D_SHADER_VARIABLE_TYPE t)
53 {
54     switch (t)
55     {
56         WINE_D3DCOMPILER_TO_STR(D3D_SVT_VOID);
57         WINE_D3DCOMPILER_TO_STR(D3D_SVT_BOOL);
58         WINE_D3DCOMPILER_TO_STR(D3D_SVT_INT);
59         WINE_D3DCOMPILER_TO_STR(D3D_SVT_FLOAT);
60         WINE_D3DCOMPILER_TO_STR(D3D_SVT_STRING);
61         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE);
62         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE1D);
63         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE2D);
64         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE3D);
65         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURECUBE);
66         WINE_D3DCOMPILER_TO_STR(D3D_SVT_SAMPLER);
67         WINE_D3DCOMPILER_TO_STR(D3D_SVT_PIXELSHADER);
68         WINE_D3DCOMPILER_TO_STR(D3D_SVT_VERTEXSHADER);
69         WINE_D3DCOMPILER_TO_STR(D3D_SVT_UINT);
70         WINE_D3DCOMPILER_TO_STR(D3D_SVT_UINT8);
71         WINE_D3DCOMPILER_TO_STR(D3D_SVT_GEOMETRYSHADER);
72         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RASTERIZER);
73         WINE_D3DCOMPILER_TO_STR(D3D_SVT_DEPTHSTENCIL);
74         WINE_D3DCOMPILER_TO_STR(D3D_SVT_BLEND);
75         WINE_D3DCOMPILER_TO_STR(D3D_SVT_BUFFER);
76         WINE_D3DCOMPILER_TO_STR(D3D_SVT_CBUFFER);
77         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TBUFFER);
78         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE1DARRAY);
79         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE2DARRAY);
80         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RENDERTARGETVIEW);
81         WINE_D3DCOMPILER_TO_STR(D3D_SVT_DEPTHSTENCILVIEW);
82         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE2DMS);
83         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURE2DMSARRAY);
84         WINE_D3DCOMPILER_TO_STR(D3D_SVT_TEXTURECUBEARRAY);
85         WINE_D3DCOMPILER_TO_STR(D3D_SVT_HULLSHADER);
86         WINE_D3DCOMPILER_TO_STR(D3D_SVT_DOMAINSHADER);
87         WINE_D3DCOMPILER_TO_STR(D3D_SVT_INTERFACE_POINTER);
88         WINE_D3DCOMPILER_TO_STR(D3D_SVT_COMPUTESHADER);
89         WINE_D3DCOMPILER_TO_STR(D3D_SVT_DOUBLE);
90         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWTEXTURE1D);
91         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWTEXTURE1DARRAY);
92         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWTEXTURE2D);
93         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWTEXTURE2DARRAY);
94         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWTEXTURE3D);
95         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWBUFFER);
96         WINE_D3DCOMPILER_TO_STR(D3D_SVT_BYTEADDRESS_BUFFER);
97         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWBYTEADDRESS_BUFFER);
98         WINE_D3DCOMPILER_TO_STR(D3D_SVT_STRUCTURED_BUFFER);
99         WINE_D3DCOMPILER_TO_STR(D3D_SVT_RWSTRUCTURED_BUFFER);
100         WINE_D3DCOMPILER_TO_STR(D3D_SVT_APPEND_STRUCTURED_BUFFER);
101         WINE_D3DCOMPILER_TO_STR(D3D_SVT_CONSUME_STRUCTURED_BUFFER);
102         default:
103             FIXME("Unrecognized D3D_SHADER_VARIABLE_TYPE %#x.\n", t);
104             return "unrecognized";
105     }
106 }
107
108 const char *debug_d3dcompiler_d3d_blob_part(D3D_BLOB_PART part)
109 {
110     switch(part)
111     {
112         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_INPUT_SIGNATURE_BLOB);
113         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_OUTPUT_SIGNATURE_BLOB);
114         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB);
115         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_PATCH_CONSTANT_SIGNATURE_BLOB);
116         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_ALL_SIGNATURE_BLOB);
117         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_DEBUG_INFO);
118         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_LEGACY_SHADER);
119         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_XNA_PREPASS_SHADER);
120         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_XNA_SHADER);
121         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_TEST_ALTERNATE_SHADER);
122         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_TEST_COMPILE_DETAILS);
123         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_TEST_COMPILE_PERF);
124         default:
125             FIXME("Unrecognized D3D_BLOB_PART %#x\n", part);
126             return "unrecognized";
127     }
128 }
129
130 const char *debug_print_srcmod(DWORD mod)
131 {
132     switch (mod)
133     {
134         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_NEG);
135         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_BIAS);
136         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_BIASNEG);
137         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_SIGN);
138         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_SIGNNEG);
139         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_COMP);
140         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_X2);
141         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_X2NEG);
142         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_DZ);
143         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_DW);
144         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_ABS);
145         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_ABSNEG);
146         WINE_D3DCOMPILER_TO_STR(BWRITERSPSM_NOT);
147         default:
148             FIXME("Unrecognized source modifier %#x.\n", mod);
149             return "unrecognized_src_mod";
150     }
151 }
152
153 #undef WINE_D3DCOMPILER_TO_STR
154
155 const char *debug_print_dstmod(DWORD mod)
156 {
157     switch (mod)
158     {
159         case 0:
160             return "";
161         case BWRITERSPDM_SATURATE:
162             return "_sat";
163         case BWRITERSPDM_PARTIALPRECISION:
164             return "_pp";
165         case BWRITERSPDM_MSAMPCENTROID:
166             return "_centroid";
167         case BWRITERSPDM_SATURATE | BWRITERSPDM_PARTIALPRECISION:
168             return "_sat_pp";
169         case BWRITERSPDM_SATURATE | BWRITERSPDM_MSAMPCENTROID:
170             return "_sat_centroid";
171         case BWRITERSPDM_PARTIALPRECISION | BWRITERSPDM_MSAMPCENTROID:
172             return "_pp_centroid";
173         case BWRITERSPDM_SATURATE | BWRITERSPDM_PARTIALPRECISION | BWRITERSPDM_MSAMPCENTROID:
174             return "_sat_pp_centroid";
175         default:
176             return "Unexpected modifier\n";
177     }
178 }
179
180 const char *debug_print_shift(DWORD shift)
181 {
182     static const char * const shiftstrings[] =
183     {
184         "",
185         "_x2",
186         "_x4",
187         "_x8",
188         "_x16",
189         "_x32",
190         "",
191         "",
192         "",
193         "",
194         "",
195         "",
196         "_d16",
197         "_d8",
198         "_d4",
199         "_d2",
200     };
201     return shiftstrings[shift];
202 }
203
204 static const char *get_regname(const struct shader_reg *reg)
205 {
206     switch (reg->type)
207     {
208         case BWRITERSPR_TEMP:
209             return wine_dbg_sprintf("r%u", reg->regnum);
210         case BWRITERSPR_INPUT:
211             return wine_dbg_sprintf("v%u", reg->regnum);
212         case BWRITERSPR_CONST:
213             return wine_dbg_sprintf("c%u", reg->regnum);
214         case BWRITERSPR_ADDR:
215             return wine_dbg_sprintf("a%u", reg->regnum);
216         case BWRITERSPR_TEXTURE:
217             return wine_dbg_sprintf("t%u", reg->regnum);
218         case BWRITERSPR_RASTOUT:
219             switch (reg->regnum)
220             {
221                 case BWRITERSRO_POSITION:   return "oPos";
222                 case BWRITERSRO_FOG:        return "oFog";
223                 case BWRITERSRO_POINT_SIZE: return "oPts";
224                 default: return "Unexpected RASTOUT";
225             }
226         case BWRITERSPR_ATTROUT:
227             return wine_dbg_sprintf("oD%u", reg->regnum);
228         case BWRITERSPR_TEXCRDOUT:
229             return wine_dbg_sprintf("oT%u", reg->regnum);
230         case BWRITERSPR_OUTPUT:
231             return wine_dbg_sprintf("o%u", reg->regnum);
232         case BWRITERSPR_CONSTINT:
233             return wine_dbg_sprintf("i%u", reg->regnum);
234         case BWRITERSPR_COLOROUT:
235             return wine_dbg_sprintf("oC%u", reg->regnum);
236         case BWRITERSPR_DEPTHOUT:
237             return "oDepth";
238         case BWRITERSPR_SAMPLER:
239             return wine_dbg_sprintf("s%u", reg->regnum);
240         case BWRITERSPR_CONSTBOOL:
241             return wine_dbg_sprintf("b%u", reg->regnum);
242         case BWRITERSPR_LOOP:
243             return "aL";
244         case BWRITERSPR_MISCTYPE:
245             switch (reg->regnum)
246             {
247                 case 0: return "vPos";
248                 case 1: return "vFace";
249                 default: return "unexpected misctype";
250             }
251         case BWRITERSPR_LABEL:
252             return wine_dbg_sprintf("l%u", reg->regnum);
253         case BWRITERSPR_PREDICATE:
254             return wine_dbg_sprintf("p%u", reg->regnum);
255         default:
256             return wine_dbg_sprintf("unknown regname %#x", reg->type);
257     }
258 }
259
260 static const char *debug_print_writemask(DWORD mask)
261 {
262     char ret[6];
263     unsigned char pos = 1;
264
265     if(mask == BWRITERSP_WRITEMASK_ALL) return "";
266     ret[0] = '.';
267     if(mask & BWRITERSP_WRITEMASK_0) ret[pos++] = 'x';
268     if(mask & BWRITERSP_WRITEMASK_1) ret[pos++] = 'y';
269     if(mask & BWRITERSP_WRITEMASK_2) ret[pos++] = 'z';
270     if(mask & BWRITERSP_WRITEMASK_3) ret[pos++] = 'w';
271     ret[pos] = 0;
272
273     return wine_dbg_sprintf("%s", ret);
274 }
275
276 static const char *debug_print_swizzle(DWORD arg)
277 {
278     char ret[6];
279     unsigned int i;
280     DWORD swizzle[4];
281
282     switch (arg)
283     {
284         case BWRITERVS_NOSWIZZLE:
285             return "";
286         case BWRITERVS_SWIZZLE_X:
287             return ".x";
288         case BWRITERVS_SWIZZLE_Y:
289             return ".y";
290         case BWRITERVS_SWIZZLE_Z:
291             return ".z";
292         case BWRITERVS_SWIZZLE_W:
293             return ".w";
294     }
295
296     swizzle[0] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 0)) & 0x03;
297     swizzle[1] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 2)) & 0x03;
298     swizzle[2] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 4)) & 0x03;
299     swizzle[3] = (arg >> (BWRITERVS_SWIZZLE_SHIFT + 6)) & 0x03;
300
301     ret[0] = '.';
302     for (i = 0; i < 4; ++i)
303     {
304         switch (swizzle[i])
305         {
306             case 0: ret[1 + i] = 'x'; break;
307             case 1: ret[1 + i] = 'y'; break;
308             case 2: ret[1 + i] = 'z'; break;
309             case 3: ret[1 + i] = 'w'; break;
310         }
311     }
312     ret[5] = '\0';
313
314     return wine_dbg_sprintf("%s", ret);
315 }
316
317 static const char *debug_print_relarg(const struct shader_reg *reg)
318 {
319     const char *short_swizzle;
320     if (!reg->rel_reg) return "";
321
322     short_swizzle = debug_print_swizzle(reg->rel_reg->u.swizzle);
323
324     if (reg->rel_reg->type == BWRITERSPR_ADDR)
325         return wine_dbg_sprintf("[a%u%s]", reg->rel_reg->regnum, short_swizzle);
326     else if(reg->rel_reg->type == BWRITERSPR_LOOP && reg->rel_reg->regnum == 0)
327         return wine_dbg_sprintf("[aL%s]", short_swizzle);
328     else
329         return "Unexpected relative addressing argument";
330 }
331
332 const char *debug_print_dstreg(const struct shader_reg *reg)
333 {
334     return wine_dbg_sprintf("%s%s%s", get_regname(reg),
335             debug_print_relarg(reg),
336             debug_print_writemask(reg->u.writemask));
337 }
338
339 const char *debug_print_srcreg(const struct shader_reg *reg)
340 {
341     switch (reg->srcmod)
342     {
343         case BWRITERSPSM_NONE:
344             return wine_dbg_sprintf("%s%s%s", get_regname(reg),
345                     debug_print_relarg(reg),
346                     debug_print_swizzle(reg->u.swizzle));
347         case BWRITERSPSM_NEG:
348             return wine_dbg_sprintf("-%s%s%s", get_regname(reg),
349                     debug_print_relarg(reg),
350                     debug_print_swizzle(reg->u.swizzle));
351         case BWRITERSPSM_BIAS:
352             return wine_dbg_sprintf("%s%s_bias%s", get_regname(reg),
353                     debug_print_relarg(reg),
354                     debug_print_swizzle(reg->u.swizzle));
355         case BWRITERSPSM_BIASNEG:
356             return wine_dbg_sprintf("-%s%s_bias%s", get_regname(reg),
357                     debug_print_relarg(reg),
358                     debug_print_swizzle(reg->u.swizzle));
359         case BWRITERSPSM_SIGN:
360             return wine_dbg_sprintf("%s%s_bx2%s", get_regname(reg),
361                     debug_print_relarg(reg),
362                     debug_print_swizzle(reg->u.swizzle));
363         case BWRITERSPSM_SIGNNEG:
364             return wine_dbg_sprintf("-%s%s_bx2%s", get_regname(reg),
365                     debug_print_relarg(reg),
366                     debug_print_swizzle(reg->u.swizzle));
367         case BWRITERSPSM_COMP:
368             return wine_dbg_sprintf("1 - %s%s%s", get_regname(reg),
369                     debug_print_relarg(reg),
370                     debug_print_swizzle(reg->u.swizzle));
371         case BWRITERSPSM_X2:
372             return wine_dbg_sprintf("%s%s_x2%s", get_regname(reg),
373                     debug_print_relarg(reg),
374                     debug_print_swizzle(reg->u.swizzle));
375         case BWRITERSPSM_X2NEG:
376             return wine_dbg_sprintf("-%s%s_x2%s", get_regname(reg),
377                     debug_print_relarg(reg),
378                     debug_print_swizzle(reg->u.swizzle));
379         case BWRITERSPSM_DZ:
380             return wine_dbg_sprintf("%s%s_dz%s", get_regname(reg),
381                     debug_print_relarg(reg),
382                     debug_print_swizzle(reg->u.swizzle));
383         case BWRITERSPSM_DW:
384             return wine_dbg_sprintf("%s%s_dw%s", get_regname(reg),
385                     debug_print_relarg(reg),
386                     debug_print_swizzle(reg->u.swizzle));
387         case BWRITERSPSM_ABS:
388             return wine_dbg_sprintf("%s%s_abs%s", get_regname(reg),
389                     debug_print_relarg(reg),
390                     debug_print_swizzle(reg->u.swizzle));
391         case BWRITERSPSM_ABSNEG:
392             return wine_dbg_sprintf("-%s%s_abs%s", get_regname(reg),
393                     debug_print_relarg(reg),
394                     debug_print_swizzle(reg->u.swizzle));
395         case BWRITERSPSM_NOT:
396             return wine_dbg_sprintf("!%s%s%s", get_regname(reg),
397                     debug_print_relarg(reg),
398                     debug_print_swizzle(reg->u.swizzle));
399     }
400     return "Unknown modifier";
401 }
402
403 const char *debug_print_comp(DWORD comp)
404 {
405     switch (comp)
406     {
407         case BWRITER_COMPARISON_NONE: return "";
408         case BWRITER_COMPARISON_GT:   return "_gt";
409         case BWRITER_COMPARISON_EQ:   return "_eq";
410         case BWRITER_COMPARISON_GE:   return "_ge";
411         case BWRITER_COMPARISON_LT:   return "_lt";
412         case BWRITER_COMPARISON_NE:   return "_ne";
413         case BWRITER_COMPARISON_LE:   return "_le";
414         default: return "_unknown";
415     }
416 }
417
418 const char *debug_print_opcode(DWORD opcode)
419 {
420     switch (opcode)
421     {
422         case BWRITERSIO_NOP:          return "nop";
423         case BWRITERSIO_MOV:          return "mov";
424         case BWRITERSIO_ADD:          return "add";
425         case BWRITERSIO_SUB:          return "sub";
426         case BWRITERSIO_MAD:          return "mad";
427         case BWRITERSIO_MUL:          return "mul";
428         case BWRITERSIO_RCP:          return "rcp";
429         case BWRITERSIO_RSQ:          return "rsq";
430         case BWRITERSIO_DP3:          return "dp3";
431         case BWRITERSIO_DP4:          return "dp4";
432         case BWRITERSIO_MIN:          return "min";
433         case BWRITERSIO_MAX:          return "max";
434         case BWRITERSIO_SLT:          return "slt";
435         case BWRITERSIO_SGE:          return "sge";
436         case BWRITERSIO_EXP:          return "exp";
437         case BWRITERSIO_LOG:          return "log";
438         case BWRITERSIO_LIT:          return "lit";
439         case BWRITERSIO_DST:          return "dst";
440         case BWRITERSIO_LRP:          return "lrp";
441         case BWRITERSIO_FRC:          return "frc";
442         case BWRITERSIO_M4x4:         return "m4x4";
443         case BWRITERSIO_M4x3:         return "m4x3";
444         case BWRITERSIO_M3x4:         return "m3x4";
445         case BWRITERSIO_M3x3:         return "m3x3";
446         case BWRITERSIO_M3x2:         return "m3x2";
447         case BWRITERSIO_CALL:         return "call";
448         case BWRITERSIO_CALLNZ:       return "callnz";
449         case BWRITERSIO_LOOP:         return "loop";
450         case BWRITERSIO_RET:          return "ret";
451         case BWRITERSIO_ENDLOOP:      return "endloop";
452         case BWRITERSIO_LABEL:        return "label";
453         case BWRITERSIO_DCL:          return "dcl";
454         case BWRITERSIO_POW:          return "pow";
455         case BWRITERSIO_CRS:          return "crs";
456         case BWRITERSIO_SGN:          return "sgn";
457         case BWRITERSIO_ABS:          return "abs";
458         case BWRITERSIO_NRM:          return "nrm";
459         case BWRITERSIO_SINCOS:       return "sincos";
460         case BWRITERSIO_REP:          return "rep";
461         case BWRITERSIO_ENDREP:       return "endrep";
462         case BWRITERSIO_IF:           return "if";
463         case BWRITERSIO_IFC:          return "ifc";
464         case BWRITERSIO_ELSE:         return "else";
465         case BWRITERSIO_ENDIF:        return "endif";
466         case BWRITERSIO_BREAK:        return "break";
467         case BWRITERSIO_BREAKC:       return "breakc";
468         case BWRITERSIO_MOVA:         return "mova";
469         case BWRITERSIO_DEFB:         return "defb";
470         case BWRITERSIO_DEFI:         return "defi";
471         case BWRITERSIO_TEXCOORD:     return "texcoord";
472         case BWRITERSIO_TEXKILL:      return "texkill";
473         case BWRITERSIO_TEX:          return "tex";
474         case BWRITERSIO_TEXBEM:       return "texbem";
475         case BWRITERSIO_TEXBEML:      return "texbeml";
476         case BWRITERSIO_TEXREG2AR:    return "texreg2ar";
477         case BWRITERSIO_TEXREG2GB:    return "texreg2gb";
478         case BWRITERSIO_TEXM3x2PAD:   return "texm3x2pad";
479         case BWRITERSIO_TEXM3x2TEX:   return "texm3x2tex";
480         case BWRITERSIO_TEXM3x3PAD:   return "texm3x3pad";
481         case BWRITERSIO_TEXM3x3TEX:   return "texm3x3tex";
482         case BWRITERSIO_TEXM3x3SPEC:  return "texm3x3vspec";
483         case BWRITERSIO_TEXM3x3VSPEC: return "texm3x3vspec";
484         case BWRITERSIO_EXPP:         return "expp";
485         case BWRITERSIO_LOGP:         return "logp";
486         case BWRITERSIO_CND:          return "cnd";
487         case BWRITERSIO_DEF:          return "def";
488         case BWRITERSIO_TEXREG2RGB:   return "texreg2rgb";
489         case BWRITERSIO_TEXDP3TEX:    return "texdp3tex";
490         case BWRITERSIO_TEXM3x2DEPTH: return "texm3x2depth";
491         case BWRITERSIO_TEXDP3:       return "texdp3";
492         case BWRITERSIO_TEXM3x3:      return "texm3x3";
493         case BWRITERSIO_TEXDEPTH:     return "texdepth";
494         case BWRITERSIO_CMP:          return "cmp";
495         case BWRITERSIO_BEM:          return "bem";
496         case BWRITERSIO_DP2ADD:       return "dp2add";
497         case BWRITERSIO_DSX:          return "dsx";
498         case BWRITERSIO_DSY:          return "dsy";
499         case BWRITERSIO_TEXLDD:       return "texldd";
500         case BWRITERSIO_SETP:         return "setp";
501         case BWRITERSIO_TEXLDL:       return "texldl";
502         case BWRITERSIO_BREAKP:       return "breakp";
503         case BWRITERSIO_PHASE:        return "phase";
504
505         case BWRITERSIO_TEXLDP:       return "texldp";
506         case BWRITERSIO_TEXLDB:       return "texldb";
507
508         default:                      return "unknown";
509     }
510 }
511
512 void skip_dword_unknown(const char **ptr, unsigned int count)
513 {
514     unsigned int i;
515     DWORD d;
516
517     FIXME("Skipping %u unknown DWORDs:\n", count);
518     for (i = 0; i < count; ++i)
519     {
520         read_dword(ptr, &d);
521         FIXME("\t0x%08x\n", d);
522     }
523 }
524
525 static void write_dword_unknown(char **ptr, DWORD d)
526 {
527     FIXME("Writing unknown DWORD 0x%08x\n", d);
528     write_dword(ptr, d);
529 }
530
531 HRESULT dxbc_add_section(struct dxbc *dxbc, DWORD tag, const char *data, DWORD data_size)
532 {
533     TRACE("dxbc %p, tag %s, size %#x.\n", dxbc, debugstr_an((const char *)&tag, 4), data_size);
534
535     if (dxbc->count >= dxbc->size)
536     {
537         struct dxbc_section *new_sections;
538         DWORD new_size = dxbc->size << 1;
539
540         new_sections = HeapReAlloc(GetProcessHeap(), 0, dxbc->sections, new_size * sizeof(*dxbc->sections));
541         if (!new_sections)
542         {
543             ERR("Failed to allocate dxbc section memory\n");
544             return E_OUTOFMEMORY;
545         }
546
547         dxbc->sections = new_sections;
548         dxbc->size = new_size;
549     }
550
551     dxbc->sections[dxbc->count].tag = tag;
552     dxbc->sections[dxbc->count].data_size = data_size;
553     dxbc->sections[dxbc->count].data = data;
554     ++dxbc->count;
555
556     return S_OK;
557 }
558
559 HRESULT dxbc_init(struct dxbc *dxbc, UINT size)
560 {
561     TRACE("dxbc %p, size %u.\n", dxbc, size);
562
563     /* use a good starting value for the size if none specified */
564     if (!size) size = 2;
565
566     dxbc->sections = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*dxbc->sections));
567     if (!dxbc->sections)
568     {
569         ERR("Failed to allocate dxbc section memory\n");
570         return E_OUTOFMEMORY;
571     }
572
573     dxbc->size = size;
574     dxbc->count = 0;
575
576     return S_OK;
577 }
578
579 HRESULT dxbc_parse(const char *data, SIZE_T data_size, struct dxbc *dxbc)
580 {
581     const char *ptr = data;
582     HRESULT hr;
583     unsigned int i;
584     DWORD tag, total_size, chunk_count;
585
586     if (!data)
587     {
588         WARN("No data supplied.\n");
589         return E_FAIL;
590     }
591
592     read_dword(&ptr, &tag);
593     TRACE("tag: %s.\n", debugstr_an((const char *)&tag, 4));
594
595     if (tag != TAG_DXBC)
596     {
597         WARN("Wrong tag.\n");
598         return E_FAIL;
599     }
600
601     /* checksum? */
602     skip_dword_unknown(&ptr, 4);
603
604     skip_dword_unknown(&ptr, 1);
605
606     read_dword(&ptr, &total_size);
607     TRACE("total size: %#x\n", total_size);
608
609     if (data_size != total_size)
610     {
611         WARN("Wrong size supplied.\n");
612         return D3DERR_INVALIDCALL;
613     }
614
615     read_dword(&ptr, &chunk_count);
616     TRACE("chunk count: %#x\n", chunk_count);
617
618     hr = dxbc_init(dxbc, chunk_count);
619     if (FAILED(hr))
620     {
621         WARN("Failed to init dxbc\n");
622         return hr;
623     }
624
625     for (i = 0; i < chunk_count; ++i)
626     {
627         DWORD chunk_tag, chunk_size;
628         const char *chunk_ptr;
629         DWORD chunk_offset;
630
631         read_dword(&ptr, &chunk_offset);
632         TRACE("chunk %u at offset %#x\n", i, chunk_offset);
633
634         chunk_ptr = data + chunk_offset;
635
636         read_dword(&chunk_ptr, &chunk_tag);
637         read_dword(&chunk_ptr, &chunk_size);
638
639         hr = dxbc_add_section(dxbc, chunk_tag, chunk_ptr, chunk_size);
640         if (FAILED(hr))
641         {
642             WARN("Failed to add section to dxbc\n");
643             return hr;
644         }
645     }
646
647     return hr;
648 }
649
650 void dxbc_destroy(struct dxbc *dxbc)
651 {
652     TRACE("dxbc %p.\n", dxbc);
653
654     HeapFree(GetProcessHeap(), 0, dxbc->sections);
655 }
656
657 HRESULT dxbc_write_blob(struct dxbc *dxbc, ID3DBlob **blob)
658 {
659     DWORD size = 32, offset = size + 4 * dxbc->count;
660     ID3DBlob *object;
661     HRESULT hr;
662     char *ptr;
663     unsigned int i;
664
665     TRACE("dxbc %p, blob %p.\n", dxbc, blob);
666
667     for (i = 0; i < dxbc->count; ++i)
668     {
669         size += 12 + dxbc->sections[i].data_size;
670     }
671
672     hr = D3DCreateBlob(size, &object);
673     if (FAILED(hr))
674     {
675         WARN("Failed to create blob\n");
676         return hr;
677     }
678
679     ptr = ID3D10Blob_GetBufferPointer(object);
680
681     write_dword(&ptr, TAG_DXBC);
682
683     /* signature(?) */
684     write_dword_unknown(&ptr, 0);
685     write_dword_unknown(&ptr, 0);
686     write_dword_unknown(&ptr, 0);
687     write_dword_unknown(&ptr, 0);
688
689     /* seems to be always 1 */
690     write_dword_unknown(&ptr, 1);
691
692     /* DXBC size */
693     write_dword(&ptr, size);
694
695     /* chunk count */
696     write_dword(&ptr, dxbc->count);
697
698     /* write the chunk offsets */
699     for (i = 0; i < dxbc->count; ++i)
700     {
701         write_dword(&ptr, offset);
702         offset += 8 + dxbc->sections[i].data_size;
703     }
704
705     /* write the chunks */
706     for (i = 0; i < dxbc->count; ++i)
707     {
708         write_dword(&ptr, dxbc->sections[i].tag);
709         write_dword(&ptr, dxbc->sections[i].data_size);
710         memcpy(ptr, dxbc->sections[i].data, dxbc->sections[i].data_size);
711         ptr += dxbc->sections[i].data_size;
712     }
713
714     TRACE("Created ID3DBlob %p\n", object);
715
716     *blob = object;
717
718     return S_OK;
719 }
720
721 void compilation_message(struct compilation_messages *msg, const char *fmt, va_list args)
722 {
723     char* buffer;
724     int rc, size;
725
726     if (msg->capacity == 0)
727     {
728         msg->string = d3dcompiler_alloc(MESSAGEBUFFER_INITIAL_SIZE);
729         if (msg->string == NULL)
730         {
731             ERR("Error allocating memory for parser messages\n");
732             return;
733         }
734         msg->capacity = MESSAGEBUFFER_INITIAL_SIZE;
735     }
736
737     while (1)
738     {
739         rc = vsnprintf(msg->string + msg->size,
740                 msg->capacity - msg->size, fmt, args);
741
742         if (rc < 0 || rc >= msg->capacity - msg->size)
743         {
744             size = msg->capacity * 2;
745             buffer = d3dcompiler_realloc(msg->string, size);
746             if (buffer == NULL)
747             {
748                 ERR("Error reallocating memory for parser messages\n");
749                 return;
750             }
751             msg->string = buffer;
752             msg->capacity = size;
753         }
754         else
755         {
756             TRACE("%s", msg->string + msg->size);
757             msg->size += rc;
758             return;
759         }
760     }
761 }