H. Verbeet wrote:
On 10/30/05, Christian Costa titan.costa@wanadoo.fr wrote:
IIRC, a patch fixing this problem was commited about 2 or 3 months ago.
This one? http://cvs.winehq.org/patch.py?id=18002
It doesn't touch CreateLight. The crash happens because of this check in GL_IDirect3DImpl_3_2T_1T_CreateLight:
if (fl == MAX_LIGHTS) { return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */ }
The application is sloppy for not checking the result of course, but on Windows the call never fails, at least not for creating more lights than the hardware supports.
Could you try this patch ?
? dlls/ddraw/.d3d_private.h.swp ? dlls/ddraw/.device_opengl.c.swp ? dlls/ddraw/.direct3d_opengl.c.swo ? dlls/ddraw/.direct3d_opengl.c.swp ? dlls/ddraw/.light.c.swp ? dlls/ddraw/.opengl_private.h.swp ? dlls/ddraw/device_opengl.c.fog ? dlls/ddraw/device_opengl.c.work ? dlls/ddraw/lights.diff ? dlls/ddraw/t.txt Index: dlls/ddraw/direct3d_opengl.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/direct3d_opengl.c,v retrieving revision 1.2 diff -u -r1.2 direct3d_opengl.c --- dlls/ddraw/direct3d_opengl.c 26 Jul 2005 20:10:51 -0000 1.2 +++ dlls/ddraw/direct3d_opengl.c 30 Oct 2005 12:10:01 -0000 @@ -98,23 +98,31 @@ { ICOM_THIS_FROM(IDirectDrawImpl, IDirect3D3, iface); IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This->d3d_private; - int fl; + DWORD light_index; IDirect3DLightImpl *d3dlimpl; HRESULT ret_value;
TRACE("(%p/%p)->(%p,%p)\n", This, iface, lplpDirect3DLight, pUnkOuter); - for (fl = 0; fl < MAX_LIGHTS; fl++) { - if ((glThis->free_lights & (0x01 << fl)) != 0) { - glThis->free_lights &= ~(0x01 << fl); + for (light_index = 0; light_index < glThis->max_lights; light_index++) { + if (!glThis->used_lights[light_index]) break; - } } - if (fl == MAX_LIGHTS) { - return DDERR_INVALIDPARAMS; /* No way to say 'max lights reached' ... */ + if (light_index == glThis->max_lights) { + int new_max_lights = glThis->max_lights ? 2 * glThis->max_lights : 1; + BOOL *new_used_lights = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_max_lights * sizeof(BOOL)); + if (!new_used_lights) + return E_OUTOFMEMORY; + CopyMemory(new_used_lights, glThis->used_lights, glThis->max_lights); + HeapFree(GetProcessHeap(), 0, glThis->used_lights); + glThis->max_lights = new_max_lights; + glThis->used_lights = new_used_lights; } - ret_value = d3dlight_create(&d3dlimpl, This, GL_LIGHT0 + fl); + ret_value = d3dlight_create(&d3dlimpl, This, light_index); *lplpDirect3DLight = ICOM_INTERFACE(d3dlimpl, IDirect3DLight);
+ if (ret_value == D3D_OK) + glThis->used_lights[light_index] = TRUE; + return ret_value; }
@@ -306,10 +314,10 @@ return res; }
-static void light_released(IDirectDrawImpl *This, GLenum light_num) +static void light_released(IDirectDrawImpl *This, DWORD light_index) { IDirect3DGLImpl *glThis = (IDirect3DGLImpl *) This->d3d_private; - glThis->free_lights |= (light_num - GL_LIGHT0); + glThis->used_lights[light_index] = FALSE; }
#if !defined(__STRICT_ANSI__) && defined(__GNUC__) @@ -453,7 +461,6 @@ ICOM_INIT_INTERFACE(This, IDirect3D3, VTABLE_IDirect3D3); ICOM_INIT_INTERFACE(This, IDirect3D7, VTABLE_IDirect3D7);
- globject->free_lights = (0x01 << MAX_LIGHTS) - 1; /* There are, in total, 8 lights in OpenGL */ globject->light_released = light_released;
This->d3d_private = globject; Index: dlls/ddraw/light.c =================================================================== RCS file: /home/wine/wine/dlls/ddraw/light.c,v retrieving revision 1.2 diff -u -r1.2 light.c --- dlls/ddraw/light.c 26 Jul 2005 20:10:51 -0000 1.2 +++ dlls/ddraw/light.c 30 Oct 2005 12:10:01 -0000 @@ -158,39 +158,43 @@
static void update(IDirect3DLightImpl* This) { IDirect3DDeviceImpl* device; - if (!This->active_viewport||!This->active_viewport->active_device) + if (!This->active_viewport || !This->active_viewport->active_device) return; device = This->active_viewport->active_device; - IDirect3DDevice7_SetLight(ICOM_INTERFACE(device,IDirect3DDevice7),This->dwLightIndex,&(This->light7)); + IDirect3DDevice7_SetLight(ICOM_INTERFACE(device,IDirect3DDevice7), This->dwLightIndex, &(This->light7)); }
static void activate(IDirect3DLightImpl* This) { IDirect3DLightGLImpl *glThis = (IDirect3DLightGLImpl *) This; + IDirect3DDeviceImpl* device; + if (!This->active_viewport || !This->active_viewport->active_device) + return; + device = This->active_viewport->active_device;
TRACE("(%p)\n", This);
- ENTER_GL(); update(This); /* If was not active, activate it */ if ((glThis->parent.light.dwFlags & D3DLIGHT_ACTIVE) == 0) { - glEnable(glThis->light_num); + IDirect3DDevice7_LightEnable(ICOM_INTERFACE(device,IDirect3DDevice7), glThis->light_index, TRUE); glThis->parent.light.dwFlags |= D3DLIGHT_ACTIVE; } - LEAVE_GL(); }
static void desactivate(IDirect3DLightImpl* This) { IDirect3DLightGLImpl *glThis = (IDirect3DLightGLImpl *) This; - + IDirect3DDeviceImpl* device; + if (!This->active_viewport || !This->active_viewport->active_device) + return; + device = This->active_viewport->active_device; + TRACE("(%p)\n", This);
- ENTER_GL(); /* If was not active, activate it */ if ((glThis->parent.light.dwFlags & D3DLIGHT_ACTIVE) != 0) { - glDisable(glThis->light_num); + IDirect3DDevice7_LightEnable(ICOM_INTERFACE(device,IDirect3DDevice7), glThis->light_index, FALSE); glThis->parent.light.dwFlags &= ~D3DLIGHT_ACTIVE; } - LEAVE_GL(); }
ULONG WINAPI @@ -203,7 +207,7 @@ TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, ref + 1);
if (!ref) { - ((IDirect3DGLImpl *) This->d3d->d3d_private)->light_released(This->d3d, glThis->light_num); + ((IDirect3DGLImpl *) This->d3d->d3d_private)->light_released(This->d3d, glThis->light_index); HeapFree(GetProcessHeap(), 0, This); return 0; } @@ -233,7 +237,7 @@
-HRESULT d3dlight_create(IDirect3DLightImpl **obj, IDirectDrawImpl *d3d, GLenum light_num) +HRESULT d3dlight_create(IDirect3DLightImpl **obj, IDirectDrawImpl *d3d, DWORD light_index) { IDirect3DLightImpl *object; IDirect3DLightGLImpl *gl_object; @@ -249,7 +253,7 @@ object->desactivate = desactivate; object->update = update; object->active_viewport = NULL; - gl_object->light_num = light_num; + gl_object->light_index = light_index;
ICOM_INIT_INTERFACE(object, IDirect3DLight, VTABLE_IDirect3DLight);
Index: dlls/ddraw/opengl_private.h =================================================================== RCS file: /home/wine/wine/dlls/ddraw/opengl_private.h,v retrieving revision 1.2 diff -u -r1.2 opengl_private.h --- dlls/ddraw/opengl_private.h 12 Jun 2005 10:43:11 -0000 1.2 +++ dlls/ddraw/opengl_private.h 30 Oct 2005 12:10:02 -0000 @@ -48,14 +48,15 @@ /* This structure is used for the 'd3d_private' field of the IDirectDraw structure */ typedef struct IDirect3DGLImpl { - DWORD free_lights; - void (*light_released)(IDirectDrawImpl *, GLenum light_num); + BOOL *used_lights; + int max_lights; + void (*light_released)(IDirectDrawImpl *, DWORD light_index); } IDirect3DGLImpl;
typedef struct IDirect3DLightGLImpl { struct IDirect3DLightImpl parent; - GLenum light_num; + DWORD light_index; } IDirect3DLightGLImpl;
/* This structure is used for the 'private' field of the IDirectDrawSurfaceImpl structure */ @@ -185,7 +186,7 @@ /* All non-static functions 'exported' by various sub-objects */ extern HRESULT direct3d_create(IDirectDrawImpl *This); extern HRESULT d3dtexture_create(IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surf, BOOLEAN at_creation, IDirectDrawSurfaceImpl *main_surf); -extern HRESULT d3dlight_create(IDirect3DLightImpl **obj, IDirectDrawImpl *d3d, GLenum light_num); +extern HRESULT d3dlight_create(IDirect3DLightImpl **obj, IDirectDrawImpl *d3d, DWORD light_index); extern HRESULT d3dexecutebuffer_create(IDirect3DExecuteBufferImpl **obj, IDirectDrawImpl *d3d, IDirect3DDeviceImpl *d3ddev, LPD3DEXECUTEBUFFERDESC lpDesc); extern HRESULT d3dmaterial_create(IDirect3DMaterialImpl **obj, IDirectDrawImpl *d3d); extern HRESULT d3dviewport_create(IDirect3DViewportImpl **obj, IDirectDrawImpl *d3d);