jscript: Added Object function invocation implementation.
[wine] / dlls / d3d10core / shader.c
1 /*
2  * Copyright 2009 Henri Verbeet for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  *
18  */
19
20 #include "config.h"
21 #include "wine/port.h"
22
23 #include "d3d10core_private.h"
24
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d10core);
26
27 static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
28 {
29     struct d3d10_shader_info *shader_info = ctx;
30     HRESULT hr;
31
32     switch(tag)
33     {
34         case TAG_OSGN:
35             hr = shader_parse_signature(data, data_size, shader_info->output_signature);
36             if (FAILED(hr)) return hr;
37             break;
38
39         case TAG_SHDR:
40             shader_info->shader_code = (const DWORD *)data;
41             break;
42
43         default:
44             FIXME("Unhandled chunk %s\n", debugstr_an((const char *)&tag, 4));
45             break;
46     }
47
48     return S_OK;
49 }
50
51 HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, struct d3d10_shader_info *shader_info)
52 {
53     HRESULT hr;
54
55     shader_info->shader_code = NULL;
56     memset(shader_info->output_signature, 0, sizeof(*shader_info->output_signature));
57
58     hr = parse_dxbc(dxbc, dxbc_length, shdr_handler, shader_info);
59     if (!shader_info->shader_code) hr = E_FAIL;
60
61     if (FAILED(hr))
62     {
63         ERR("Failed to parse shader, hr %#x\n", hr);
64         shader_free_signature(shader_info->output_signature);
65     }
66
67     return hr;
68 }
69
70 HRESULT shader_parse_signature(const char *data, DWORD data_size, struct wined3d_shader_signature *s)
71 {
72     struct wined3d_shader_signature_element *e;
73     unsigned int string_data_offset;
74     unsigned int string_data_size;
75     const char *ptr = data;
76     char *string_data;
77     unsigned int i;
78     DWORD count;
79
80     read_dword(&ptr, &count);
81     TRACE("%u elements\n", count);
82
83     skip_dword_unknown(&ptr, 1);
84
85     e = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*e));
86     if (!e)
87     {
88         ERR("Failed to allocate input signature memory.\n");
89         return E_OUTOFMEMORY;
90     }
91
92     /* 2 DWORDs for the header, 6 for each element. */
93     string_data_offset = 2 * sizeof(DWORD) + count * 6 * sizeof(DWORD);
94     string_data_size = data_size - string_data_offset;
95     string_data = HeapAlloc(GetProcessHeap(), 0, string_data_size);
96     if (!string_data)
97     {
98         ERR("Failed to allocate string data memory.\n");
99         HeapFree(GetProcessHeap(), 0, e);
100         return E_OUTOFMEMORY;
101     }
102     memcpy(string_data, data + string_data_offset, string_data_size);
103
104     for (i = 0; i < count; ++i)
105     {
106         UINT name_offset;
107
108         read_dword(&ptr, &name_offset);
109         e[i].semantic_name = string_data + (name_offset - string_data_offset);
110         read_dword(&ptr, &e[i].semantic_idx);
111         read_dword(&ptr, &e[i].sysval_semantic);
112         read_dword(&ptr, &e[i].component_type);
113         read_dword(&ptr, &e[i].register_idx);
114         read_dword(&ptr, &e[i].mask);
115
116         TRACE("semantic: %s, semantic idx: %u, sysval_semantic %#x, "
117                 "type %u, register idx: %u, use_mask %#x, input_mask %#x\n",
118                 debugstr_a(e[i].semantic_name), e[i].semantic_idx, e[i].sysval_semantic,
119                 e[i].component_type, e[i].register_idx, (e[i].mask >> 8) & 0xff, e[i].mask & 0xff);
120     }
121
122     s->elements = e;
123     s->element_count = count;
124     s->string_data = string_data;
125
126     return S_OK;
127 }
128
129 void shader_free_signature(struct wined3d_shader_signature *s)
130 {
131     HeapFree(GetProcessHeap(), 0, s->string_data);
132     HeapFree(GetProcessHeap(), 0, s->elements);
133 }
134
135 /* IUnknown methods */
136
137 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_QueryInterface(ID3D10VertexShader *iface,
138         REFIID riid, void **object)
139 {
140     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
141
142     if (IsEqualGUID(riid, &IID_ID3D10VertexShader)
143             || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
144             || IsEqualGUID(riid, &IID_IUnknown))
145     {
146         IUnknown_AddRef(iface);
147         *object = iface;
148         return S_OK;
149     }
150
151     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
152
153     *object = NULL;
154     return E_NOINTERFACE;
155 }
156
157 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *iface)
158 {
159     struct d3d10_vertex_shader *This = (struct d3d10_vertex_shader *)iface;
160     ULONG refcount = InterlockedIncrement(&This->refcount);
161
162     TRACE("%p increasing refcount to %u\n", This, refcount);
163
164     return refcount;
165 }
166
167 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *iface)
168 {
169     struct d3d10_vertex_shader *This = (struct d3d10_vertex_shader *)iface;
170     ULONG refcount = InterlockedDecrement(&This->refcount);
171
172     TRACE("%p decreasing refcount to %u\n", This, refcount);
173
174     if (!refcount)
175     {
176         IWineD3DVertexShader_Release(This->wined3d_shader);
177         shader_free_signature(&This->output_signature);
178         HeapFree(GetProcessHeap(), 0, This);
179     }
180
181     return refcount;
182 }
183
184 /* ID3D10DeviceChild methods */
185
186 static void STDMETHODCALLTYPE d3d10_vertex_shader_GetDevice(ID3D10VertexShader *iface, ID3D10Device **device)
187 {
188     FIXME("iface %p, device %p stub!\n", iface, device);
189 }
190
191 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_GetPrivateData(ID3D10VertexShader *iface,
192         REFGUID guid, UINT *data_size, void *data)
193 {
194     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
195             iface, debugstr_guid(guid), data_size, data);
196
197     return E_NOTIMPL;
198 }
199
200 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateData(ID3D10VertexShader *iface,
201         REFGUID guid, UINT data_size, const void *data)
202 {
203     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
204             iface, debugstr_guid(guid), data_size, data);
205
206     return E_NOTIMPL;
207 }
208
209 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateDataInterface(ID3D10VertexShader *iface,
210         REFGUID guid, const IUnknown *data)
211 {
212     FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
213
214     return E_NOTIMPL;
215 }
216
217 const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
218 {
219     /* IUnknown methods */
220     d3d10_vertex_shader_QueryInterface,
221     d3d10_vertex_shader_AddRef,
222     d3d10_vertex_shader_Release,
223     /* ID3D10DeviceChild methods */
224     d3d10_vertex_shader_GetDevice,
225     d3d10_vertex_shader_GetPrivateData,
226     d3d10_vertex_shader_SetPrivateData,
227     d3d10_vertex_shader_SetPrivateDataInterface,
228 };
229
230 /* IUnknown methods */
231
232 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
233         REFIID riid, void **object)
234 {
235     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
236
237     if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
238             || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
239             || IsEqualGUID(riid, &IID_IUnknown))
240     {
241         IUnknown_AddRef(iface);
242         *object = iface;
243         return S_OK;
244     }
245
246     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
247
248     *object = NULL;
249     return E_NOINTERFACE;
250 }
251
252 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
253 {
254     struct d3d10_geometry_shader *This = (struct d3d10_geometry_shader *)iface;
255     ULONG refcount = InterlockedIncrement(&This->refcount);
256
257     TRACE("%p increasing refcount to %u\n", This, refcount);
258
259     return refcount;
260 }
261
262 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
263 {
264     struct d3d10_geometry_shader *This = (struct d3d10_geometry_shader *)iface;
265     ULONG refcount = InterlockedDecrement(&This->refcount);
266
267     TRACE("%p decreasing refcount to %u\n", This, refcount);
268
269     if (!refcount)
270     {
271         HeapFree(GetProcessHeap(), 0, This);
272     }
273
274     return refcount;
275 }
276
277 /* ID3D10DeviceChild methods */
278
279 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
280 {
281     FIXME("iface %p, device %p stub!\n", iface, device);
282 }
283
284 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
285         REFGUID guid, UINT *data_size, void *data)
286 {
287     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
288             iface, debugstr_guid(guid), data_size, data);
289
290     return E_NOTIMPL;
291 }
292
293 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
294         REFGUID guid, UINT data_size, const void *data)
295 {
296     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
297             iface, debugstr_guid(guid), data_size, data);
298
299     return E_NOTIMPL;
300 }
301
302 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
303         REFGUID guid, const IUnknown *data)
304 {
305     FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
306
307     return E_NOTIMPL;
308 }
309
310 const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
311 {
312     /* IUnknown methods */
313     d3d10_geometry_shader_QueryInterface,
314     d3d10_geometry_shader_AddRef,
315     d3d10_geometry_shader_Release,
316     /* ID3D10DeviceChild methods */
317     d3d10_geometry_shader_GetDevice,
318     d3d10_geometry_shader_GetPrivateData,
319     d3d10_geometry_shader_SetPrivateData,
320     d3d10_geometry_shader_SetPrivateDataInterface,
321 };
322
323 /* IUnknown methods */
324
325 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_QueryInterface(ID3D10PixelShader *iface,
326         REFIID riid, void **object)
327 {
328     TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
329
330     if (IsEqualGUID(riid, &IID_ID3D10PixelShader)
331             || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
332             || IsEqualGUID(riid, &IID_IUnknown))
333     {
334         IUnknown_AddRef(iface);
335         *object = iface;
336         return S_OK;
337     }
338
339     WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
340
341     *object = NULL;
342     return E_NOINTERFACE;
343 }
344
345 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_AddRef(ID3D10PixelShader *iface)
346 {
347     struct d3d10_pixel_shader *This = (struct d3d10_pixel_shader *)iface;
348     ULONG refcount = InterlockedIncrement(&This->refcount);
349
350     TRACE("%p increasing refcount to %u\n", This, refcount);
351
352     return refcount;
353 }
354
355 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_Release(ID3D10PixelShader *iface)
356 {
357     struct d3d10_pixel_shader *This = (struct d3d10_pixel_shader *)iface;
358     ULONG refcount = InterlockedDecrement(&This->refcount);
359
360     TRACE("%p decreasing refcount to %u\n", This, refcount);
361
362     if (!refcount)
363     {
364         IWineD3DPixelShader_Release(This->wined3d_shader);
365         shader_free_signature(&This->output_signature);
366         HeapFree(GetProcessHeap(), 0, This);
367     }
368
369     return refcount;
370 }
371
372 /* ID3D10DeviceChild methods */
373
374 static void STDMETHODCALLTYPE d3d10_pixel_shader_GetDevice(ID3D10PixelShader *iface, ID3D10Device **device)
375 {
376     FIXME("iface %p, device %p stub!\n", iface, device);
377 }
378
379 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_GetPrivateData(ID3D10PixelShader *iface,
380         REFGUID guid, UINT *data_size, void *data)
381 {
382     FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
383             iface, debugstr_guid(guid), data_size, data);
384
385     return E_NOTIMPL;
386 }
387
388 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateData(ID3D10PixelShader *iface,
389         REFGUID guid, UINT data_size, const void *data)
390 {
391     FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
392             iface, debugstr_guid(guid), data_size, data);
393
394     return E_NOTIMPL;
395 }
396
397 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateDataInterface(ID3D10PixelShader *iface,
398         REFGUID guid, const IUnknown *data)
399 {
400     FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
401
402     return E_NOTIMPL;
403 }
404
405 const struct ID3D10PixelShaderVtbl d3d10_pixel_shader_vtbl =
406 {
407     /* IUnknown methods */
408     d3d10_pixel_shader_QueryInterface,
409     d3d10_pixel_shader_AddRef,
410     d3d10_pixel_shader_Release,
411     /* ID3D10DeviceChild methods */
412     d3d10_pixel_shader_GetDevice,
413     d3d10_pixel_shader_GetPrivateData,
414     d3d10_pixel_shader_SetPrivateData,
415     d3d10_pixel_shader_SetPrivateDataInterface,
416 };