d3d9/tests: Give the texture transform test a defined colorop.
[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 "d3d9_private.h"
22
23 WINE_DEFAULT_DEBUG_CHANNEL(d3d9);
24
25 static inline struct d3d9_vertexshader *impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
26 {
27     return CONTAINING_RECORD(iface, struct d3d9_vertexshader, IDirect3DVertexShader9_iface);
28 }
29
30 static HRESULT WINAPI d3d9_vertexshader_QueryInterface(IDirect3DVertexShader9 *iface, REFIID riid, void **out)
31 {
32     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
33
34     if (IsEqualGUID(riid, &IID_IDirect3DVertexShader9)
35             || IsEqualGUID(riid, &IID_IUnknown))
36     {
37         IDirect3DVertexShader9_AddRef(iface);
38         *out = iface;
39         return S_OK;
40     }
41
42     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
43
44     *out = NULL;
45     return E_NOINTERFACE;
46 }
47
48 static ULONG WINAPI d3d9_vertexshader_AddRef(IDirect3DVertexShader9 *iface)
49 {
50     struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
51     ULONG refcount = InterlockedIncrement(&shader->refcount);
52
53     TRACE("%p increasing refcount to %u.\n", iface, refcount);
54
55     if (refcount == 1)
56     {
57         IDirect3DDevice9Ex_AddRef(shader->parent_device);
58         wined3d_mutex_lock();
59         wined3d_shader_incref(shader->wined3d_shader);
60         wined3d_mutex_unlock();
61     }
62
63     return refcount;
64 }
65
66 static ULONG WINAPI d3d9_vertexshader_Release(IDirect3DVertexShader9 *iface)
67 {
68     struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
69     ULONG refcount = InterlockedDecrement(&shader->refcount);
70
71     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
72
73     if (!refcount)
74     {
75         IDirect3DDevice9Ex *device = shader->parent_device;
76
77         wined3d_mutex_lock();
78         wined3d_shader_decref(shader->wined3d_shader);
79         wined3d_mutex_unlock();
80
81         /* Release the device last, as it may cause the device to be destroyed. */
82         IDirect3DDevice9Ex_Release(device);
83     }
84
85     return refcount;
86 }
87
88 static HRESULT WINAPI d3d9_vertexshader_GetDevice(IDirect3DVertexShader9 *iface, IDirect3DDevice9 **device)
89 {
90     struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
91
92     TRACE("iface %p, device %p.\n", iface, device);
93
94     *device = (IDirect3DDevice9 *)shader->parent_device;
95     IDirect3DDevice9_AddRef(*device);
96
97     TRACE("Returning device %p.\n", *device);
98
99     return D3D_OK;
100 }
101
102 static HRESULT WINAPI d3d9_vertexshader_GetFunction(IDirect3DVertexShader9 *iface, void *data, UINT *data_size)
103 {
104     struct d3d9_vertexshader *shader = impl_from_IDirect3DVertexShader9(iface);
105     HRESULT hr;
106
107     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
108
109     wined3d_mutex_lock();
110     hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
111     wined3d_mutex_unlock();
112
113     return hr;
114 }
115
116 static const IDirect3DVertexShader9Vtbl d3d9_vertexshader_vtbl =
117 {
118     /* IUnknown */
119     d3d9_vertexshader_QueryInterface,
120     d3d9_vertexshader_AddRef,
121     d3d9_vertexshader_Release,
122     /* IDirect3DVertexShader9 */
123     d3d9_vertexshader_GetDevice,
124     d3d9_vertexshader_GetFunction,
125 };
126
127 static void STDMETHODCALLTYPE d3d9_vertexshader_wined3d_object_destroyed(void *parent)
128 {
129     HeapFree(GetProcessHeap(), 0, parent);
130 }
131
132 static const struct wined3d_parent_ops d3d9_vertexshader_wined3d_parent_ops =
133 {
134     d3d9_vertexshader_wined3d_object_destroyed,
135 };
136
137 HRESULT vertexshader_init(struct d3d9_vertexshader *shader, struct d3d9_device *device, const DWORD *byte_code)
138 {
139     HRESULT hr;
140
141     shader->refcount = 1;
142     shader->IDirect3DVertexShader9_iface.lpVtbl = &d3d9_vertexshader_vtbl;
143
144     wined3d_mutex_lock();
145     hr = wined3d_shader_create_vs(device->wined3d_device, byte_code, NULL,
146             shader, &d3d9_vertexshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
147     wined3d_mutex_unlock();
148     if (FAILED(hr))
149     {
150         WARN("Failed to create wined3d vertex shader, hr %#x.\n", hr);
151         return hr;
152     }
153
154     shader->parent_device = &device->IDirect3DDevice9Ex_iface;
155     IDirect3DDevice9Ex_AddRef(shader->parent_device);
156
157     return D3D_OK;
158 }
159
160 struct d3d9_vertexshader *unsafe_impl_from_IDirect3DVertexShader9(IDirect3DVertexShader9 *iface)
161 {
162     if (!iface)
163         return NULL;
164     assert(iface->lpVtbl == &d3d9_vertexshader_vtbl);
165
166     return impl_from_IDirect3DVertexShader9(iface);
167 }
168
169 static inline struct d3d9_pixelshader *impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
170 {
171     return CONTAINING_RECORD(iface, struct d3d9_pixelshader, IDirect3DPixelShader9_iface);
172 }
173
174 static HRESULT WINAPI d3d9_pixelshader_QueryInterface(IDirect3DPixelShader9 *iface, REFIID riid, void **out)
175 {
176     TRACE("iface %p, riid %s, out %p.\n", iface, debugstr_guid(riid), out);
177
178     if (IsEqualGUID(riid, &IID_IDirect3DPixelShader9)
179             || IsEqualGUID(riid, &IID_IUnknown))
180     {
181         IDirect3DPixelShader9_AddRef(iface);
182         *out = iface;
183         return S_OK;
184     }
185
186     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid));
187
188     *out = NULL;
189     return E_NOINTERFACE;
190 }
191
192 static ULONG WINAPI d3d9_pixelshader_AddRef(IDirect3DPixelShader9 *iface)
193 {
194     struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
195     ULONG refcount = InterlockedIncrement(&shader->refcount);
196
197     TRACE("%p increasing refcount to %u.\n", iface, refcount);
198
199     if (refcount == 1)
200     {
201         IDirect3DDevice9Ex_AddRef(shader->parent_device);
202         wined3d_mutex_lock();
203         wined3d_shader_incref(shader->wined3d_shader);
204         wined3d_mutex_unlock();
205     }
206
207     return refcount;
208 }
209
210 static ULONG WINAPI d3d9_pixelshader_Release(IDirect3DPixelShader9 *iface)
211 {
212     struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
213     ULONG refcount = InterlockedDecrement(&shader->refcount);
214
215     TRACE("%p decreasing refcount to %u.\n", iface, refcount);
216
217     if (!refcount)
218     {
219         IDirect3DDevice9Ex *device = shader->parent_device;
220
221         wined3d_mutex_lock();
222         wined3d_shader_decref(shader->wined3d_shader);
223         wined3d_mutex_unlock();
224
225         /* Release the device last, as it may cause the device to be destroyed. */
226         IDirect3DDevice9Ex_Release(device);
227     }
228
229     return refcount;
230 }
231
232 static HRESULT WINAPI d3d9_pixelshader_GetDevice(IDirect3DPixelShader9 *iface, IDirect3DDevice9 **device)
233 {
234     struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
235
236     TRACE("iface %p, device %p.\n", iface, device);
237
238     *device = (IDirect3DDevice9 *)shader->parent_device;
239     IDirect3DDevice9_AddRef(*device);
240
241     TRACE("Returning device %p.\n", *device);
242
243     return D3D_OK;
244 }
245
246 static HRESULT WINAPI d3d9_pixelshader_GetFunction(IDirect3DPixelShader9 *iface, void *data, UINT *data_size)
247 {
248     struct d3d9_pixelshader *shader = impl_from_IDirect3DPixelShader9(iface);
249     HRESULT hr;
250
251     TRACE("iface %p, data %p, data_size %p.\n", iface, data, data_size);
252
253     wined3d_mutex_lock();
254     hr = wined3d_shader_get_byte_code(shader->wined3d_shader, data, data_size);
255     wined3d_mutex_unlock();
256
257     return hr;
258 }
259
260 static const IDirect3DPixelShader9Vtbl d3d9_pixelshader_vtbl =
261 {
262     /* IUnknown */
263     d3d9_pixelshader_QueryInterface,
264     d3d9_pixelshader_AddRef,
265     d3d9_pixelshader_Release,
266     /* IDirect3DPixelShader9 */
267     d3d9_pixelshader_GetDevice,
268     d3d9_pixelshader_GetFunction,
269 };
270
271 static void STDMETHODCALLTYPE d3d9_pixelshader_wined3d_object_destroyed(void *parent)
272 {
273     HeapFree(GetProcessHeap(), 0, parent);
274 }
275
276 static const struct wined3d_parent_ops d3d9_pixelshader_wined3d_parent_ops =
277 {
278     d3d9_pixelshader_wined3d_object_destroyed,
279 };
280
281 HRESULT pixelshader_init(struct d3d9_pixelshader *shader, struct d3d9_device *device, const DWORD *byte_code)
282 {
283     HRESULT hr;
284
285     shader->refcount = 1;
286     shader->IDirect3DPixelShader9_iface.lpVtbl = &d3d9_pixelshader_vtbl;
287
288     wined3d_mutex_lock();
289     hr = wined3d_shader_create_ps(device->wined3d_device, byte_code, NULL, shader,
290             &d3d9_pixelshader_wined3d_parent_ops, &shader->wined3d_shader, 3);
291     wined3d_mutex_unlock();
292     if (FAILED(hr))
293     {
294         WARN("Failed to created wined3d pixel shader, hr %#x.\n", hr);
295         return hr;
296     }
297
298     shader->parent_device = &device->IDirect3DDevice9Ex_iface;
299     IDirect3DDevice9Ex_AddRef(shader->parent_device);
300
301     return D3D_OK;
302 }
303
304 struct d3d9_pixelshader *unsafe_impl_from_IDirect3DPixelShader9(IDirect3DPixelShader9 *iface)
305 {
306     if (!iface)
307         return NULL;
308     assert(iface->lpVtbl == &d3d9_pixelshader_vtbl);
309
310     return impl_from_IDirect3DPixelShader9(iface);
311 }