diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 7a1d357e641..e7a9c1dfa69 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -661,4 +661,7 @@ struct member_info HRESULT hr_ddraw_from_wined3d(HRESULT hr) DECLSPEC_HIDDEN; +void viewport_alloc_active_light_index(struct d3d_light *light) DECLSPEC_HIDDEN; +void viewport_free_active_light_index(struct d3d_light *light) DECLSPEC_HIDDEN; + #endif diff --git a/dlls/ddraw/light.c b/dlls/ddraw/light.c index a86f046b741..22ebe2057f6 100644 --- a/dlls/ddraw/light.c +++ b/dlls/ddraw/light.c @@ -59,9 +59,14 @@ void light_activate(struct d3d_light *light) return; device = light->active_viewport->active_device; - light_update(light); if (light->light.dwFlags & D3DLIGHT_ACTIVE) + { + viewport_alloc_active_light_index(light); + if (!light->active_light_index) + return; + light_update(light); IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->active_light_index, TRUE); + } } /***************************************************************************** @@ -79,11 +84,17 @@ void light_deactivate(struct d3d_light *light) if (!light->active_viewport || !light->active_viewport->active_device || light->active_viewport->active_device->current_viewport != light->active_viewport) + { + assert(!light->active_light_index); return; + } device = light->active_viewport->active_device; - if (light->light.dwFlags & D3DLIGHT_ACTIVE) + if (light->active_light_index) + { IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->active_light_index, FALSE); + viewport_free_active_light_index(light); + } } static inline struct d3d_light *impl_from_IDirect3DLight(IDirect3DLight *iface) diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c index 31724402b36..07fd197e0d0 100644 --- a/dlls/ddraw/viewport.c +++ b/dlls/ddraw/viewport.c @@ -122,7 +122,7 @@ void viewport_deactivate(struct d3d_viewport *viewport) } } -static void viewport_alloc_active_light_index(struct d3d_light *light) +void viewport_alloc_active_light_index(struct d3d_light *light) { struct d3d_viewport *vp = light->active_viewport; unsigned int i; @@ -150,6 +150,23 @@ static void viewport_alloc_active_light_index(struct d3d_light *light) vp->map_lights |= 1u << i; } +void viewport_free_active_light_index(struct d3d_light *light) +{ + struct d3d_viewport *vp = light->active_viewport; + + TRACE("vp %p, light %p, index %u, active_lights_count %u, map_lights %#x.\n", + vp, light, light->active_light_index, vp->active_lights_count, vp->map_lights); + + if (!light->active_light_index) + return; + + assert(vp->map_lights & (1u << (light->active_light_index - 1))); + + --vp->active_lights_count; + vp->map_lights &= ~(1u << (light->active_light_index - 1)); + light->active_light_index = 0; +} + /***************************************************************************** * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2 * @@ -798,19 +815,11 @@ static HRESULT WINAPI d3d_viewport_AddLight(IDirect3DViewport3 *viewport, IDirec } light_impl->active_viewport = vp; - viewport_alloc_active_light_index(light_impl); - if (!light_impl->active_light_index) - { - light_impl->active_viewport = NULL; - wined3d_mutex_unlock(); - return DDERR_INVALIDPARAMS; - } /* Add the light in the 'linked' chain */ list_add_head(&vp->light_list, &light_impl->entry); IDirect3DLight_AddRef(light); - /* Attach the light to the viewport */ light_activate(light_impl); wined3d_mutex_unlock(); @@ -851,8 +860,6 @@ static HRESULT WINAPI d3d_viewport_DeleteLight(IDirect3DViewport3 *iface, IDirec list_remove(&l->entry); l->active_viewport = NULL; IDirect3DLight_Release(lpDirect3DLight); - --viewport->active_lights_count; - viewport->map_lights &= ~(1 << l->active_light_index); wined3d_mutex_unlock();