ddraw: Replace the light list with a standard Wine list.
[wine] / dlls / ddraw / light.c
1 /* Direct3D Light
2  * Copyright (c) 1998 / 2002 Lionel ULMER
3  * Copyright (c) 2006        Stefan DÖSINGER
4  *
5  * This file contains the implementation of Direct3DLight.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include "ddraw_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
28
29 /*****************************************************************************
30  * light_update
31  *
32  * Updates the Direct3DDevice7 lighting parameters
33  *
34  *****************************************************************************/
35 static void light_update(IDirect3DLightImpl *light)
36 {
37     IDirect3DDeviceImpl *device;
38
39     TRACE("light %p.\n", light);
40
41     if (!light->active_viewport || !light->active_viewport->active_device) return;
42     device = light->active_viewport->active_device;
43
44     IDirect3DDevice7_SetLight((IDirect3DDevice7 *)device, light->dwLightIndex, &light->light7);
45 }
46
47 /*****************************************************************************
48  * light_activate
49  *
50  * Uses the Direct3DDevice7::LightEnable method to active the light
51  *
52  *****************************************************************************/
53 void light_activate(IDirect3DLightImpl *light)
54 {
55     IDirect3DDeviceImpl *device;
56
57     TRACE("light %p.\n", light);
58
59     if (!light->active_viewport || !light->active_viewport->active_device) return;
60     device = light->active_viewport->active_device;
61
62     light_update(light);
63     if (!(light->light.dwFlags & D3DLIGHT_ACTIVE))
64     {
65         IDirect3DDevice7_LightEnable((IDirect3DDevice7 *)device, light->dwLightIndex, TRUE);
66         light->light.dwFlags |= D3DLIGHT_ACTIVE;
67     }
68 }
69
70 /*****************************************************************************
71  *
72  * light_deactivate
73  *
74  * Uses the Direct3DDevice7::LightEnable method to deactivate the light
75  *
76  *****************************************************************************/
77 void light_deactivate(IDirect3DLightImpl *light)
78 {
79     IDirect3DDeviceImpl *device;
80
81     TRACE("light %p.\n", light);
82
83     if (!light->active_viewport || !light->active_viewport->active_device) return;
84     device = light->active_viewport->active_device;
85
86     /* If was not active, activate it */
87     if (light->light.dwFlags & D3DLIGHT_ACTIVE)
88     {
89         IDirect3DDevice7_LightEnable((IDirect3DDevice7 *)device, light->dwLightIndex, FALSE);
90         light->light.dwFlags &= ~D3DLIGHT_ACTIVE;
91     }
92 }
93
94 /*****************************************************************************
95  * IUnknown Methods.
96  *****************************************************************************/
97
98 /*****************************************************************************
99  * IDirect3DLight::QueryInterface
100  *
101  * Queries the object for different interfaces. Unimplemented for this
102  * object at the moment
103  *
104  * Params:
105  *  riid: Interface id asked for
106  *  obj: Address to return the resulting pointer at.
107  *
108  * Returns:
109  *  E_NOINTERFACE, because it's a stub
110  *****************************************************************************/
111 static HRESULT WINAPI IDirect3DLightImpl_QueryInterface(IDirect3DLight *iface, REFIID riid, void **object)
112 {
113     FIXME("iface %p, riid %s, object %p stub!\n", iface, debugstr_guid(riid), object);
114
115     *object = NULL;
116     return E_NOINTERFACE;
117 }
118
119 /*****************************************************************************
120  * IDirect3DLight::AddRef
121  *
122  * Increases the refcount by 1
123  *
124  * Returns:
125  *  The new refcount
126  *
127  *****************************************************************************/
128 static ULONG WINAPI
129 IDirect3DLightImpl_AddRef(IDirect3DLight *iface)
130 {
131     IDirect3DLightImpl *This = (IDirect3DLightImpl *)iface;
132     ULONG ref = InterlockedIncrement(&This->ref);
133
134     TRACE("%p increasing refcount to %u.\n", This, ref);
135
136     return ref;
137 }
138
139 /*****************************************************************************
140  * IDirect3DLight::Release
141  *
142  * Reduces the refcount by one. If the refcount falls to 0, the object
143  * is destroyed
144  *
145  * Returns:
146  *  The new refcount
147  *
148  *****************************************************************************/
149 static ULONG WINAPI
150 IDirect3DLightImpl_Release(IDirect3DLight *iface)
151 {
152     IDirect3DLightImpl *This = (IDirect3DLightImpl *)iface;
153     ULONG ref = InterlockedDecrement(&This->ref);
154
155     TRACE("%p decreasing refcount to %u.\n", This, ref);
156
157     if (!ref) {
158         HeapFree(GetProcessHeap(), 0, This);
159         return 0;
160     }
161     return ref;
162 }
163
164 /*****************************************************************************
165  * IDirect3DLight Methods.
166  *****************************************************************************/
167
168 /*****************************************************************************
169  * IDirect3DLight::Initialize
170  *
171  * Initializes the interface. This implementation is a no-op, because
172  * initialization takes place at creation time
173  *
174  * Params:
175  *  Direct3D: Pointer to an IDirect3D interface.
176  *
177  * Returns:
178  *  D3D_OK
179  *
180  *****************************************************************************/
181 static HRESULT WINAPI IDirect3DLightImpl_Initialize(IDirect3DLight *iface, IDirect3D *d3d)
182 {
183     TRACE("iface %p, d3d %p.\n", iface, d3d);
184
185     return D3D_OK;
186 }
187
188 /*****************************************************************************
189  * IDirect3DLight::SetLight
190  *
191  * Assigns a lighting value to this object
192  *
193  * Params:
194  *  Light: Lighting parameter to set
195  *
196  * Returns:
197  *  D3D_OK on success
198  *  DDERR_INVALIDPARAMS if Light is NULL
199  *
200  *****************************************************************************/
201 static void dump_light(const D3DLIGHT2 *light)
202 {
203     TRACE("    - dwSize : %d\n", light->dwSize);
204 }
205
206 static const float zero_value[] = {
207     0.0, 0.0, 0.0, 0.0
208 };
209
210 static HRESULT WINAPI
211 IDirect3DLightImpl_SetLight(IDirect3DLight *iface,
212                             D3DLIGHT *lpLight)
213 {
214     IDirect3DLightImpl *This = (IDirect3DLightImpl *)iface;
215     LPD3DLIGHT7 light7 = &(This->light7);
216
217     TRACE("iface %p, light %p.\n", iface, lpLight);
218
219     if (TRACE_ON(ddraw))
220     {
221         TRACE("  Light definition :\n");
222         dump_light((LPD3DLIGHT2) lpLight);
223     }
224
225     if ( (lpLight->dltType == 0) || (lpLight->dltType > D3DLIGHT_PARALLELPOINT) )
226          return DDERR_INVALIDPARAMS;
227
228     if ( lpLight->dltType == D3DLIGHT_PARALLELPOINT )
229         FIXME("D3DLIGHT_PARALLELPOINT no supported\n");
230
231     /* Translate D3DLIGH2 structure to D3DLIGHT7 */
232     light7->dltType        = lpLight->dltType;
233     light7->dcvDiffuse     = lpLight->dcvColor;
234     if ((((LPD3DLIGHT2)lpLight)->dwFlags & D3DLIGHT_NO_SPECULAR) != 0)
235       light7->dcvSpecular    = lpLight->dcvColor;
236     else
237       light7->dcvSpecular    = *(const D3DCOLORVALUE*)zero_value;
238     light7->dcvAmbient     = lpLight->dcvColor;
239     light7->dvPosition     = lpLight->dvPosition;
240     light7->dvDirection    = lpLight->dvDirection;
241     light7->dvRange        = lpLight->dvRange;
242     light7->dvFalloff      = lpLight->dvFalloff;
243     light7->dvAttenuation0 = lpLight->dvAttenuation0;
244     light7->dvAttenuation1 = lpLight->dvAttenuation1;
245     light7->dvAttenuation2 = lpLight->dvAttenuation2;
246     light7->dvTheta        = lpLight->dvTheta;
247     light7->dvPhi          = lpLight->dvPhi;
248
249     EnterCriticalSection(&ddraw_cs);
250     memcpy(&This->light, lpLight, lpLight->dwSize);
251     if (This->light.dwFlags & D3DLIGHT_ACTIVE)
252         light_update(This);
253     LeaveCriticalSection(&ddraw_cs);
254     return D3D_OK;
255 }
256
257 /*****************************************************************************
258  * IDirect3DLight::GetLight
259  *
260  * Returns the parameters currently assigned to the IDirect3DLight object
261  *
262  * Params:
263  *  Light: Pointer to an D3DLIGHT structure to store the parameters
264  *
265  * Returns:
266  *  D3D_OK on success
267  *  DDERR_INVALIDPARAMS if Light is NULL
268  *****************************************************************************/
269 static HRESULT WINAPI
270 IDirect3DLightImpl_GetLight(IDirect3DLight *iface,
271                             D3DLIGHT *lpLight)
272 {
273     IDirect3DLightImpl *This = (IDirect3DLightImpl *)iface;
274
275     TRACE("iface %p, light %p.\n", iface, lpLight);
276
277     if (TRACE_ON(ddraw))
278     {
279         TRACE("  Returning light definition :\n");
280         dump_light(&This->light);
281     }
282
283     EnterCriticalSection(&ddraw_cs);
284     memcpy(lpLight, &This->light, lpLight->dwSize);
285     LeaveCriticalSection(&ddraw_cs);
286
287     return DD_OK;
288 }
289
290 static const struct IDirect3DLightVtbl d3d_light_vtbl =
291 {
292     /*** IUnknown Methods ***/
293     IDirect3DLightImpl_QueryInterface,
294     IDirect3DLightImpl_AddRef,
295     IDirect3DLightImpl_Release,
296     /*** IDirect3DLight Methods ***/
297     IDirect3DLightImpl_Initialize,
298     IDirect3DLightImpl_SetLight,
299     IDirect3DLightImpl_GetLight
300 };
301
302 void d3d_light_init(IDirect3DLightImpl *light, IDirectDrawImpl *ddraw)
303 {
304     light->lpVtbl = &d3d_light_vtbl;
305     light->ref = 1;
306     light->ddraw = ddraw;
307 }