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