po: Fix a mistake in Dutch translation.
[wine.git] / dlls / d3d10core / shader.c
blob1000054429055d4a458af24883f27e4e48a4aaa2
1 /*
2 * Copyright 2009 Henri Verbeet for CodeWeavers
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.
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.
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
20 #include "config.h"
21 #include "wine/port.h"
23 #include "d3d10core_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(d3d10core);
27 static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
29 struct d3d10_shader_info *shader_info = ctx;
30 HRESULT hr;
32 switch (tag)
34 case TAG_ISGN:
35 if (FAILED(hr = shader_parse_signature(data, data_size, shader_info->input_signature)))
36 return hr;
37 break;
39 case TAG_OSGN:
40 if (FAILED(hr = shader_parse_signature(data, data_size, shader_info->output_signature)))
41 return hr;
42 break;
44 case TAG_SHDR:
45 shader_info->shader_code = (const DWORD *)data;
46 break;
48 default:
49 FIXME("Unhandled chunk %s\n", debugstr_an((const char *)&tag, 4));
50 break;
53 return S_OK;
56 static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, struct d3d10_shader_info *shader_info)
58 HRESULT hr;
60 shader_info->shader_code = NULL;
61 memset(shader_info->input_signature, 0, sizeof(*shader_info->input_signature));
62 memset(shader_info->output_signature, 0, sizeof(*shader_info->output_signature));
64 hr = parse_dxbc(dxbc, dxbc_length, shdr_handler, shader_info);
65 if (!shader_info->shader_code) hr = E_INVALIDARG;
67 if (FAILED(hr))
69 ERR("Failed to parse shader, hr %#x\n", hr);
70 shader_free_signature(shader_info->input_signature);
71 shader_free_signature(shader_info->output_signature);
74 return hr;
77 HRESULT shader_parse_signature(const char *data, DWORD data_size, struct wined3d_shader_signature *s)
79 struct wined3d_shader_signature_element *e;
80 const char *ptr = data;
81 unsigned int i;
82 DWORD count;
84 read_dword(&ptr, &count);
85 TRACE("%u elements\n", count);
87 skip_dword_unknown(&ptr, 1);
89 e = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*e));
90 if (!e)
92 ERR("Failed to allocate input signature memory.\n");
93 return E_OUTOFMEMORY;
96 for (i = 0; i < count; ++i)
98 UINT name_offset;
100 read_dword(&ptr, &name_offset);
101 e[i].semantic_name = data + name_offset;
102 read_dword(&ptr, &e[i].semantic_idx);
103 read_dword(&ptr, &e[i].sysval_semantic);
104 read_dword(&ptr, &e[i].component_type);
105 read_dword(&ptr, &e[i].register_idx);
106 read_dword(&ptr, &e[i].mask);
108 TRACE("semantic: %s, semantic idx: %u, sysval_semantic %#x, "
109 "type %u, register idx: %u, use_mask %#x, input_mask %#x\n",
110 debugstr_a(e[i].semantic_name), e[i].semantic_idx, e[i].sysval_semantic,
111 e[i].component_type, e[i].register_idx, (e[i].mask >> 8) & 0xff, e[i].mask & 0xff);
114 s->elements = e;
115 s->element_count = count;
117 return S_OK;
120 void shader_free_signature(struct wined3d_shader_signature *s)
122 HeapFree(GetProcessHeap(), 0, s->elements);
125 static inline struct d3d10_vertex_shader *impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
127 return CONTAINING_RECORD(iface, struct d3d10_vertex_shader, ID3D10VertexShader_iface);
130 /* IUnknown methods */
132 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_QueryInterface(ID3D10VertexShader *iface,
133 REFIID riid, void **object)
135 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
137 if (IsEqualGUID(riid, &IID_ID3D10VertexShader)
138 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
139 || IsEqualGUID(riid, &IID_IUnknown))
141 IUnknown_AddRef(iface);
142 *object = iface;
143 return S_OK;
146 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
148 *object = NULL;
149 return E_NOINTERFACE;
152 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *iface)
154 struct d3d10_vertex_shader *This = impl_from_ID3D10VertexShader(iface);
155 ULONG refcount = InterlockedIncrement(&This->refcount);
157 TRACE("%p increasing refcount to %u\n", This, refcount);
159 if (refcount == 1)
161 ID3D10Device1_AddRef(This->device);
162 wined3d_shader_incref(This->wined3d_shader);
165 return refcount;
168 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *iface)
170 struct d3d10_vertex_shader *This = impl_from_ID3D10VertexShader(iface);
171 ULONG refcount = InterlockedDecrement(&This->refcount);
173 TRACE("%p decreasing refcount to %u\n", This, refcount);
175 if (!refcount)
177 ID3D10Device1 *device = This->device;
179 wined3d_shader_decref(This->wined3d_shader);
180 /* Release the device last, it may cause the wined3d device to be
181 * destroyed. */
182 ID3D10Device1_Release(device);
185 return refcount;
188 /* ID3D10DeviceChild methods */
190 static void STDMETHODCALLTYPE d3d10_vertex_shader_GetDevice(ID3D10VertexShader *iface, ID3D10Device **device)
192 struct d3d10_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
194 TRACE("iface %p, device %p.\n", iface, device);
196 *device = (ID3D10Device *)shader->device;
197 ID3D10Device_AddRef(*device);
200 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_GetPrivateData(ID3D10VertexShader *iface,
201 REFGUID guid, UINT *data_size, void *data)
203 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
204 iface, debugstr_guid(guid), data_size, data);
206 return E_NOTIMPL;
209 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateData(ID3D10VertexShader *iface,
210 REFGUID guid, UINT data_size, const void *data)
212 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
213 iface, debugstr_guid(guid), data_size, data);
215 return E_NOTIMPL;
218 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateDataInterface(ID3D10VertexShader *iface,
219 REFGUID guid, const IUnknown *data)
221 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
223 return E_NOTIMPL;
226 static const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
228 /* IUnknown methods */
229 d3d10_vertex_shader_QueryInterface,
230 d3d10_vertex_shader_AddRef,
231 d3d10_vertex_shader_Release,
232 /* ID3D10DeviceChild methods */
233 d3d10_vertex_shader_GetDevice,
234 d3d10_vertex_shader_GetPrivateData,
235 d3d10_vertex_shader_SetPrivateData,
236 d3d10_vertex_shader_SetPrivateDataInterface,
239 static void STDMETHODCALLTYPE d3d10_vertex_shader_wined3d_object_destroyed(void *parent)
241 HeapFree(GetProcessHeap(), 0, parent);
244 static const struct wined3d_parent_ops d3d10_vertex_shader_wined3d_parent_ops =
246 d3d10_vertex_shader_wined3d_object_destroyed,
249 HRESULT d3d10_vertex_shader_init(struct d3d10_vertex_shader *shader, struct d3d10_device *device,
250 const void *byte_code, SIZE_T byte_code_length)
252 struct wined3d_shader_signature output_signature;
253 struct wined3d_shader_signature input_signature;
254 struct d3d10_shader_info shader_info;
255 struct wined3d_shader_desc desc;
256 HRESULT hr;
258 shader->ID3D10VertexShader_iface.lpVtbl = &d3d10_vertex_shader_vtbl;
259 shader->refcount = 1;
261 shader_info.input_signature = &input_signature;
262 shader_info.output_signature = &output_signature;
263 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info)))
265 ERR("Failed to extract shader, hr %#x.\n", hr);
266 return hr;
269 desc.byte_code = shader_info.shader_code;
270 desc.input_signature = &input_signature;
271 desc.output_signature = &output_signature;
272 desc.max_version = 4;
274 hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader,
275 &d3d10_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader);
276 shader_free_signature(&input_signature);
277 shader_free_signature(&output_signature);
278 if (FAILED(hr))
280 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
281 return E_INVALIDARG;
284 shader->device = &device->ID3D10Device1_iface;
285 ID3D10Device1_AddRef(shader->device);
287 return S_OK;
290 struct d3d10_vertex_shader *unsafe_impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
292 if (!iface)
293 return NULL;
294 assert(iface->lpVtbl == &d3d10_vertex_shader_vtbl);
296 return impl_from_ID3D10VertexShader(iface);
299 static inline struct d3d10_geometry_shader *impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
301 return CONTAINING_RECORD(iface, struct d3d10_geometry_shader, ID3D10GeometryShader_iface);
304 /* IUnknown methods */
306 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
307 REFIID riid, void **object)
309 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
311 if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
312 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
313 || IsEqualGUID(riid, &IID_IUnknown))
315 IUnknown_AddRef(iface);
316 *object = iface;
317 return S_OK;
320 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
322 *object = NULL;
323 return E_NOINTERFACE;
326 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
328 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
329 ULONG refcount = InterlockedIncrement(&This->refcount);
331 TRACE("%p increasing refcount to %u\n", This, refcount);
333 return refcount;
336 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
338 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
339 ULONG refcount = InterlockedDecrement(&This->refcount);
341 TRACE("%p decreasing refcount to %u\n", This, refcount);
343 if (!refcount)
344 wined3d_shader_decref(This->wined3d_shader);
346 return refcount;
349 /* ID3D10DeviceChild methods */
351 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
353 FIXME("iface %p, device %p stub!\n", iface, device);
356 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
357 REFGUID guid, UINT *data_size, void *data)
359 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
360 iface, debugstr_guid(guid), data_size, data);
362 return E_NOTIMPL;
365 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
366 REFGUID guid, UINT data_size, const void *data)
368 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
369 iface, debugstr_guid(guid), data_size, data);
371 return E_NOTIMPL;
374 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
375 REFGUID guid, const IUnknown *data)
377 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
379 return E_NOTIMPL;
382 static const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
384 /* IUnknown methods */
385 d3d10_geometry_shader_QueryInterface,
386 d3d10_geometry_shader_AddRef,
387 d3d10_geometry_shader_Release,
388 /* ID3D10DeviceChild methods */
389 d3d10_geometry_shader_GetDevice,
390 d3d10_geometry_shader_GetPrivateData,
391 d3d10_geometry_shader_SetPrivateData,
392 d3d10_geometry_shader_SetPrivateDataInterface,
395 static void STDMETHODCALLTYPE d3d10_geometry_shader_wined3d_object_destroyed(void *parent)
397 HeapFree(GetProcessHeap(), 0, parent);
400 static const struct wined3d_parent_ops d3d10_geometry_shader_wined3d_parent_ops =
402 d3d10_geometry_shader_wined3d_object_destroyed,
405 HRESULT d3d10_geometry_shader_init(struct d3d10_geometry_shader *shader, struct d3d10_device *device,
406 const void *byte_code, SIZE_T byte_code_length)
408 struct wined3d_shader_signature output_signature;
409 struct wined3d_shader_signature input_signature;
410 struct d3d10_shader_info shader_info;
411 struct wined3d_shader_desc desc;
412 HRESULT hr;
414 shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl;
415 shader->refcount = 1;
417 shader_info.input_signature = &input_signature;
418 shader_info.output_signature = &output_signature;
419 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info)))
421 ERR("Failed to extract shader, hr %#x.\n", hr);
422 return hr;
425 desc.byte_code = shader_info.shader_code;
426 desc.input_signature = &input_signature;
427 desc.output_signature = &output_signature;
428 desc.max_version = 4;
430 hr = wined3d_shader_create_gs(device->wined3d_device, &desc, shader,
431 &d3d10_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
432 shader_free_signature(&input_signature);
433 shader_free_signature(&output_signature);
434 if (FAILED(hr))
436 WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
437 return E_INVALIDARG;
440 return S_OK;
443 struct d3d10_geometry_shader *unsafe_impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
445 if (!iface)
446 return NULL;
447 assert(iface->lpVtbl == &d3d10_geometry_shader_vtbl);
449 return impl_from_ID3D10GeometryShader(iface);
452 static inline struct d3d10_pixel_shader *impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
454 return CONTAINING_RECORD(iface, struct d3d10_pixel_shader, ID3D10PixelShader_iface);
457 /* IUnknown methods */
459 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_QueryInterface(ID3D10PixelShader *iface,
460 REFIID riid, void **object)
462 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
464 if (IsEqualGUID(riid, &IID_ID3D10PixelShader)
465 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
466 || IsEqualGUID(riid, &IID_IUnknown))
468 IUnknown_AddRef(iface);
469 *object = iface;
470 return S_OK;
473 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
475 *object = NULL;
476 return E_NOINTERFACE;
479 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_AddRef(ID3D10PixelShader *iface)
481 struct d3d10_pixel_shader *This = impl_from_ID3D10PixelShader(iface);
482 ULONG refcount = InterlockedIncrement(&This->refcount);
484 TRACE("%p increasing refcount to %u\n", This, refcount);
486 if (refcount == 1)
488 ID3D10Device1_AddRef(This->device);
489 wined3d_shader_incref(This->wined3d_shader);
492 return refcount;
495 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_Release(ID3D10PixelShader *iface)
497 struct d3d10_pixel_shader *This = impl_from_ID3D10PixelShader(iface);
498 ULONG refcount = InterlockedDecrement(&This->refcount);
500 TRACE("%p decreasing refcount to %u\n", This, refcount);
502 if (!refcount)
504 ID3D10Device1 *device = This->device;
506 wined3d_shader_decref(This->wined3d_shader);
507 /* Release the device last, it may cause the wined3d device to be
508 * destroyed. */
509 ID3D10Device1_Release(device);
512 return refcount;
515 /* ID3D10DeviceChild methods */
517 static void STDMETHODCALLTYPE d3d10_pixel_shader_GetDevice(ID3D10PixelShader *iface, ID3D10Device **device)
519 struct d3d10_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
521 TRACE("iface %p, device %p.\n", iface, device);
523 *device = (ID3D10Device *)shader->device;
524 ID3D10Device_AddRef(*device);
527 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_GetPrivateData(ID3D10PixelShader *iface,
528 REFGUID guid, UINT *data_size, void *data)
530 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
531 iface, debugstr_guid(guid), data_size, data);
533 return E_NOTIMPL;
536 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateData(ID3D10PixelShader *iface,
537 REFGUID guid, UINT data_size, const void *data)
539 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
540 iface, debugstr_guid(guid), data_size, data);
542 return E_NOTIMPL;
545 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateDataInterface(ID3D10PixelShader *iface,
546 REFGUID guid, const IUnknown *data)
548 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
550 return E_NOTIMPL;
553 static const struct ID3D10PixelShaderVtbl d3d10_pixel_shader_vtbl =
555 /* IUnknown methods */
556 d3d10_pixel_shader_QueryInterface,
557 d3d10_pixel_shader_AddRef,
558 d3d10_pixel_shader_Release,
559 /* ID3D10DeviceChild methods */
560 d3d10_pixel_shader_GetDevice,
561 d3d10_pixel_shader_GetPrivateData,
562 d3d10_pixel_shader_SetPrivateData,
563 d3d10_pixel_shader_SetPrivateDataInterface,
566 static void STDMETHODCALLTYPE d3d10_pixel_shader_wined3d_object_destroyed(void *parent)
568 HeapFree(GetProcessHeap(), 0, parent);
571 static const struct wined3d_parent_ops d3d10_pixel_shader_wined3d_parent_ops =
573 d3d10_pixel_shader_wined3d_object_destroyed,
576 HRESULT d3d10_pixel_shader_init(struct d3d10_pixel_shader *shader, struct d3d10_device *device,
577 const void *byte_code, SIZE_T byte_code_length)
579 struct wined3d_shader_signature output_signature;
580 struct wined3d_shader_signature input_signature;
581 struct d3d10_shader_info shader_info;
582 struct wined3d_shader_desc desc;
583 HRESULT hr;
585 shader->ID3D10PixelShader_iface.lpVtbl = &d3d10_pixel_shader_vtbl;
586 shader->refcount = 1;
588 shader_info.input_signature = &input_signature;
589 shader_info.output_signature = &output_signature;
590 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info)))
592 ERR("Failed to extract shader, hr %#x.\n", hr);
593 return hr;
596 desc.byte_code = shader_info.shader_code;
597 desc.input_signature = &input_signature;
598 desc.output_signature = &output_signature;
599 desc.max_version = 4;
601 hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader,
602 &d3d10_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader);
603 shader_free_signature(&input_signature);
604 shader_free_signature(&output_signature);
605 if (FAILED(hr))
607 WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
608 return E_INVALIDARG;
611 shader->device = &device->ID3D10Device1_iface;
612 ID3D10Device1_AddRef(shader->device);
614 return S_OK;
617 struct d3d10_pixel_shader *unsafe_impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
619 if (!iface)
620 return NULL;
621 assert(iface->lpVtbl == &d3d10_pixel_shader_vtbl);
623 return impl_from_ID3D10PixelShader(iface);