kernel32: Forward RtlRaiseException to ntdll on ARM.
[wine] / dlls / d3d9 / shader.c
1 /*
2  * Copyright 2002-2003 Jason Edmeades
3  *                     Raphael Junqueira
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include "config.h"
21 #include <assert.h>
22 #include "d3d9_private.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
25
26 static inline IDirect3DVertexShader9Impl *impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
27 {
28     return CONTAINING_RECORD(iface, IDirect3DVertexShader9Impl, IDirect3DVertexShader9_iface);
29 }
30
31 static HRESULT WINAPI d3d9_vertexshader_QueryInterface(IDirect3DVertexShader9 *iface, REFIID riid, void **object)
32 {
33     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
34
35     if (IsEqualGUID(riid, &IID_IDirect3DVertexShader9)
36             || IsEqualGUID(riid, &IID_IUnknown))
37     {
38         IDirect3DVertexShader9_AddRef(iface);
39         *object = iface;
40         return S_OK;
41     }
42
43     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
44
45     *object = NULL;
46     return E_NOINTERFACE;
47 }
48
49 static ULONG WINAPI d3d9_vertexshader_AddRef(IDirect3DVertexShader9 *iface)
50 {
51     IDirect3DVertexShader9Impl *shader = impl_from_IDirect3DVertexShader9(iface);
52     ULONG refcount = InterlockedIncrement(&shader->ref);
53
54     TRACE("%p increasing refcount to %u.\n", iface, refcount);
55
56     if (refcount == 1)
57     {
58         IDirect3DDevice9Ex_AddRef(shader->parentDevice);
59         wined3d_mutex_lock();
60         wined3d_shader_incref(shader->wined3d_shader);
61         wined3d_mutex_unlock();
62     }
63
64     return refcount;
65 }
66
67 static ULONG WINAPI d3d9_vertexshader_Release(IDirect3DVertexShader9 *iface)
68 {
69     IDirect3DVertexShader9Impl *shader = impl_from_IDirect3DVertexShader9(iface);
70     ULONG refcount = InterlockedDecrement(&shader->ref);
71
72     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
73
74     if (!refcount)
75     {
76         IDirect3DDevice9Ex *device = shader->parentDevice;
77
78         wined3d_mutex_lock();
79         wined3d_shader_decref(shader->wined3d_shader);
80         wined3d_mutex_unlock();
81
82         /* Release the device last, as it may cause the device to be destroyed. */
83         IDirect3DDevice9Ex_Release(device);
84     }
85
86     return refcount;
87 }
88
89 static HRESULT WINAPI d3d9_vertexshader_GetDevice(IDirect3DVertexShader9 *iface, IDirect3DDevice9 **device)
90 {
91     IDirect3DVertexShader9Impl *shader = impl_from_IDirect3DVertexShader9(iface);
92
93     TRACE("iface %p, device %p.\n", iface, device);
94
95     *device = (IDirect3DDevice9 *)shader->parentDevice;
96     IDirect3DDevice9_AddRef(*device);
97
98     TRACE("Returning device %p.\n", *device);
99
100     return D3D_OK;
101 }
102
103 static HRESULT WINAPI d3d9_vertexshader_GetFunction(IDirect3DVertexShader9 *iface,
104         void *data, UINT *data_size)
105 {
106     IDirect3DVertexShader9Impl *shader = impl_from_IDirect3DVertexShader9(iface);
107     HRESULT hr;
108
109     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
110
111     wined3d_mutex_lock();
112     hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
113     wined3d_mutex_unlock();
114
115     return hr;
116 }
117
118 static const IDirect3DVertexShader9Vtbl d3d9_vertexshader_vtbl =
119 {
120     /* IUnknown */
121     d3d9_vertexshader_QueryInterface,
122     d3d9_vertexshader_AddRef,
123     d3d9_vertexshader_Release,
124     /* IDirect3DVertexShader9 */
125     d3d9_vertexshader_GetDevice,
126     d3d9_vertexshader_GetFunction,
127 };
128
129 static void STDMETHODCALLTYPE d3d9_vertexshader_wined3d_object_destroyed(void *parent)
130 {
131     HeapFree(GetProcessHeap(), 0, parent);
132 }
133
134 static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops =
135 {
136     d3d9_vertexshader_wined3d_object_destroyed,
137 };
138
139 HRESULT vertexshader_init(IDirect3DVertexShader9Impl *shader, IDirect3DDevice9Impl *device, const DWORD *byte_code)
140 {
141     HRESULT hr;
142
143     shader->ref = 1;
144     shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl;
145
146     wined3d_mutex_lock();
147     hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL,
148             shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
149     wined3d_mutex_unlock();
150     if (FAILED(hr))
151     {
152         WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
153         return hr;
154     }
155
156     shader->parentDevice = &device->IDirect3DDevice9Ex_iface;
157     IDirect3DDevice9Ex_AddRef(shader->parentDevice);
158
159     return D3D_OK;
160 }
161
162 IDirect3DVertexShader9Impl *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
163 {
164     if (!iface)
165         return NULL;
166     assert(iface->lpVtbl == &d3d9_vertexshader_vtbl);
167
168     return impl_from_IDirect3DVertexShader9(iface);
169 }
170
171 static inline IDirect3DPixelShader9Impl *impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
172 {
173     return CONTAINING_RECORD(iface, IDirect3DPixelShader9Impl, IDirect3DPixelShader9_iface);
174 }
175
176 static HRESULT WINAPI d3d9_pixelshader_QueryInterface(IDirect3DPixelShader9 *iface, REFIID riid, void **object)
177 {
178     TRACE("iface %p, riid %s, object %p.\n", iface, debugstr_guid(riid), object);
179
180     if (IsEqualGUID(riid, &IID_IDirect3DPixelShader9)
181             || IsEqualGUID(riid, &IID_IUnknown))
182     {
183         IDirect3DPixelShader9_AddRef(iface);
184         *object = iface;
185         return S_OK;
186     }
187
188     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
189
190     *object = NULL;
191     return E_NOINTERFACE;
192 }
193
194 static ULONG WINAPI d3d9_pixelshader_AddRef(IDirect3DPixelShader9 *iface)
195 {
196     IDirect3DPixelShader9Impl *shader = impl_from_IDirect3DPixelShader9(iface);
197     ULONG refcount = InterlockedIncrement(&shader->ref);
198
199     TRACE("%p increasing refcount to %u.\n", iface, refcount);
200
201     if (refcount == 1)
202     {
203         IDirect3DDevice9Ex_AddRef(shader->parentDevice);
204         wined3d_mutex_lock();
205         wined3d_shader_incref(shader->wined3d_shader);
206         wined3d_mutex_unlock();
207     }
208
209     return refcount;
210 }
211
212 static ULONG WINAPI d3d9_pixelshader_Release(IDirect3DPixelShader9 *iface)
213 {
214     IDirect3DPixelShader9Impl *shader = impl_from_IDirect3DPixelShader9(iface);
215     ULONG refcount = InterlockedDecrement(&shader->ref);
216
217     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
218
219     if (!refcount)
220     {
221         IDirect3DDevice9Ex *device = shader->parentDevice;
222
223         wined3d_mutex_lock();
224         wined3d_shader_decref(shader->wined3d_shader);
225         wined3d_mutex_unlock();
226
227         /* Release the device last, as it may cause the device to be destroyed. */
228         IDirect3DDevice9Ex_Release(device);
229     }
230
231     return refcount;
232 }
233
234 static HRESULT WINAPI d3d9_pixelshader_GetDevice(IDirect3DPixelShader9 *iface,
235         IDirect3DDevice9 **device)
236 {
237     IDirect3DPixelShader9Impl *shader = impl_from_IDirect3DPixelShader9(iface);
238
239     TRACE("iface %p, device %p.\n", iface, device);
240
241     *device = (IDirect3DDevice9 *)shader->parentDevice;
242     IDirect3DDevice9_AddRef(*device);
243
244     TRACE("Returning device %p.\n", *device);
245
246     return D3D_OK;
247 }
248
249 static HRESULT WINAPI d3d9_pixelshader_GetFunction(IDirect3DPixelShader9 *iface, void *data,
250         UINT *data_size)
251 {
252     IDirect3DPixelShader9Impl *shader = impl_from_IDirect3DPixelShader9(iface);
253     HRESULT hr;
254
255     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
256
257     wined3d_mutex_lock();
258     hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
259     wined3d_mutex_unlock();
260
261     return hr;
262 }
263
264 static const IDirect3DPixelShader9Vtbl d3d9_pixelshader_vtbl =
265 {
266     /* IUnknown */
267     d3d9_pixelshader_QueryInterface,
268     d3d9_pixelshader_AddRef,
269     d3d9_pixelshader_Release,
270     /* IDirect3DPixelShader9 */
271     d3d9_pixelshader_GetDevice,
272     d3d9_pixelshader_GetFunction,
273 };
274
275 static void STDMETHODCALLTYPE d3d9_pixelshader_wined3d_object_destroyed(void *parent)
276 {
277     HeapFree(GetProcessHeap(), 0, parent);
278 }
279
280 static const struct wined3d_parent_ops d3d9_pixelshader_wined3d_parent_ops =
281 {
282     d3d9_pixelshader_wined3d_object_destroyed,
283 };
284
285 HRESULT pixelshader_init(IDirect3DPixelShader9Impl *shader, IDirect3DDevice9Impl *device, const DWORD *byte_code)
286 {
287     HRESULT hr;
288
289     shader->ref = 1;
290     shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl;
291
292     wined3d_mutex_lock();
293     hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader,
294             &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
295     wined3d_mutex_unlock();
296     if (FAILED(hr))
297     {
298         WARN("Failed to created wined3d pixel shader, hr %#x.\n", hr);
299         return hr;
300     }
301
302     shader->parentDevice = &device->IDirect3DDevice9Ex_iface;
303     IDirect3DDevice9Ex_AddRef(shader->parentDevice);
304
305     return D3D_OK;
306 }
307
308 IDirect3DPixelShader9Impl *unsafe_impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
309 {
310     if (!iface)
311         return NULL;
312     assert(iface->lpVtbl == &d3d9_pixelshader_vtbl);
313
314     return impl_from_IDirect3DPixelShader9(iface);
315 }