Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/ddraw_private.h | 6 ++-- dlls/ddraw/light.c | 6 ++-- dlls/ddraw/viewport.c | 66 ++++++++++++++++++++++++-------------- 3 files changed, 49 insertions(+), 29 deletions(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index a5fce2a15e..22910d7cc4 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -66,6 +66,8 @@ struct FvfToDecl | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART \ | WINED3D_LEGACY_CUBEMAP_FILTERING)
+#define DDRAW_MAX_ACTIVE_LIGHTS 8 + enum ddraw_device_state { DDRAW_DEVICE_STATE_OK, @@ -446,7 +448,7 @@ struct d3d_light D3DLIGHT2 light; D3DLIGHT7 light7;
- DWORD dwLightIndex; + DWORD active_light_index;
struct list entry; }; @@ -500,7 +502,7 @@ struct d3d_viewport /* If this viewport is active for one device, put the device here */ struct d3d_device *active_device;
- DWORD num_lights; + DWORD active_lights_count; DWORD map_lights;
enum ddraw_viewport_version version; diff --git a/dlls/ddraw/light.c b/dlls/ddraw/light.c index c6513ffe8a..a86f046b74 100644 --- a/dlls/ddraw/light.c +++ b/dlls/ddraw/light.c @@ -39,7 +39,7 @@ static void light_update(struct d3d_light *light) if (!light->active_viewport || !light->active_viewport->active_device) return; device = light->active_viewport->active_device;
- IDirect3DDevice7_SetLight(&device->IDirect3DDevice7_iface, light->dwLightIndex, &light->light7); + IDirect3DDevice7_SetLight(&device->IDirect3DDevice7_iface, light->active_light_index, &light->light7); }
/***************************************************************************** @@ -61,7 +61,7 @@ void light_activate(struct d3d_light *light)
light_update(light); if (light->light.dwFlags & D3DLIGHT_ACTIVE) - IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->dwLightIndex, TRUE); + IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->active_light_index, TRUE); }
/***************************************************************************** @@ -83,7 +83,7 @@ void light_deactivate(struct d3d_light *light)
device = light->active_viewport->active_device; if (light->light.dwFlags & D3DLIGHT_ACTIVE) - IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->dwLightIndex, FALSE); + IDirect3DDevice7_LightEnable(&device->IDirect3DDevice7_iface, light->active_light_index, FALSE); }
static inline struct d3d_light *impl_from_IDirect3DLight(IDirect3DLight *iface) diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c index daa5ac8d5a..31724402b3 100644 --- a/dlls/ddraw/viewport.c +++ b/dlls/ddraw/viewport.c @@ -122,6 +122,34 @@ void viewport_deactivate(struct d3d_viewport *viewport) } }
+static void viewport_alloc_active_light_index(struct d3d_light *light) +{ + struct d3d_viewport *vp = light->active_viewport; + unsigned int i; + DWORD map; + + TRACE("vp %p, light %p, index %u, active_lights_count %u.\n", + vp, light, light->active_light_index, vp->active_lights_count); + + if (light->active_light_index) + return; + + if (vp->active_lights_count >= DDRAW_MAX_ACTIVE_LIGHTS) + return; + + map = vp->map_lights; + + i = 0; + while (map & 1) + { + map >>= 1; + ++i; + } + light->active_light_index = i + 1; + ++vp->active_lights_count; + vp->map_lights |= 1u << i; +} + /***************************************************************************** * _dump_D3DVIEWPORT, _dump_D3DVIEWPORT2 * @@ -753,23 +781,15 @@ static HRESULT WINAPI d3d_viewport_Clear(IDirect3DViewport3 *iface, * DDERR_INVALIDPARAMS if there are 8 lights or more * *****************************************************************************/ -static HRESULT WINAPI d3d_viewport_AddLight(IDirect3DViewport3 *iface, IDirect3DLight *lpDirect3DLight) +static HRESULT WINAPI d3d_viewport_AddLight(IDirect3DViewport3 *viewport, IDirect3DLight *light) { - struct d3d_viewport *This = impl_from_IDirect3DViewport3(iface); - struct d3d_light *light_impl = unsafe_impl_from_IDirect3DLight(lpDirect3DLight); - DWORD i = 0; - DWORD map = This->map_lights; + struct d3d_light *light_impl = unsafe_impl_from_IDirect3DLight(light); + struct d3d_viewport *vp = impl_from_IDirect3DViewport3(viewport);
- TRACE("iface %p, light %p.\n", iface, lpDirect3DLight); + TRACE("viewport %p, light %p.\n", viewport, light);
wined3d_mutex_lock();
- if (This->num_lights >= 8) - { - wined3d_mutex_unlock(); - return DDERR_INVALIDPARAMS; - } - if (light_impl->active_viewport) { wined3d_mutex_unlock(); @@ -777,22 +797,20 @@ static HRESULT WINAPI d3d_viewport_AddLight(IDirect3DViewport3 *iface, IDirect3D return D3DERR_LIGHTHASVIEWPORT; }
- /* Find a light number and update both light and viewports objects accordingly */ - while (map & 1) + light_impl->active_viewport = vp; + viewport_alloc_active_light_index(light_impl); + if (!light_impl->active_light_index) { - map >>= 1; - ++i; + light_impl->active_viewport = NULL; + wined3d_mutex_unlock(); + return DDERR_INVALIDPARAMS; } - light_impl->dwLightIndex = i; - This->num_lights++; - This->map_lights |= 1<<i;
/* Add the light in the 'linked' chain */ - list_add_head(&This->light_list, &light_impl->entry); - IDirect3DLight_AddRef(lpDirect3DLight); + list_add_head(&vp->light_list, &light_impl->entry); + IDirect3DLight_AddRef(light);
/* Attach the light to the viewport */ - light_impl->active_viewport = This; light_activate(light_impl);
wined3d_mutex_unlock(); @@ -833,8 +851,8 @@ static HRESULT WINAPI d3d_viewport_DeleteLight(IDirect3DViewport3 *iface, IDirec list_remove(&l->entry); l->active_viewport = NULL; IDirect3DLight_Release(lpDirect3DLight); - --viewport->num_lights; - viewport->map_lights &= ~(1 << l->dwLightIndex); + --viewport->active_lights_count; + viewport->map_lights &= ~(1 << l->active_light_index);
wined3d_mutex_unlock();
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/ddraw_private.h | 3 +++ dlls/ddraw/light.c | 15 +++++++++++++-- dlls/ddraw/viewport.c | 29 ++++++++++++++++++----------- 3 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 22910d7cc4..9686b77866 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -662,4 +662,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 a86f046b74..22ebe2057f 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 31724402b3..07fd197e0d 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();
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/light.c | 2 -- dlls/ddraw/viewport.c | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-)
diff --git a/dlls/ddraw/light.c b/dlls/ddraw/light.c index 22ebe2057f..9c624f115b 100644 --- a/dlls/ddraw/light.c +++ b/dlls/ddraw/light.c @@ -62,8 +62,6 @@ void light_activate(struct d3d_light *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); } diff --git a/dlls/ddraw/viewport.c b/dlls/ddraw/viewport.c index 07fd197e0d..e94c4b8da0 100644 --- a/dlls/ddraw/viewport.c +++ b/dlls/ddraw/viewport.c @@ -135,9 +135,25 @@ void viewport_alloc_active_light_index(struct d3d_light *light) return;
if (vp->active_lights_count >= DDRAW_MAX_ACTIVE_LIGHTS) - return; + { + struct d3d_light *l; + + LIST_FOR_EACH_ENTRY(l, &vp->light_list, struct d3d_light, entry) + { + if (l->active_light_index) + { + WARN("Too many active lights, viewport %p, light %p, deactivating %p.\n", vp, light, l); + light_deactivate(l);
+ /* Recycle active lights in a FIFO way. */ + list_remove(&light->entry); + list_add_tail(&vp->light_list, &light->entry); + break; + } + } + } map = vp->map_lights; + assert(vp->active_lights_count < DDRAW_MAX_ACTIVE_LIGHTS && map != ~0u);
i = 0; while (map & 1) @@ -817,7 +833,7 @@ static HRESULT WINAPI d3d_viewport_AddLight(IDirect3DViewport3 *viewport, IDirec light_impl->active_viewport = vp;
/* Add the light in the 'linked' chain */ - list_add_head(&vp->light_list, &light_impl->entry); + list_add_tail(&vp->light_list, &light_impl->entry); IDirect3DLight_AddRef(light);
light_activate(light_impl);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53498
Your paranoid android.
=== debian9 (32 bit report) ===
ddraw: ddraw7.c:2597: Test failed: Expected message 0x46, but didn't receive it. ddraw7.c:2599: Test failed: Expected screen size 1920x1200, got 0x0. ddraw7.c:2604: Test failed: Expected (0,0)-(1920,1200), got (0,0)-(1920,1080).
=== debian9 (32 bit Chinese:China report) ===
ddraw: ddraw1.c:2753: Test failed: Expected message 0x7e, but didn't receive it.
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/tests/ddraw4.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index 42609f201e..3dae48a076 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -4556,6 +4556,7 @@ static void test_specular_lighting(void) {&point_far, TRUE, 0.0f, expected_zero, ARRAY_SIZE(expected_zero)}, };
+ IDirect3DLight *light, *dummy_lights[64]; IDirect3DVertexBuffer *src_vb, *dst_vb; struct vertex *quad, *src_data; D3DVERTEXBUFFERDESC vb_desc; @@ -4564,7 +4565,7 @@ static void test_specular_lighting(void) IDirect3DMaterial3 *material; IDirect3DDevice3 *device; IDirectDrawSurface4 *rt; - IDirect3DLight *light; + D3DLIGHT2 light_desc; IDirect3D3 *d3d; D3DCOLOR color; ULONG refcount; @@ -4635,6 +4636,22 @@ static void test_specular_lighting(void) hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+ memset(&light_desc, 0, sizeof(light_desc)); + light_desc.dwSize = sizeof(light_desc); + light_desc.dltType = D3DLIGHT_DIRECTIONAL; + light_desc.dwFlags = D3DLIGHT_ACTIVE; + U3(light_desc.dvDirection).z = 1.0f; + + for (i = 0; i < ARRAY_SIZE(dummy_lights); ++i) + { + hr = IDirect3D3_CreateLight(d3d, &dummy_lights[i], NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DViewport3_AddLight(viewport, dummy_lights[i]); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DLight_SetLight(dummy_lights[i], (D3DLIGHT *)&light_desc); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + } + hr = IDirect3D3_CreateLight(d3d, &light, NULL); ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); hr = IDirect3DViewport3_AddLight(viewport, light); @@ -4721,6 +4738,9 @@ static void test_specular_lighting(void) destroy_material(material); }
+ for (i = 0; i < ARRAY_SIZE(dummy_lights); ++i) + IDirect3DLight_Release(dummy_lights[i]); + IDirect3DVertexBuffer_Release(dst_vb); IDirect3DVertexBuffer_Release(src_vb);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53499
Your paranoid android.
=== debian9 (32 bit WoW report) ===
ddraw: ddraw7.c:2597: Test failed: Expected message 0x46, but didn't receive it. ddraw7.c:2599: Test failed: Expected screen size 1920x1200, got 0x0. ddraw7.c:2604: Test failed: Expected (0,0)-(1920,1200), got (0,0)-(1920,1080).
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/ddraw_private.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 9686b77866..b08f66564c 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -66,7 +66,7 @@ struct FvfToDecl | WINED3D_LEGACY_UNBOUND_RESOURCE_COLOR | WINED3D_NO_PRIMITIVE_RESTART \ | WINED3D_LEGACY_CUBEMAP_FILTERING)
-#define DDRAW_MAX_ACTIVE_LIGHTS 8 +#define DDRAW_MAX_ACTIVE_LIGHTS 32
enum ddraw_device_state {
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=53496
Your paranoid android.
=== debian9 (64 bit WoW report) ===
ddraw: ddraw1.c:2727: Test failed: Got unexpected hr 0. ddraw1.c:2729: Test failed: Expected message 0x46, but didn't receive it. ddraw1.c:2731: Test failed: Expected screen size 1920x1080, got 0x0. ddraw1.c:2736: Test failed: Expected (0,0)-(1920,1080), got (0,0)-(1920,1200).
On Tue, 11 Jun 2019 at 14:37, Paul Gofman gofmanp@gmail.com wrote:
- i = 0;
- while (map & 1)
- {
map >>= 1;
++i;
- }
This is existing code, but: "i = wined3d_bit_scan(~map);"