Commit 3cc253c5 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Enabling too many lights is silently ignored.

I'm resending this patch because my reply to Henri's concern came too late. Henri noted that I am enabling lights that do not exist. Existing tests show that if no light is assigned to the index, LightEnable creates a light with a set of default parameters, so the tests should be fine. From 9ee4c61805b50886f79e87d744b52f27b7b00b4e Mon Sep 17 00:00:00 2001 From: Stefan Doesinger <stefan@codeweavers.com> Date: Thu, 29 Nov 2007 13:22:47 +0100 Subject: [PATCH] WineD3D: Enabling too many lights is silently ignored This patch adds tests for all d3d versions that show that Windows pretends that enabling more lights than supported succeeds. D3D_OK is returned, and the light is reported as enabled. What is not tested in this patch is the rendering output of this situation, thus the FIXME is still written.
parent 0f39b29d
......@@ -1106,6 +1106,74 @@ cleanup:
if(hwnd) DestroyWindow(hwnd);
}
static void test_lights(void)
{
D3DPRESENT_PARAMETERS d3dpp;
IDirect3DDevice8 *device = NULL;
IDirect3D8 *d3d8;
HWND hwnd;
HRESULT hr;
unsigned int i;
BOOL enabled;
D3DCAPS8 caps;
D3DDISPLAYMODE d3ddm;
d3d8 = pDirect3DCreate8( D3D_SDK_VERSION );
ok(d3d8 != NULL, "Failed to create IDirect3D8 object\n");
hwnd = CreateWindow( "static", "d3d8_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
ok(hwnd != NULL, "Failed to create window\n");
if (!d3d8 || !hwnd) goto cleanup;
IDirect3D8_GetAdapterDisplayMode( d3d8, D3DADAPTER_DEFAULT, &d3ddm );
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferWidth = 800;
d3dpp.BackBufferHeight = 600;
d3dpp.BackBufferFormat = d3ddm.Format;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
hr = IDirect3D8_CreateDevice( d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL /* no NULLREF here */, hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &d3dpp, &device );
ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D8_CreateDevice failed with %s\n", DXGetErrorString8(hr));
if(!device)
{
skip("Failed to create a d3d device\n");
goto cleanup;
}
memset(&caps, 0, sizeof(caps));
hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps failed with %s\n", DXGetErrorString8(hr));
for(i = 1; i <= caps.MaxActiveLights; i++) {
hr = IDirect3DDevice8_LightEnable(device, i, TRUE);
ok(hr == D3D_OK, "Enabling light %u failed with %s\n", i, DXGetErrorString8(hr));
hr = IDirect3DDevice8_GetLightEnable(device, i, &enabled);
ok(hr == D3D_OK, "GetLightEnable on light %u failed with %s\n", i, DXGetErrorString8(hr));
ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
}
/* TODO: Test the rendering results in this situation */
hr = IDirect3DDevice8_LightEnable(device, i + 1, TRUE);
ok(hr == D3D_OK, "Enabling one light more than supported returned %s\n", DXGetErrorString8(hr));
hr = IDirect3DDevice8_GetLightEnable(device, i + 1, &enabled);
ok(hr == D3D_OK, "GetLightEnable on light %u failed with %s\n", i + 1, DXGetErrorString8(hr));
ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
hr = IDirect3DDevice8_LightEnable(device, i + 1, FALSE);
ok(hr == D3D_OK, "Disabling the additional returned %s\n", DXGetErrorString8(hr));
for(i = 1; i <= caps.MaxActiveLights; i++) {
hr = IDirect3DDevice8_LightEnable(device, i, FALSE);
ok(hr == D3D_OK, "Disabling light %u failed with %s\n", i, DXGetErrorString8(hr));
}
cleanup:
if(device) IDirect3DDevice8_Release(device);
if(d3d8) IDirect3D8_Release(d3d8);
}
START_TEST(device)
{
HMODULE d3d8_handle = LoadLibraryA( "d3d8.dll" );
......@@ -1129,5 +1197,6 @@ START_TEST(device)
test_scene();
test_shader();
test_limits();
test_lights();
}
}
......@@ -1593,6 +1593,68 @@ static void test_vertex_buffer_alignment(void)
if(d3d9) IDirect3D9_Release(d3d9);
}
static void test_lights(void)
{
D3DPRESENT_PARAMETERS present_parameters;
IDirect3DDevice9 *device = NULL;
IDirect3D9 *d3d9;
HWND hwnd;
HRESULT hr;
unsigned int i;
BOOL enabled;
D3DCAPS9 caps;
d3d9 = pDirect3DCreate9( D3D_SDK_VERSION );
ok(d3d9 != NULL, "Failed to create IDirect3D9 object\n");
hwnd = CreateWindow( "static", "d3d9_test", WS_OVERLAPPEDWINDOW, 100, 100, 160, 160, NULL, NULL, NULL, NULL );
ok(hwnd != NULL, "Failed to create window\n");
if (!d3d9 || !hwnd) goto cleanup;
ZeroMemory(&present_parameters, sizeof(present_parameters));
present_parameters.Windowed = TRUE;
present_parameters.hDeviceWindow = hwnd;
present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
hr = IDirect3D9_CreateDevice( d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &present_parameters, &device );
ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D9_CreateDevice failed with %s\n", DXGetErrorString9(hr));
if(!device)
{
skip("Failed to create a d3d device\n");
goto cleanup;
}
memset(&caps, 0, sizeof(caps));
hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %s\n", DXGetErrorString9(hr));
for(i = 1; i <= caps.MaxActiveLights; i++) {
hr = IDirect3DDevice9_LightEnable(device, i, TRUE);
ok(hr == D3D_OK, "Enabling light %u failed with %s\n", i, DXGetErrorString9(hr));
hr = IDirect3DDevice9_GetLightEnable(device, i, &enabled);
ok(hr == D3D_OK, "GetLightEnable on light %u failed with %s\n", i, DXGetErrorString9(hr));
ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
}
/* TODO: Test the rendering results in this situation */
hr = IDirect3DDevice9_LightEnable(device, i + 1, TRUE);
ok(hr == D3D_OK, "Enabling one light more than supported returned %s\n", DXGetErrorString9(hr));
hr = IDirect3DDevice9_GetLightEnable(device, i + 1, &enabled);
ok(hr == D3D_OK, "GetLightEnable on light %u failed with %s\n", i + 1, DXGetErrorString9(hr));
ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
hr = IDirect3DDevice9_LightEnable(device, i + 1, FALSE);
ok(hr == D3D_OK, "Disabling the additional returned %s\n", DXGetErrorString9(hr));
for(i = 1; i <= caps.MaxActiveLights; i++) {
hr = IDirect3DDevice9_LightEnable(device, i, FALSE);
ok(hr == D3D_OK, "Disabling light %u failed with %s\n", i, DXGetErrorString9(hr));
}
cleanup:
if(device) IDirect3DDevice9_Release(device);
if(d3d9) IDirect3D9_Release(d3d9);
}
START_TEST(device)
{
HMODULE d3d9_handle = LoadLibraryA( "d3d9.dll" );
......@@ -1618,5 +1680,6 @@ START_TEST(device)
test_draw_indexed();
test_null_stream();
test_vertex_buffer_alignment();
test_lights();
}
}
......@@ -180,6 +180,9 @@ static void LightTest(void)
float one = 1.0f;
float zero= 0.0f;
D3DMATERIAL7 mat;
BOOL enabled;
unsigned int i;
D3DDEVICEDESC7 caps;
/* Set a few lights with funky indices. */
memset(&light, 0, sizeof(light));
......@@ -343,6 +346,32 @@ static void LightTest(void)
rc = IDirect3DDevice7_GetMaterial(lpD3DDevice, &mat);
ok(rc == D3D_OK, "IDirect3DDevice7_GetMaterial returned: %x\n", rc);
ok(U4(mat).power == -1, "Returned power is %f\n", U4(mat).power);
memset(&caps, 0, sizeof(caps));
rc = IDirect3DDevice7_GetCaps(lpD3DDevice, &caps);
ok(rc == D3D_OK, "IDirect3DDevice7_GetCaps failed with %x\n", rc);
for(i = 1; i <= caps.dwMaxActiveLights; i++) {
rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, TRUE);
ok(rc == D3D_OK, "Enabling light %u failed with %x\n", i, rc);
rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i, &enabled);
ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i, rc);
ok(enabled, "Light %d is %s\n", i, enabled ? "enabled" : "disabled");
}
/* TODO: Test the rendering results in this situation */
rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, TRUE);
ok(rc == D3D_OK, "Enabling one light more than supported returned %x\n", rc);
rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, i + 1, &enabled);
ok(rc == D3D_OK, "GetLightEnable on light %u failed with %x\n", i + 1, rc);
ok(enabled, "Light %d is %s\n", i + 1, enabled ? "enabled" : "disabled");
rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i + 1, FALSE);
ok(rc == D3D_OK, "Disabling the additional returned %x\n", rc);
for(i = 1; i <= caps.dwMaxActiveLights; i++) {
rc = IDirect3DDevice7_LightEnable(lpD3DDevice, i, FALSE);
ok(rc == D3D_OK, "Disabling light %u failed with %x\n", i, rc);
}
}
static void ProcessVerticesTest(void)
......
......@@ -2845,7 +2845,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D
} else {
TRACE("Light already disabled, nothing to do\n");
}
lightInfo->enabled = FALSE;
} else {
lightInfo->enabled = TRUE;
if (lightInfo->glIndex != -1) {
/* nop */
TRACE("Nothing to do as light was enabled\n");
......@@ -2860,8 +2862,15 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, D
}
}
if(lightInfo->glIndex == -1) {
ERR("Too many concurrently active lights\n");
return WINED3DERR_INVALIDCALL;
/* Our tests show that Windows returns D3D_OK in this situation, even with
* D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE devices. This
* is consistent among ddraw, d3d8 and d3d9. GetLightEnable returns TRUE
* as well for those lights.
*
* TODO: Test how this affects rendering
*/
FIXME("Too many concurrently active lights\n");
return WINED3D_OK;
}
/* i == lightInfo->glIndex */
......@@ -2893,7 +2902,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, D
return WINED3DERR_INVALIDCALL;
}
/* true is 128 according to SetLightEnable */
*pEnable = lightInfo->glIndex != -1 ? 128 : 0;
*pEnable = lightInfo->enabled ? 128 : 0;
return WINED3D_OK;
}
......
......@@ -549,6 +549,7 @@ struct PLIGHTINFOEL {
LONG glIndex;
BOOL changed;
BOOL enabledChanged;
BOOL enabled;
/* Converted parms to speed up swapping lights */
float lightPosn[4];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment