wineps: Simplify the failure path.
[wine/multimedia.git] / dlls / d3d10core / shader.c
blob82ddadc49800cc59b719626a56c6b64adc695997
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_INVALIDARG;
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, 4);
266 if (FAILED(hr))
268 WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
269 shader_free_signature(&shader->output_signature);
270 hr = E_INVALIDARG;
271 return hr;
274 return S_OK;
277 struct d3d10_vertex_shader *unsafe_impl_from_ID3D10VertexShader(ID3D10VertexShader *iface)
279 if (!iface)
280 return NULL;
281 assert(iface->lpVtbl == &d3d10_vertex_shader_vtbl);
283 return impl_from_ID3D10VertexShader(iface);
286 static inline struct d3d10_geometry_shader *impl_from_ID3D10GeometryShader(ID3D10GeometryShader *iface)
288 return CONTAINING_RECORD(iface, struct d3d10_geometry_shader, ID3D10GeometryShader_iface);
291 /* IUnknown methods */
293 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_QueryInterface(ID3D10GeometryShader *iface,
294 REFIID riid, void **object)
296 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
298 if (IsEqualGUID(riid, &IID_ID3D10GeometryShader)
299 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
300 || IsEqualGUID(riid, &IID_IUnknown))
302 IUnknown_AddRef(iface);
303 *object = iface;
304 return S_OK;
307 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
309 *object = NULL;
310 return E_NOINTERFACE;
313 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_AddRef(ID3D10GeometryShader *iface)
315 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
316 ULONG refcount = InterlockedIncrement(&This->refcount);
318 TRACE("%p increasing refcount to %u\n", This, refcount);
320 return refcount;
323 static ULONG STDMETHODCALLTYPE d3d10_geometry_shader_Release(ID3D10GeometryShader *iface)
325 struct d3d10_geometry_shader *This = impl_from_ID3D10GeometryShader(iface);
326 ULONG refcount = InterlockedDecrement(&This->refcount);
328 TRACE("%p decreasing refcount to %u\n", This, refcount);
330 if (!refcount)
331 wined3d_shader_decref(This->wined3d_shader);
333 return refcount;
336 /* ID3D10DeviceChild methods */
338 static void STDMETHODCALLTYPE d3d10_geometry_shader_GetDevice(ID3D10GeometryShader *iface, ID3D10Device **device)
340 FIXME("iface %p, device %p stub!\n", iface, device);
343 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_GetPrivateData(ID3D10GeometryShader *iface,
344 REFGUID guid, UINT *data_size, void *data)
346 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
347 iface, debugstr_guid(guid), data_size, data);
349 return E_NOTIMPL;
352 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateData(ID3D10GeometryShader *iface,
353 REFGUID guid, UINT data_size, const void *data)
355 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
356 iface, debugstr_guid(guid), data_size, data);
358 return E_NOTIMPL;
361 static HRESULT STDMETHODCALLTYPE d3d10_geometry_shader_SetPrivateDataInterface(ID3D10GeometryShader *iface,
362 REFGUID guid, const IUnknown *data)
364 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
366 return E_NOTIMPL;
369 static const struct ID3D10GeometryShaderVtbl d3d10_geometry_shader_vtbl =
371 /* IUnknown methods */
372 d3d10_geometry_shader_QueryInterface,
373 d3d10_geometry_shader_AddRef,
374 d3d10_geometry_shader_Release,
375 /* ID3D10DeviceChild methods */
376 d3d10_geometry_shader_GetDevice,
377 d3d10_geometry_shader_GetPrivateData,
378 d3d10_geometry_shader_SetPrivateData,
379 d3d10_geometry_shader_SetPrivateDataInterface,
382 static void STDMETHODCALLTYPE d3d10_geometry_shader_wined3d_object_destroyed(void *parent)
384 struct d3d10_geometry_shader *shader = parent;
385 shader_free_signature(&shader->output_signature);
386 HeapFree(GetProcessHeap(), 0, shader);
389 static const struct wined3d_parent_ops d3d10_geometry_shader_wined3d_parent_ops =
391 d3d10_geometry_shader_wined3d_object_destroyed,
394 HRESULT d3d10_geometry_shader_init(struct d3d10_geometry_shader *shader, struct d3d10_device *device,
395 const void *byte_code, SIZE_T byte_code_length)
397 struct d3d10_shader_info shader_info;
398 HRESULT hr;
400 shader->ID3D10GeometryShader_iface.lpVtbl = &d3d10_geometry_shader_vtbl;
401 shader->refcount = 1;
403 shader_info.output_signature = &shader->output_signature;
404 hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info);
405 if (FAILED(hr))
407 ERR("Failed to extract shader, hr %#x.\n", hr);
408 return hr;
411 hr = wined3d_shader_create_gs(device->wined3d_device, shader_info.shader_code,
412 &shader->output_signature, shader, &d3d10_geometry_shader_wined3d_parent_ops, &shader->wined3d_shader, 4);
413 if (FAILED(hr))
415 WARN("Failed to create wined3d geometry shader, hr %#x.\n", hr);
416 shader_free_signature(&shader->output_signature);
417 hr = E_INVALIDARG;
418 return hr;
421 return S_OK;
424 static inline struct d3d10_pixel_shader *impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
426 return CONTAINING_RECORD(iface, struct d3d10_pixel_shader, ID3D10PixelShader_iface);
429 /* IUnknown methods */
431 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_QueryInterface(ID3D10PixelShader *iface,
432 REFIID riid, void **object)
434 TRACE("iface %p, riid %s, object %p\n", iface, debugstr_guid(riid), object);
436 if (IsEqualGUID(riid, &IID_ID3D10PixelShader)
437 || IsEqualGUID(riid, &IID_ID3D10DeviceChild)
438 || IsEqualGUID(riid, &IID_IUnknown))
440 IUnknown_AddRef(iface);
441 *object = iface;
442 return S_OK;
445 WARN("%s not implemented, returning E_NOINTERFACE\n", debugstr_guid(riid));
447 *object = NULL;
448 return E_NOINTERFACE;
451 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_AddRef(ID3D10PixelShader *iface)
453 struct d3d10_pixel_shader *This = impl_from_ID3D10PixelShader(iface);
454 ULONG refcount = InterlockedIncrement(&This->refcount);
456 TRACE("%p increasing refcount to %u\n", This, refcount);
458 if (refcount == 1)
459 wined3d_shader_incref(This->wined3d_shader);
461 return refcount;
464 static ULONG STDMETHODCALLTYPE d3d10_pixel_shader_Release(ID3D10PixelShader *iface)
466 struct d3d10_pixel_shader *This = impl_from_ID3D10PixelShader(iface);
467 ULONG refcount = InterlockedDecrement(&This->refcount);
469 TRACE("%p decreasing refcount to %u\n", This, refcount);
471 if (!refcount)
472 wined3d_shader_decref(This->wined3d_shader);
474 return refcount;
477 /* ID3D10DeviceChild methods */
479 static void STDMETHODCALLTYPE d3d10_pixel_shader_GetDevice(ID3D10PixelShader *iface, ID3D10Device **device)
481 FIXME("iface %p, device %p stub!\n", iface, device);
484 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_GetPrivateData(ID3D10PixelShader *iface,
485 REFGUID guid, UINT *data_size, void *data)
487 FIXME("iface %p, guid %s, data_size %p, data %p stub!\n",
488 iface, debugstr_guid(guid), data_size, data);
490 return E_NOTIMPL;
493 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateData(ID3D10PixelShader *iface,
494 REFGUID guid, UINT data_size, const void *data)
496 FIXME("iface %p, guid %s, data_size %u, data %p stub!\n",
497 iface, debugstr_guid(guid), data_size, data);
499 return E_NOTIMPL;
502 static HRESULT STDMETHODCALLTYPE d3d10_pixel_shader_SetPrivateDataInterface(ID3D10PixelShader *iface,
503 REFGUID guid, const IUnknown *data)
505 FIXME("iface %p, guid %s, data %p stub!\n", iface, debugstr_guid(guid), data);
507 return E_NOTIMPL;
510 static const struct ID3D10PixelShaderVtbl d3d10_pixel_shader_vtbl =
512 /* IUnknown methods */
513 d3d10_pixel_shader_QueryInterface,
514 d3d10_pixel_shader_AddRef,
515 d3d10_pixel_shader_Release,
516 /* ID3D10DeviceChild methods */
517 d3d10_pixel_shader_GetDevice,
518 d3d10_pixel_shader_GetPrivateData,
519 d3d10_pixel_shader_SetPrivateData,
520 d3d10_pixel_shader_SetPrivateDataInterface,
523 static void STDMETHODCALLTYPE d3d10_pixel_shader_wined3d_object_destroyed(void *parent)
525 struct d3d10_pixel_shader *shader = parent;
526 shader_free_signature(&shader->output_signature);
527 HeapFree(GetProcessHeap(), 0, shader);
530 static const struct wined3d_parent_ops d3d10_pixel_shader_wined3d_parent_ops =
532 d3d10_pixel_shader_wined3d_object_destroyed,
535 HRESULT d3d10_pixel_shader_init(struct d3d10_pixel_shader *shader, struct d3d10_device *device,
536 const void *byte_code, SIZE_T byte_code_length)
538 struct d3d10_shader_info shader_info;
539 HRESULT hr;
541 shader->ID3D10PixelShader_iface.lpVtbl = &d3d10_pixel_shader_vtbl;
542 shader->refcount = 1;
544 shader_info.output_signature = &shader->output_signature;
545 hr = shader_extract_from_dxbc(byte_code, byte_code_length, &shader_info);
546 if (FAILED(hr))
548 ERR("Failed to extract shader, hr %#x.\n", hr);
549 return hr;
552 hr = wined3d_shader_create_ps(device->wined3d_device, shader_info.shader_code,
553 &shader->output_signature, shader, &d3d10_pixel_shader_wined3d_parent_ops, &shader->wined3d_shader, 4);
554 if (FAILED(hr))
556 WARN("Failed to create wined3d pixel shader, hr %#x.\n", hr);
557 shader_free_signature(&shader->output_signature);
558 hr = E_INVALIDARG;
559 return hr;
562 return S_OK;
565 struct d3d10_pixel_shader *unsafe_impl_from_ID3D10PixelShader(ID3D10PixelShader *iface)
567 if (!iface)
568 return NULL;
569 assert(iface->lpVtbl == &d3d10_pixel_shader_vtbl);
571 return impl_from_ID3D10PixelShader(iface);