d3d10core: Use unsafe_impl_from_ID3D10PixelShader for an app provided iface.
[wine.git] / dlls / d3d10core / shader.c
blob79131e1cfdde3539f8532bbd99357afddaddbe8c
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"
22 #include <assert.h>
24 #include "d3d10core_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d10core);
28 static HRESULT shdr_handler(const char *data, DWORD data_size, DWORD tag, void *ctx)
30 struct d3d10_shader_info *shader_info = ctx;
31 HRESULT hr;
33 switch(tag)
35 case TAG_OSGN:
36 hr = shader_parse_signature(data, data_size, shader_info->output_signature);
37 if (FAILED(hr)) return hr;
38 break;
40 case TAG_SHDR:
41 shader_info->shader_code = (const DWORD *)data;
42 break;
44 default:
45 FIXME("Unhandled chunk %s\n", debugstr_an((const char *)&tag, 4));
46 break;
49 return S_OK;
52 static HRESULT shader_extract_from_dxbc(const void *dxbc, SIZE_T dxbc_length, struct d3d10_shader_info *shader_info)
54 HRESULT hr;
56 shader_info->shader_code = NULL;
57 memset(shader_info->output_signature, 0, sizeof(*shader_info->output_signature));
59 hr = parse_dxbc(dxbc, dxbc_length, shdr_handler, shader_info);
60 if (!shader_info->shader_code) hr = E_FAIL;
62 if (FAILED(hr))
64 ERR("Failed to parse shader, hr %#x\n", hr);
65 shader_free_signature(shader_info->output_signature);
68 return hr;
71 HRESULT shader_parse_signature(const char *data, DWORD data_size, struct wined3d_shader_signature *s)
73 struct wined3d_shader_signature_element *e;
74 unsigned int string_data_offset;
75 unsigned int string_data_size;
76 const char *ptr = data;
77 char *string_data;
78 unsigned int i;
79 DWORD count;
81 read_dword(&ptr, &count);
82 TRACE("%u elements\n", count);
84 skip_dword_unknown(&ptr, 1);
86 e = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*e));
87 if (!e)
89 ERR("Failed to allocate input signature memory.\n");
90 return E_OUTOFMEMORY;
93 /* 2 DWORDs for the header, 6 for each element. */
94 string_data_offset = 2 * sizeof(DWORD) + count * 6 * sizeof(DWORD);
95 string_data_size = data_size - string_data_offset;
96 string_data = HeapAlloc(GetProcessHeap(), 0, string_data_size);
97 if (!string_data)
99 ERR("Failed to allocate string data memory.\n");
100 HeapFree(GetProcessHeap(), 0, e);
101 return E_OUTOFMEMORY;
103 memcpy(string_data, data + string_data_offset, string_data_size);
105 for (i = 0; i < count; ++i)
107 UINT name_offset;
109 read_dword(&ptr, &name_offset);
110 e[i].semantic_name = string_data + (name_offset - string_data_offset);
111 read_dword(&ptr, &e[i].semantic_idx);
112 read_dword(&ptr, &e[i].sysval_semantic);
113 read_dword(&ptr, &e[i].component_type);
114 read_dword(&ptr, &e[i].register_idx);
115 read_dword(&ptr, &e[i].mask);
117 TRACE("semantic: %s, semantic idx: %u, sysval_semantic %#x, "
118 "type %u, register idx: %u, use_mask %#x, input_mask %#x\n",
119 debugstr_a(e[i].semantic_name), e[i].semantic_idx, e[i].sysval_semantic,
120 e[i].component_type, e[i].register_idx, (e[i].mask >> 8) & 0xff, e[i].mask & 0xff);
123 s->elements = e;
124 s->element_count = count;
125 s->string_data = string_data;
127 return S_OK;
130 void shader_free_signature(struct wined3d_shader_signature *s)
132 HeapFree(GetProcessHeap(), 0, s->string_data);
133 HeapFree(GetProcessHeap(), 0, s->elements);
136 static inline struct d3d10_vertex_shader *impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
138 return CONTAINING_RECORD(iface, struct d3d10_vertex_shader, ID3D10VertexShader_iface);
141 /* IUnknown methods */
143 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_QueryInterface(ID3D10VertexShader *iface,
144 REFIID riid, void **object)
146 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
148 if (IsEqualGUID(riid, &IID_ID3D10VertexShader)
149 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
150 || IsEqualGUID(riid, &IID_IUnknown))
152 IUnknown_AddRef(iface);
153 *object = iface;
154 return S_OK;
157 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
159 *object = NULL;
160 return E_NOINTERFACE;
163 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_AddRef(ID3D10VertexShader *iface)
165 struct d3d10_vertex_shader *This = impl_from_ID3D10VertexShader(iface);
166 ULONG refcount = InterlockedIncrement(&This->refcount);
168 TRACE("%p increasing refcount to %u\n", This, refcount);
170 if (refcount == 1)
171 wined3d_shader_incref(This->wined3d_shader);
173 return refcount;
176 static ULONG STDMETHODCALLTYPE d3d10_vertex_shader_Release(ID3D10VertexShader *iface)
178 struct d3d10_vertex_shader *This = impl_from_ID3D10VertexShader(iface);
179 ULONG refcount = InterlockedDecrement(&This->refcount);
181 TRACE("%p decreasing refcount to %u\n", This, refcount);
183 if (!refcount)
184 wined3d_shader_decref(This->wined3d_shader);
186 return refcount;
189 /* ID3D10DeviceChild methods */
191 static void STDMETHODCALLTYPE d3d10_vertex_shader_GetDevice(ID3D10VertexShader *iface, ID3D10Device **device)
193 FIXME("iface %p, device %p stub!\n", iface, device);
196 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_GetPrivateData(ID3D10VertexShader *iface,
197 REFGUID guid, UINT *data_size, void *data)
199 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
200 iface, debugstr_guid(guid), data_size, data);
202 return E_NOTIMPL;
205 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateData(ID3D10VertexShader *iface,
206 REFGUID guid, UINT data_size, const void *data)
208 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
209 iface, debugstr_guid(guid), data_size, data);
211 return E_NOTIMPL;
214 static HRESULT STDMETHODCALLTYPE d3d10_vertex_shader_SetPrivateDataInterface(ID3D10VertexShader *iface,
215 REFGUID guid, const IUnknown *data)
217 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
219 return E_NOTIMPL;
222 static const struct ID3D10VertexShaderVtbl d3d10_vertex_shader_vtbl =
224 /* IUnknown methods */
225 d3d10_vertex_shader_QueryInterface,
226 d3d10_vertex_shader_AddRef,
227 d3d10_vertex_shader_Release,
228 /* ID3D10DeviceChild methods */
229 d3d10_vertex_shader_GetDevice,
230 d3d10_vertex_shader_GetPrivateData,
231 d3d10_vertex_shader_SetPrivateData,
232 d3d10_vertex_shader_SetPrivateDataInterface,
235 static void STDMETHODCALLTYPE d3d10_vertex_shader_wined3d_object_destroyed(void *parent)
237 struct d3d10_vertex_shader *shader = parent;
238 shader_free_signature(&shader->output_signature);
239 HeapFree(GetProcessHeap(), 0, shader);
242 static const struct wined3d_parent_ops d3d10_vertex_shader_wined3d_parent_ops =
244 d3d10_vertex_shader_wined3d_object_destroyed,
247 HRESULT d3d10_vertex_shader_init(struct d3d10_vertex_shader *shader, struct d3d10_device *device,
248 const void *byte_code, SIZE_T byte_code_length)
250 struct d3d10_shader_info shader_info;
251 HRESULT hr;
253 shader->ID3D10VertexShader_iface.lpVtbl = &d3d10_vertex_shader_vtbl;
254 shader->refcount = 1;
256 shader_info.output_signature = &shader->output_signature;
257 hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info);
258 if (FAILED(hr))
260 ERR("Failed to extract shader, hr %#x.\n", hr);
261 return hr;
264 hr = wined3d_shader_create_vs(device->wined3d_device, shader_info.shader_code,
265 &shader->output_signature, shader, &d3d10_vertex_shader_wined3d_parent_ops, &shader->wined3d_shader);
266 if (FAILED(hr))
268 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
269 shader_free_signature(&shader->output_signature);
270 return hr;
273 return S_OK;
276 struct d3d10_vertex_shader *unsafe_impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
278 if (!iface)
279 return NULL;
280 assert(iface->lpVtbl == &d3d10_vertex_shader_vtbl);
282 return impl_from_ID3D10VertexShader(iface);
285 static inline struct d3d10_geometry_shader *impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
287 return CONTAINING_RECORD(iface, struct d3d10_geometry_shader, ID3D10GeometryShader_iface);
290 /* IUnknown methods */
292 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
293 REFIID riid, void **object)
295 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
297 if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
298 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
299 || IsEqualGUID(riid, &IID_IUnknown))
301 IUnknown_AddRef(iface);
302 *object = iface;
303 return S_OK;
306 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
308 *object = NULL;
309 return E_NOINTERFACE;
312 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
314 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
315 ULONG refcount = InterlockedIncrement(&This->refcount);
317 TRACE("%p increasing refcount to %u\n", This, refcount);
319 return refcount;
322 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
324 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
325 ULONG refcount = InterlockedDecrement(&This->refcount);
327 TRACE("%p decreasing refcount to %u\n", This, refcount);
329 if (!refcount)
330 wined3d_shader_decref(This->wined3d_shader);
332 return refcount;
335 /* ID3D10DeviceChild methods */
337 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
339 FIXME("iface %p, device %p stub!\n", iface, device);
342 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
343 REFGUID guid, UINT *data_size, void *data)
345 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
346 iface, debugstr_guid(guid), data_size, data);
348 return E_NOTIMPL;
351 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
352 REFGUID guid, UINT data_size, const void *data)
354 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
355 iface, debugstr_guid(guid), data_size, data);
357 return E_NOTIMPL;
360 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
361 REFGUID guid, const IUnknown *data)
363 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
365 return E_NOTIMPL;
368 static const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
370 /* IUnknown methods */
371 d3d10_geometry_shader_QueryInterface,
372 d3d10_geometry_shader_AddRef,
373 d3d10_geometry_shader_Release,
374 /* ID3D10DeviceChild methods */
375 d3d10_geometry_shader_GetDevice,
376 d3d10_geometry_shader_GetPrivateData,
377 d3d10_geometry_shader_SetPrivateData,
378 d3d10_geometry_shader_SetPrivateDataInterface,
381 static void STDMETHODCALLTYPE d3d10_geometry_shader_wined3d_object_destroyed(void *parent)
383 struct d3d10_geometry_shader *shader = parent;
384 shader_free_signature(&shader->output_signature);
385 HeapFree(GetProcessHeap(), 0, shader);
388 static const struct wined3d_parent_ops d3d10_geometry_shader_wined3d_parent_ops =
390 d3d10_geometry_shader_wined3d_object_destroyed,
393 HRESULT d3d10_geometry_shader_init(struct d3d10_geometry_shader *shader, struct d3d10_device *device,
394 const void *byte_code, SIZE_T byte_code_length)
396 struct d3d10_shader_info shader_info;
397 HRESULT hr;
399 shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl;
400 shader->refcount = 1;
402 shader_info.output_signature = &shader->output_signature;
403 hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info);
404 if (FAILED(hr))
406 ERR("Failed to extract shader, hr %#x.\n", hr);
407 return hr;
410 hr = wined3d_shader_create_gs(device->wined3d_device, shader_info.shader_code,
411 &shader->output_signature, shader, &d3d10_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader);
412 if (FAILED(hr))
414 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
415 shader_free_signature(&shader->output_signature);
416 return hr;
419 return S_OK;
422 static inline struct d3d10_pixel_shader *impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
424 return CONTAINING_RECORD(iface, struct d3d10_pixel_shader, vtbl);
427 /* IUnknown methods */
429 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_QueryInterface(ID3D10PixelShader *iface,
430 REFIID riid, void **object)
432 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
434 if (IsEqualGUID(riid, &IID_ID3D10PixelShader)
435 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
436 || IsEqualGUID(riid, &IID_IUnknown))
438 IUnknown_AddRef(iface);
439 *object = iface;
440 return S_OK;
443 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
445 *object = NULL;
446 return E_NOINTERFACE;
449 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_AddRef(ID3D10PixelShader *iface)
451 struct d3d10_pixel_shader *This = (struct d3d10_pixel_shader *)iface;
452 ULONG refcount = InterlockedIncrement(&This->refcount);
454 TRACE("%p increasing refcount to %u\n", This, refcount);
456 if (refcount == 1)
457 wined3d_shader_incref(This->wined3d_shader);
459 return refcount;
462 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_Release(ID3D10PixelShader *iface)
464 struct d3d10_pixel_shader *This = (struct d3d10_pixel_shader *)iface;
465 ULONG refcount = InterlockedDecrement(&This->refcount);
467 TRACE("%p decreasing refcount to %u\n", This, refcount);
469 if (!refcount)
470 wined3d_shader_decref(This->wined3d_shader);
472 return refcount;
475 /* ID3D10DeviceChild methods */
477 static void STDMETHODCALLTYPE d3d10_pixel_shader_GetDevice(ID3D10PixelShader *iface, ID3D10Device **device)
479 FIXME("iface %p, device %p stub!\n", iface, device);
482 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_GetPrivateData(ID3D10PixelShader *iface,
483 REFGUID guid, UINT *data_size, void *data)
485 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
486 iface, debugstr_guid(guid), data_size, data);
488 return E_NOTIMPL;
491 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateData(ID3D10PixelShader *iface,
492 REFGUID guid, UINT data_size, const void *data)
494 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
495 iface, debugstr_guid(guid), data_size, data);
497 return E_NOTIMPL;
500 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateDataInterface(ID3D10PixelShader *iface,
501 REFGUID guid, const IUnknown *data)
503 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
505 return E_NOTIMPL;
508 static const struct ID3D10PixelShaderVtbl d3d10_pixel_shader_vtbl =
510 /* IUnknown methods */
511 d3d10_pixel_shader_QueryInterface,
512 d3d10_pixel_shader_AddRef,
513 d3d10_pixel_shader_Release,
514 /* ID3D10DeviceChild methods */
515 d3d10_pixel_shader_GetDevice,
516 d3d10_pixel_shader_GetPrivateData,
517 d3d10_pixel_shader_SetPrivateData,
518 d3d10_pixel_shader_SetPrivateDataInterface,
521 static void STDMETHODCALLTYPE d3d10_pixel_shader_wined3d_object_destroyed(void *parent)
523 struct d3d10_pixel_shader *shader = parent;
524 shader_free_signature(&shader->output_signature);
525 HeapFree(GetProcessHeap(), 0, shader);
528 static const struct wined3d_parent_ops d3d10_pixel_shader_wined3d_parent_ops =
530 d3d10_pixel_shader_wined3d_object_destroyed,
533 HRESULT d3d10_pixel_shader_init(struct d3d10_pixel_shader *shader, struct d3d10_device *device,
534 const void *byte_code, SIZE_T byte_code_length)
536 struct d3d10_shader_info shader_info;
537 HRESULT hr;
539 shader->vtbl = &d3d10_pixel_shader_vtbl;
540 shader->refcount = 1;
542 shader_info.output_signature = &shader->output_signature;
543 hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info);
544 if (FAILED(hr))
546 ERR("Failed to extract shader, hr %#x.\n", hr);
547 return hr;
550 hr = wined3d_shader_create_ps(device->wined3d_device, shader_info.shader_code,
551 &shader->output_signature, shader, &d3d10_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader);
552 if (FAILED(hr))
554 WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
555 shader_free_signature(&shader->output_signature);
556 return hr;
559 return S_OK;
562 struct d3d10_pixel_shader *unsafe_impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
564 if (!iface)
565 return NULL;
566 assert(iface->lpVtbl == &d3d10_pixel_shader_vtbl);
568 return impl_from_ID3D10PixelShader(iface);