wined3d: IWineD3DBuffer_Unmap() can't fail.
[wine] / dlls / d3dcompiler_43 / utils.c
1 /*
2  * Copyright 2008-2009 Henri Verbeet for CodeWeavers
3  * Copyright 2010 Rico Schüller
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  */
20
21 #include "config.h"
22 #include "wine/port.h"
23
24 #include "d3dcompiler_private.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(d3dcompiler);
27
28 #define WINE_D3DCOMPILER_TO_STR(x) case x: return #x
29
30 const char *debug_d3dcompiler_d3d_blob_part(D3D_BLOB_PART part)
31 {
32     switch(part)
33     {
34         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_INPUT_SIGNATURE_BLOB);
35         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_OUTPUT_SIGNATURE_BLOB);
36         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_INPUT_AND_OUTPUT_SIGNATURE_BLOB);
37         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_PATCH_CONSTANT_SIGNATURE_BLOB);
38         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_ALL_SIGNATURE_BLOB);
39         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_DEBUG_INFO);
40         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_LEGACY_SHADER);
41         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_XNA_PREPASS_SHADER);
42         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_XNA_SHADER);
43         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_TEST_ALTERNATE_SHADER);
44         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_TEST_COMPILE_DETAILS);
45         WINE_D3DCOMPILER_TO_STR(D3D_BLOB_TEST_COMPILE_PERF);
46         default:
47             FIXME("Unrecognized D3D_BLOB_PART %#x\n", part);
48             return "unrecognized";
49     }
50 }
51
52 #undef WINE_D3DCOMPILER_TO_STR
53
54 void skip_dword_unknown(const char **ptr, unsigned int count)
55 {
56     unsigned int i;
57     DWORD d;
58
59     FIXME("Skipping %u unknown DWORDs:\n", count);
60     for (i = 0; i < count; ++i)
61     {
62         read_dword(ptr, &d);
63         FIXME("\t0x%08x\n", d);
64     }
65 }
66
67 void write_dword_unknown(char **ptr, DWORD d)
68 {
69     FIXME("Writing unknown DWORD 0x%08x\n", d);
70     write_dword(ptr, d);
71 }
72
73 HRESULT dxbc_add_section(struct dxbc *dxbc, DWORD tag, const char *data, DWORD data_size)
74 {
75     TRACE("dxbc %p, tag %s, size %#x.\n", dxbc, debugstr_an((const char *)&tag, 4), data_size);
76
77     if (dxbc->count >= dxbc->size)
78     {
79         struct dxbc_section *new_sections;
80         DWORD new_size = dxbc->size << 1;
81
82         new_sections = HeapReAlloc(GetProcessHeap(), 0, dxbc->sections, new_size * sizeof(*dxbc->sections));
83         if (!new_sections)
84         {
85             ERR("Failed to allocate dxbc section memory\n");
86             return E_OUTOFMEMORY;
87         }
88
89         dxbc->sections = new_sections;
90         dxbc->size = new_size;
91     }
92
93     dxbc->sections[dxbc->count].tag = tag;
94     dxbc->sections[dxbc->count].data_size = data_size;
95     dxbc->sections[dxbc->count].data = data;
96     ++dxbc->count;
97
98     return S_OK;
99 }
100
101 HRESULT dxbc_init(struct dxbc *dxbc, UINT size)
102 {
103     TRACE("dxbc %p, size %u.\n", dxbc, size);
104
105     /* use a good starting value for the size if none specified */
106     if (!size) size = 2;
107
108     dxbc->sections = HeapAlloc(GetProcessHeap(), 0, size * sizeof(*dxbc->sections));
109     if (!dxbc->sections)
110     {
111         ERR("Failed to allocate dxbc section memory\n");
112         return E_OUTOFMEMORY;
113     }
114
115     dxbc->size = size;
116     dxbc->count = 0;
117
118     return S_OK;
119 }
120
121 HRESULT dxbc_parse(const char *data, SIZE_T data_size, struct dxbc *dxbc)
122 {
123     const char *ptr = data;
124     HRESULT hr;
125     unsigned int i;
126     DWORD tag, total_size, chunk_count;
127
128     if (!data)
129     {
130         WARN("No data supplied.\n");
131         return E_FAIL;
132     }
133
134     read_dword(&ptr, &tag);
135     TRACE("tag: %s.\n", debugstr_an((const char *)&tag, 4));
136
137     if (tag != TAG_DXBC)
138     {
139         WARN("Wrong tag.\n");
140         return E_FAIL;
141     }
142
143     /* checksum? */
144     skip_dword_unknown(&ptr, 4);
145
146     skip_dword_unknown(&ptr, 1);
147
148     read_dword(&ptr, &total_size);
149     TRACE("total size: %#x\n", total_size);
150
151     if (data_size != total_size)
152     {
153         WARN("Wrong size supplied.\n");
154         return D3DERR_INVALIDCALL;
155     }
156
157     read_dword(&ptr, &chunk_count);
158     TRACE("chunk count: %#x\n", chunk_count);
159
160     hr = dxbc_init(dxbc, chunk_count);
161     if (FAILED(hr))
162     {
163         WARN("Failed to init dxbc\n");
164         return hr;
165     }
166
167     for (i = 0; i < chunk_count; ++i)
168     {
169         DWORD chunk_tag, chunk_size;
170         const char *chunk_ptr;
171         DWORD chunk_offset;
172
173         read_dword(&ptr, &chunk_offset);
174         TRACE("chunk %u at offset %#x\n", i, chunk_offset);
175
176         chunk_ptr = data + chunk_offset;
177
178         read_dword(&chunk_ptr, &chunk_tag);
179         read_dword(&chunk_ptr, &chunk_size);
180
181         hr = dxbc_add_section(dxbc, chunk_tag, chunk_ptr, chunk_size);
182         if (FAILED(hr))
183         {
184             WARN("Failed to add section to dxbc\n");
185             return hr;
186         }
187     }
188
189     return hr;
190 }
191
192 void dxbc_destroy(struct dxbc *dxbc)
193 {
194     TRACE("dxbc %p.\n", dxbc);
195
196     HeapFree(GetProcessHeap(), 0, dxbc->sections);
197 }
198
199 HRESULT dxbc_write_blob(struct dxbc *dxbc, ID3DBlob **blob)
200 {
201     DWORD size = 32, offset = size + 4 * dxbc->count;
202     ID3DBlob *object;
203     HRESULT hr;
204     char *ptr;
205     unsigned int i;
206
207     TRACE("dxbc %p, blob %p.\n", dxbc, blob);
208
209     for (i = 0; i < dxbc->count; ++i)
210     {
211         size += 12 + dxbc->sections[i].data_size;
212     }
213
214     hr = D3DCreateBlob(size, &object);
215     if (FAILED(hr))
216     {
217         WARN("Failed to create blob\n");
218         return hr;
219     }
220
221     ptr = ID3D10Blob_GetBufferPointer(object);
222
223     write_dword(&ptr, TAG_DXBC);
224
225     /* signature(?) */
226     write_dword_unknown(&ptr, 0);
227     write_dword_unknown(&ptr, 0);
228     write_dword_unknown(&ptr, 0);
229     write_dword_unknown(&ptr, 0);
230
231     /* seems to be always 1 */
232     write_dword_unknown(&ptr, 1);
233
234     /* DXBC size */
235     write_dword(&ptr, size);
236
237     /* chunk count */
238     write_dword(&ptr, dxbc->count);
239
240     /* write the chunk offsets */
241     for (i = 0; i < dxbc->count; ++i)
242     {
243         write_dword(&ptr, offset);
244         offset += 8 + dxbc->sections[i].data_size;
245     }
246
247     /* write the chunks */
248     for (i = 0; i < dxbc->count; ++i)
249     {
250         write_dword(&ptr, dxbc->sections[i].tag);
251         write_dword(&ptr, dxbc->sections[i].data_size);
252         memcpy(ptr, dxbc->sections[i].data, dxbc->sections[i].data_size);
253         ptr += dxbc->sections[i].data_size;
254     }
255
256     TRACE("Created ID3DBlob %p\n", object);
257
258     *blob = object;
259
260     return S_OK;
261 }