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.
This commit is contained in:
Stefan Dösinger 2007-11-29 13:22:47 +01:00 committed by Alexandre Julliard
parent 0f39b29da0
commit 3cc253c557
5 changed files with 174 additions and 3 deletions

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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)

View File

@ -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;
}

View File

@ -549,6 +549,7 @@ struct PLIGHTINFOEL {
LONG glIndex;
BOOL changed;
BOOL enabledChanged;
BOOL enabled;
/* Converted parms to speed up swapping lights */
float lightPosn[4];