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