xref: /reactos/dll/directx/wine/ddraw/light.c (revision 9987f029)
1c2c66affSColin Finck /* Direct3D Light
2c2c66affSColin Finck  * Copyright (c) 1998 / 2002 Lionel ULMER
3c2c66affSColin Finck  * Copyright (c) 2006        Stefan DÖSINGER
4c2c66affSColin Finck  *
5c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
6c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
7c2c66affSColin Finck  * License as published by the Free Software Foundation; either
8c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
9c2c66affSColin Finck  *
10c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
11c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13c2c66affSColin Finck  * Lesser General Public License for more details.
14c2c66affSColin Finck  *
15c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
16c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
17c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18c2c66affSColin Finck  */
19c2c66affSColin Finck 
20*9987f029SAmine Khaldi #include "config.h"
21*9987f029SAmine Khaldi #include "wine/port.h"
22*9987f029SAmine Khaldi 
23c2c66affSColin Finck #include "ddraw_private.h"
24c2c66affSColin Finck 
25*9987f029SAmine Khaldi WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
26*9987f029SAmine Khaldi 
27c2c66affSColin Finck /*****************************************************************************
28c2c66affSColin Finck  * light_update
29c2c66affSColin Finck  *
30c2c66affSColin Finck  * Updates the Direct3DDevice7 lighting parameters
31c2c66affSColin Finck  *
32c2c66affSColin Finck  *****************************************************************************/
light_update(struct d3d_light * light)33c2c66affSColin Finck static void light_update(struct d3d_light *light)
34c2c66affSColin Finck {
35c2c66affSColin Finck     struct d3d_device *device;
36c2c66affSColin Finck 
37c2c66affSColin Finck     TRACE("light %p.\n", light);
38c2c66affSColin Finck 
39c2c66affSColin Finck     if (!light->active_viewport || !light->active_viewport->active_device) return;
40c2c66affSColin Finck     device = light->active_viewport->active_device;
41c2c66affSColin Finck 
42c2c66affSColin Finck     IDirect3DDevice7_SetLight(&device->IDirect3DDevice7_iface, light->dwLightIndex, &light->light7);
43c2c66affSColin Finck }
44c2c66affSColin Finck 
45c2c66affSColin Finck /*****************************************************************************
46c2c66affSColin Finck  * light_activate
47c2c66affSColin Finck  *
48c2c66affSColin Finck  * Uses the Direct3DDevice7::LightEnable method to active the light
49c2c66affSColin Finck  *
50c2c66affSColin Finck  *****************************************************************************/
light_activate(struct d3d_light * light)51c2c66affSColin Finck void light_activate(struct d3d_light *light)
52c2c66affSColin Finck {
53c2c66affSColin Finck     struct d3d_device *device;
54c2c66affSColin Finck 
55c2c66affSColin Finck     TRACE("light %p.\n", light);
56c2c66affSColin Finck 
57c2c66affSColin Finck     if (!light->active_viewport || !light->active_viewport->active_device) return;
58c2c66affSColin Finck     device = light->active_viewport->active_device;
59c2c66affSColin Finck 
60c2c66affSColin Finck     light_update(light);
61c2c66affSColin Finck     if (!(light->light.dwFlags & D3DLIGHT_ACTIVE))
62c2c66affSColin Finck     {
63c2c66affSColin Finck         IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->dwLightIndex, TRUE);
64c2c66affSColin Finck         light->light.dwFlags |= D3DLIGHT_ACTIVE;
65c2c66affSColin Finck     }
66c2c66affSColin Finck }
67c2c66affSColin Finck 
68c2c66affSColin Finck /*****************************************************************************
69c2c66affSColin Finck  *
70c2c66affSColin Finck  * light_deactivate
71c2c66affSColin Finck  *
72c2c66affSColin Finck  * Uses the Direct3DDevice7::LightEnable method to deactivate the light
73c2c66affSColin Finck  *
74c2c66affSColin Finck  *****************************************************************************/
light_deactivate(struct d3d_light * light)75c2c66affSColin Finck void light_deactivate(struct d3d_light *light)
76c2c66affSColin Finck {
77c2c66affSColin Finck     struct d3d_device *device;
78c2c66affSColin Finck 
79c2c66affSColin Finck     TRACE("light %p.\n", light);
80c2c66affSColin Finck 
81c2c66affSColin Finck     if (!light->active_viewport || !light->active_viewport->active_device) return;
82c2c66affSColin Finck     device = light->active_viewport->active_device;
83c2c66affSColin Finck 
84c2c66affSColin Finck     if (light->light.dwFlags & D3DLIGHT_ACTIVE)
85c2c66affSColin Finck     {
86c2c66affSColin Finck         IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->dwLightIndex, FALSE);
87c2c66affSColin Finck         light->light.dwFlags &= ~D3DLIGHT_ACTIVE;
88c2c66affSColin Finck     }
89c2c66affSColin Finck }
90c2c66affSColin Finck 
impl_from_IDirect3DLight(IDirect3DLight * iface)91c2c66affSColin Finck static inline struct d3d_light *impl_from_IDirect3DLight(IDirect3DLight *iface)
92c2c66affSColin Finck {
93c2c66affSColin Finck     return CONTAINING_RECORD(iface, struct d3d_light, IDirect3DLight_iface);
94c2c66affSColin Finck }
95c2c66affSColin Finck 
96c2c66affSColin Finck /*****************************************************************************
97c2c66affSColin Finck  * IDirect3DLight::QueryInterface
98c2c66affSColin Finck  *
99c2c66affSColin Finck  * Queries the object for different interfaces. Unimplemented for this
100c2c66affSColin Finck  * object at the moment
101c2c66affSColin Finck  *
102c2c66affSColin Finck  * Params:
103c2c66affSColin Finck  *  riid: Interface id asked for
104c2c66affSColin Finck  *  obj: Address to return the resulting pointer at.
105c2c66affSColin Finck  *
106c2c66affSColin Finck  * Returns:
107c2c66affSColin Finck  *  E_NOINTERFACE, because it's a stub
108c2c66affSColin Finck  *****************************************************************************/
d3d_light_QueryInterface(IDirect3DLight * iface,REFIID riid,void ** object)109c2c66affSColin Finck static HRESULT WINAPI d3d_light_QueryInterface(IDirect3DLight *iface, REFIID riid, void **object)
110c2c66affSColin Finck {
111c2c66affSColin Finck     FIXME("iface %p, riid %s, object %p stub!\n", iface, debugstr_guid(riid), object);
112c2c66affSColin Finck 
113c2c66affSColin Finck     *object = NULL;
114c2c66affSColin Finck     return E_NOINTERFACE;
115c2c66affSColin Finck }
116c2c66affSColin Finck 
d3d_light_AddRef(IDirect3DLight * iface)117c2c66affSColin Finck static ULONG WINAPI d3d_light_AddRef(IDirect3DLight *iface)
118c2c66affSColin Finck {
119c2c66affSColin Finck     struct d3d_light *light = impl_from_IDirect3DLight(iface);
120c2c66affSColin Finck     ULONG ref = InterlockedIncrement(&light->ref);
121c2c66affSColin Finck 
122c2c66affSColin Finck     TRACE("%p increasing refcount to %u.\n", light, ref);
123c2c66affSColin Finck 
124c2c66affSColin Finck     return ref;
125c2c66affSColin Finck }
126c2c66affSColin Finck 
d3d_light_Release(IDirect3DLight * iface)127c2c66affSColin Finck static ULONG WINAPI d3d_light_Release(IDirect3DLight *iface)
128c2c66affSColin Finck {
129c2c66affSColin Finck     struct d3d_light *light = impl_from_IDirect3DLight(iface);
130c2c66affSColin Finck     ULONG ref = InterlockedDecrement(&light->ref);
131c2c66affSColin Finck 
132c2c66affSColin Finck     TRACE("%p decreasing refcount to %u.\n", light, ref);
133c2c66affSColin Finck 
134c2c66affSColin Finck     if (!ref)
135c2c66affSColin Finck     {
136*9987f029SAmine Khaldi         heap_free(light);
137c2c66affSColin Finck         return 0;
138c2c66affSColin Finck     }
139c2c66affSColin Finck     return ref;
140c2c66affSColin Finck }
141c2c66affSColin Finck 
142c2c66affSColin Finck /*****************************************************************************
143c2c66affSColin Finck  * IDirect3DLight Methods.
144c2c66affSColin Finck  *****************************************************************************/
145c2c66affSColin Finck 
146c2c66affSColin Finck /*****************************************************************************
147c2c66affSColin Finck  * IDirect3DLight::Initialize
148c2c66affSColin Finck  *
149c2c66affSColin Finck  * Initializes the interface. This implementation is a no-op, because
150c2c66affSColin Finck  * initialization takes place at creation time
151c2c66affSColin Finck  *
152c2c66affSColin Finck  * Params:
153c2c66affSColin Finck  *  Direct3D: Pointer to an IDirect3D interface.
154c2c66affSColin Finck  *
155c2c66affSColin Finck  * Returns:
156c2c66affSColin Finck  *  D3D_OK
157c2c66affSColin Finck  *
158c2c66affSColin Finck  *****************************************************************************/
d3d_light_Initialize(IDirect3DLight * iface,IDirect3D * d3d)159c2c66affSColin Finck static HRESULT WINAPI d3d_light_Initialize(IDirect3DLight *iface, IDirect3D *d3d)
160c2c66affSColin Finck {
161c2c66affSColin Finck     TRACE("iface %p, d3d %p.\n", iface, d3d);
162c2c66affSColin Finck 
163c2c66affSColin Finck     return D3D_OK;
164c2c66affSColin Finck }
165c2c66affSColin Finck 
d3d_light_SetLight(IDirect3DLight * iface,D3DLIGHT * data)166c2c66affSColin Finck static HRESULT WINAPI d3d_light_SetLight(IDirect3DLight *iface, D3DLIGHT *data)
167c2c66affSColin Finck {
168c2c66affSColin Finck     static const D3DCOLORVALUE zero_value = {{0.0f}, {0.0f}, {0.0f}, {0.0f}};
169c2c66affSColin Finck     struct d3d_light *light = impl_from_IDirect3DLight(iface);
170c2c66affSColin Finck     DWORD flags = data->dwSize >= sizeof(D3DLIGHT2) ? ((D3DLIGHT2 *)data)->dwFlags : D3DLIGHT_ACTIVE;
171c2c66affSColin Finck     D3DLIGHT7 *light7 = &light->light7;
172c2c66affSColin Finck 
173c2c66affSColin Finck     TRACE("iface %p, data %p.\n", iface, data);
174c2c66affSColin Finck 
175c2c66affSColin Finck     if ((!data->dltType) || (data->dltType > D3DLIGHT_PARALLELPOINT))
176c2c66affSColin Finck          return DDERR_INVALIDPARAMS;
177c2c66affSColin Finck 
178c2c66affSColin Finck     /* Translate D3DLIGHT2 structure to D3DLIGHT7. */
179c2c66affSColin Finck     light7->dltType = data->dltType;
180c2c66affSColin Finck     light7->dcvDiffuse = data->dcvColor;
181c2c66affSColin Finck     if (flags & D3DLIGHT_NO_SPECULAR)
182c2c66affSColin Finck         light7->dcvSpecular = zero_value;
183c2c66affSColin Finck     else
184c2c66affSColin Finck         light7->dcvSpecular = data->dcvColor;
185c2c66affSColin Finck     light7->dcvAmbient = data->dcvColor;
186c2c66affSColin Finck     light7->dvPosition = data->dvPosition;
187c2c66affSColin Finck     light7->dvDirection = data->dvDirection;
188c2c66affSColin Finck     light7->dvRange = data->dvRange;
189c2c66affSColin Finck     light7->dvFalloff = data->dvFalloff;
190c2c66affSColin Finck     light7->dvAttenuation0 = data->dvAttenuation0;
191c2c66affSColin Finck     light7->dvAttenuation1 = data->dvAttenuation1;
192c2c66affSColin Finck     light7->dvAttenuation2 = data->dvAttenuation2;
193c2c66affSColin Finck     light7->dvTheta = data->dvTheta;
194c2c66affSColin Finck     light7->dvPhi = data->dvPhi;
195c2c66affSColin Finck 
196c2c66affSColin Finck     wined3d_mutex_lock();
197c2c66affSColin Finck     memcpy(&light->light, data, sizeof(*data));
198c2c66affSColin Finck     if (!(light->light.dwFlags & D3DLIGHT_ACTIVE) && flags & D3DLIGHT_ACTIVE)
199c2c66affSColin Finck         light_activate(light);
200c2c66affSColin Finck     else if (light->light.dwFlags & D3DLIGHT_ACTIVE && !(flags & D3DLIGHT_ACTIVE))
201c2c66affSColin Finck         light_deactivate(light);
202c2c66affSColin Finck     else if (flags & D3DLIGHT_ACTIVE)
203c2c66affSColin Finck         light_update(light);
204c2c66affSColin Finck     light->light.dwFlags = flags;
205c2c66affSColin Finck     wined3d_mutex_unlock();
206c2c66affSColin Finck 
207c2c66affSColin Finck     return D3D_OK;
208c2c66affSColin Finck }
209c2c66affSColin Finck 
210c2c66affSColin Finck /*****************************************************************************
211c2c66affSColin Finck  * IDirect3DLight::GetLight
212c2c66affSColin Finck  *
213c2c66affSColin Finck  * Returns the parameters currently assigned to the IDirect3DLight object
214c2c66affSColin Finck  *
215c2c66affSColin Finck  * Params:
216c2c66affSColin Finck  *  Light: Pointer to an D3DLIGHT structure to store the parameters
217c2c66affSColin Finck  *
218c2c66affSColin Finck  * Returns:
219c2c66affSColin Finck  *  D3D_OK on success
220c2c66affSColin Finck  *  DDERR_INVALIDPARAMS if Light is NULL
221c2c66affSColin Finck  *****************************************************************************/
d3d_light_GetLight(IDirect3DLight * iface,D3DLIGHT * lpLight)222c2c66affSColin Finck static HRESULT WINAPI d3d_light_GetLight(IDirect3DLight *iface, D3DLIGHT *lpLight)
223c2c66affSColin Finck {
224c2c66affSColin Finck     struct d3d_light *light = impl_from_IDirect3DLight(iface);
225c2c66affSColin Finck 
226c2c66affSColin Finck     TRACE("iface %p, light %p.\n", iface, lpLight);
227c2c66affSColin Finck 
228c2c66affSColin Finck     wined3d_mutex_lock();
229c2c66affSColin Finck     memcpy(lpLight, &light->light, lpLight->dwSize);
230c2c66affSColin Finck     wined3d_mutex_unlock();
231c2c66affSColin Finck 
232c2c66affSColin Finck     return DD_OK;
233c2c66affSColin Finck }
234c2c66affSColin Finck 
235c2c66affSColin Finck static const struct IDirect3DLightVtbl d3d_light_vtbl =
236c2c66affSColin Finck {
237c2c66affSColin Finck     /*** IUnknown Methods ***/
238c2c66affSColin Finck     d3d_light_QueryInterface,
239c2c66affSColin Finck     d3d_light_AddRef,
240c2c66affSColin Finck     d3d_light_Release,
241c2c66affSColin Finck     /*** IDirect3DLight Methods ***/
242c2c66affSColin Finck     d3d_light_Initialize,
243c2c66affSColin Finck     d3d_light_SetLight,
244c2c66affSColin Finck     d3d_light_GetLight
245c2c66affSColin Finck };
246c2c66affSColin Finck 
d3d_light_init(struct d3d_light * light,struct ddraw * ddraw)247c2c66affSColin Finck void d3d_light_init(struct d3d_light *light, struct ddraw *ddraw)
248c2c66affSColin Finck {
249c2c66affSColin Finck     light->IDirect3DLight_iface.lpVtbl = &d3d_light_vtbl;
250c2c66affSColin Finck     light->ref = 1;
251c2c66affSColin Finck     light->ddraw = ddraw;
252c2c66affSColin Finck }
253c2c66affSColin Finck 
unsafe_impl_from_IDirect3DLight(IDirect3DLight * iface)254c2c66affSColin Finck struct d3d_light *unsafe_impl_from_IDirect3DLight(IDirect3DLight *iface)
255c2c66affSColin Finck {
256c2c66affSColin Finck     if (!iface)
257c2c66affSColin Finck         return NULL;
258c2c66affSColin Finck     assert(iface->lpVtbl == &d3d_light_vtbl);
259c2c66affSColin Finck 
260c2c66affSColin Finck     return impl_from_IDirect3DLight(iface);
261c2c66affSColin Finck }
262