d3d10core: Implement d3d10_vertex_shader_GetPrivateData().
[wine/multimedia.git] / dlls / d3d10core / shader.c
blob8010828a61aa2ecead55e9bad33ada6d1b7e0be7
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 struct d3d10_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
205 TRACE("iface %p, guid %s, data_size %p, data %p.\n",
206 iface, debugstr_guid(guid), data_size, data);
208 return d3d10_get_private_data(&shader->private_store, guid, data_size, data);
211 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateData(ID3D10VertexShader *iface,
212 REFGUID guid, UINT data_size, const void *data)
214 struct d3d10_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
216 TRACE("iface %p, guid %s, data_size %u, data %p.\n",
217 iface, debugstr_guid(guid), data_size, data);
219 return d3d10_set_private_data(&shader->private_store, guid, data_size, data);
222 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateDataInterface(ID3D10VertexShader *iface,
223 REFGUID guid, const IUnknown *data)
225 struct d3d10_vertex_shader *shader = impl_from_ID3D10VertexShader(iface);
227 TRACE("iface %p, guid %s, data %p.\n", iface, debugstr_guid(guid), data);
229 return d3d10_set_private_data_interface(&shader->private_store, guid, data);
232 static const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
234 /* IUnknown methods */
235 d3d10_vertex_shader_QueryInterface,
236 d3d10_vertex_shader_AddRef,
237 d3d10_vertex_shader_Release,
238 /* ID3D10DeviceChild methods */
239 d3d10_vertex_shader_GetDevice,
240 d3d10_vertex_shader_GetPrivateData,
241 d3d10_vertex_shader_SetPrivateData,
242 d3d10_vertex_shader_SetPrivateDataInterface,
245 static void STDMETHODCALLTYPE d3d10_vertex_shader_wined3d_object_destroyed(void *parent)
247 struct d3d10_vertex_shader *shader = parent;
249 wined3d_private_store_cleanup(&shader->private_store);
250 HeapFree(GetProcessHeap(), 0, parent);
253 static const struct wined3d_parent_ops d3d10_vertex_shader_wined3d_parent_ops =
255 d3d10_vertex_shader_wined3d_object_destroyed,
258 HRESULT d3d10_vertex_shader_init(struct d3d10_vertex_shader *shader, struct d3d10_device *device,
259 const void *byte_code, SIZE_T byte_code_length)
261 struct wined3d_shader_signature output_signature;
262 struct wined3d_shader_signature input_signature;
263 struct d3d10_shader_info shader_info;
264 struct wined3d_shader_desc desc;
265 HRESULT hr;
267 shader->ID3D10VertexShader_iface.lpVtbl = &d3d10_vertex_shader_vtbl;
268 shader->refcount = 1;
269 wined3d_private_store_init(&shader->private_store);
271 shader_info.input_signature = &input_signature;
272 shader_info.output_signature = &output_signature;
273 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info)))
275 ERR("Failed to extract shader, hr %#x.\n", hr);
276 wined3d_private_store_cleanup(&shader->private_store);
277 return hr;
280 desc.byte_code = shader_info.shader_code;
281 desc.input_signature = &input_signature;
282 desc.output_signature = &output_signature;
283 desc.max_version = 4;
285 hr = wined3d_shader_create_vs(device->wined3d_device, &desc, shader,
286 &d3d10_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader);
287 shader_free_signature(&input_signature);
288 shader_free_signature(&output_signature);
289 if (FAILED(hr))
291 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
292 wined3d_private_store_cleanup(&shader->private_store);
293 return E_INVALIDARG;
296 shader->device = &device->ID3D10Device1_iface;
297 ID3D10Device1_AddRef(shader->device);
299 return S_OK;
302 struct d3d10_vertex_shader *unsafe_impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
304 if (!iface)
305 return NULL;
306 assert(iface->lpVtbl == &d3d10_vertex_shader_vtbl);
308 return impl_from_ID3D10VertexShader(iface);
311 static inline struct d3d10_geometry_shader *impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
313 return CONTAINING_RECORD(iface, struct d3d10_geometry_shader, ID3D10GeometryShader_iface);
316 /* IUnknown methods */
318 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
319 REFIID riid, void **object)
321 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
323 if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
324 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
325 || IsEqualGUID(riid, &IID_IUnknown))
327 IUnknown_AddRef(iface);
328 *object = iface;
329 return S_OK;
332 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
334 *object = NULL;
335 return E_NOINTERFACE;
338 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
340 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
341 ULONG refcount = InterlockedIncrement(&This->refcount);
343 TRACE("%p increasing refcount to %u\n", This, refcount);
345 return refcount;
348 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
350 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
351 ULONG refcount = InterlockedDecrement(&This->refcount);
353 TRACE("%p decreasing refcount to %u\n", This, refcount);
355 if (!refcount)
356 wined3d_shader_decref(This->wined3d_shader);
358 return refcount;
361 /* ID3D10DeviceChild methods */
363 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
365 FIXME("iface %p, device %p stub!\n", iface, device);
368 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
369 REFGUID guid, UINT *data_size, void *data)
371 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
372 iface, debugstr_guid(guid), data_size, data);
374 return E_NOTIMPL;
377 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
378 REFGUID guid, UINT data_size, const void *data)
380 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
381 iface, debugstr_guid(guid), data_size, data);
383 return E_NOTIMPL;
386 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
387 REFGUID guid, const IUnknown *data)
389 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
391 return E_NOTIMPL;
394 static const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
396 /* IUnknown methods */
397 d3d10_geometry_shader_QueryInterface,
398 d3d10_geometry_shader_AddRef,
399 d3d10_geometry_shader_Release,
400 /* ID3D10DeviceChild methods */
401 d3d10_geometry_shader_GetDevice,
402 d3d10_geometry_shader_GetPrivateData,
403 d3d10_geometry_shader_SetPrivateData,
404 d3d10_geometry_shader_SetPrivateDataInterface,
407 static void STDMETHODCALLTYPE d3d10_geometry_shader_wined3d_object_destroyed(void *parent)
409 HeapFree(GetProcessHeap(), 0, parent);
412 static const struct wined3d_parent_ops d3d10_geometry_shader_wined3d_parent_ops =
414 d3d10_geometry_shader_wined3d_object_destroyed,
417 HRESULT d3d10_geometry_shader_init(struct d3d10_geometry_shader *shader, struct d3d10_device *device,
418 const void *byte_code, SIZE_T byte_code_length)
420 struct wined3d_shader_signature output_signature;
421 struct wined3d_shader_signature input_signature;
422 struct d3d10_shader_info shader_info;
423 struct wined3d_shader_desc desc;
424 HRESULT hr;
426 shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl;
427 shader->refcount = 1;
429 shader_info.input_signature = &input_signature;
430 shader_info.output_signature = &output_signature;
431 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info)))
433 ERR("Failed to extract shader, hr %#x.\n", hr);
434 return hr;
437 desc.byte_code = shader_info.shader_code;
438 desc.input_signature = &input_signature;
439 desc.output_signature = &output_signature;
440 desc.max_version = 4;
442 hr = wined3d_shader_create_gs(device->wined3d_device, &desc, shader,
443 &d3d10_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
444 shader_free_signature(&input_signature);
445 shader_free_signature(&output_signature);
446 if (FAILED(hr))
448 WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
449 return E_INVALIDARG;
452 return S_OK;
455 struct d3d10_geometry_shader *unsafe_impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
457 if (!iface)
458 return NULL;
459 assert(iface->lpVtbl == &d3d10_geometry_shader_vtbl);
461 return impl_from_ID3D10GeometryShader(iface);
464 static inline struct d3d10_pixel_shader *impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
466 return CONTAINING_RECORD(iface, struct d3d10_pixel_shader, ID3D10PixelShader_iface);
469 /* IUnknown methods */
471 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_QueryInterface(ID3D10PixelShader *iface,
472 REFIID riid, void **object)
474 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
476 if (IsEqualGUID(riid, &IID_ID3D10PixelShader)
477 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
478 || IsEqualGUID(riid, &IID_IUnknown))
480 IUnknown_AddRef(iface);
481 *object = iface;
482 return S_OK;
485 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
487 *object = NULL;
488 return E_NOINTERFACE;
491 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_AddRef(ID3D10PixelShader *iface)
493 struct d3d10_pixel_shader *This = impl_from_ID3D10PixelShader(iface);
494 ULONG refcount = InterlockedIncrement(&This->refcount);
496 TRACE("%p increasing refcount to %u\n", This, refcount);
498 if (refcount == 1)
500 ID3D10Device1_AddRef(This->device);
501 wined3d_shader_incref(This->wined3d_shader);
504 return refcount;
507 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_Release(ID3D10PixelShader *iface)
509 struct d3d10_pixel_shader *This = impl_from_ID3D10PixelShader(iface);
510 ULONG refcount = InterlockedDecrement(&This->refcount);
512 TRACE("%p decreasing refcount to %u\n", This, refcount);
514 if (!refcount)
516 ID3D10Device1 *device = This->device;
518 wined3d_shader_decref(This->wined3d_shader);
519 /* Release the device last, it may cause the wined3d device to be
520 * destroyed. */
521 ID3D10Device1_Release(device);
524 return refcount;
527 /* ID3D10DeviceChild methods */
529 static void STDMETHODCALLTYPE d3d10_pixel_shader_GetDevice(ID3D10PixelShader *iface, ID3D10Device **device)
531 struct d3d10_pixel_shader *shader = impl_from_ID3D10PixelShader(iface);
533 TRACE("iface %p, device %p.\n", iface, device);
535 *device = (ID3D10Device *)shader->device;
536 ID3D10Device_AddRef(*device);
539 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_GetPrivateData(ID3D10PixelShader *iface,
540 REFGUID guid, UINT *data_size, void *data)
542 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
543 iface, debugstr_guid(guid), data_size, data);
545 return E_NOTIMPL;
548 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateData(ID3D10PixelShader *iface,
549 REFGUID guid, UINT data_size, const void *data)
551 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
552 iface, debugstr_guid(guid), data_size, data);
554 return E_NOTIMPL;
557 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateDataInterface(ID3D10PixelShader *iface,
558 REFGUID guid, const IUnknown *data)
560 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
562 return E_NOTIMPL;
565 static const struct ID3D10PixelShaderVtbl d3d10_pixel_shader_vtbl =
567 /* IUnknown methods */
568 d3d10_pixel_shader_QueryInterface,
569 d3d10_pixel_shader_AddRef,
570 d3d10_pixel_shader_Release,
571 /* ID3D10DeviceChild methods */
572 d3d10_pixel_shader_GetDevice,
573 d3d10_pixel_shader_GetPrivateData,
574 d3d10_pixel_shader_SetPrivateData,
575 d3d10_pixel_shader_SetPrivateDataInterface,
578 static void STDMETHODCALLTYPE d3d10_pixel_shader_wined3d_object_destroyed(void *parent)
580 HeapFree(GetProcessHeap(), 0, parent);
583 static const struct wined3d_parent_ops d3d10_pixel_shader_wined3d_parent_ops =
585 d3d10_pixel_shader_wined3d_object_destroyed,
588 HRESULT d3d10_pixel_shader_init(struct d3d10_pixel_shader *shader, struct d3d10_device *device,
589 const void *byte_code, SIZE_T byte_code_length)
591 struct wined3d_shader_signature output_signature;
592 struct wined3d_shader_signature input_signature;
593 struct d3d10_shader_info shader_info;
594 struct wined3d_shader_desc desc;
595 HRESULT hr;
597 shader->ID3D10PixelShader_iface.lpVtbl = &d3d10_pixel_shader_vtbl;
598 shader->refcount = 1;
600 shader_info.input_signature = &input_signature;
601 shader_info.output_signature = &output_signature;
602 if (FAILED(hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info)))
604 ERR("Failed to extract shader, hr %#x.\n", hr);
605 return hr;
608 desc.byte_code = shader_info.shader_code;
609 desc.input_signature = &input_signature;
610 desc.output_signature = &output_signature;
611 desc.max_version = 4;
613 hr = wined3d_shader_create_ps(device->wined3d_device, &desc, shader,
614 &d3d10_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader);
615 shader_free_signature(&input_signature);
616 shader_free_signature(&output_signature);
617 if (FAILED(hr))
619 WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
620 return E_INVALIDARG;
623 shader->device = &device->ID3D10Device1_iface;
624 ID3D10Device1_AddRef(shader->device);
626 return S_OK;
629 struct d3d10_pixel_shader *unsafe_impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
631 if (!iface)
632 return NULL;
633 assert(iface->lpVtbl == &d3d10_pixel_shader_vtbl);
635 return impl_from_ID3D10PixelShader(iface);