Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/wined3d/device.c | 127 +++++++++++++++++++++++++-------- dlls/wined3d/wined3d_private.h | 13 ++++ 2 files changed, 111 insertions(+), 29 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 0f9485aa6a..3d4914eb6a 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -58,16 +58,21 @@ struct lights_settings struct wined3d_color ambient_light; struct wined3d_matrix modelview_matrix; struct wined3d_matrix_3x3 normal_matrix; + struct wined3d_vec4 position_transformed; + + float fog_start, fog_end, fog_density;
uint32_t point_light_count : 8; uint32_t spot_light_count : 8; uint32_t directional_light_count : 8; uint32_t parallel_point_light_count : 8; - + uint32_t lighting : 1; uint32_t legacy_lighting : 1; uint32_t normalise : 1; uint32_t localviewer : 1; - uint32_t padding : 29; + uint32_t fog_coord_mode : 2; + uint32_t fog_mode : 2; + uint32_t padding : 24; };
/* Define the default light parameters as specified by MSDN. */ @@ -3269,7 +3274,7 @@ static void wined3d_color_rgb_mul_add(struct wined3d_color *dst, const struct wi }
static void init_transformed_lights(struct lights_settings *ls, - const struct wined3d_state *state, BOOL legacy_lighting) + const struct wined3d_state *state, BOOL legacy_lighting, BOOL compute_lighting) { const struct wined3d_light_info *lights[WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS]; const struct wined3d_light_info *light_info; @@ -3280,15 +3285,30 @@ static void init_transformed_lights(struct lights_settings *ls,
memset(ls, 0, sizeof(*ls));
- wined3d_color_from_d3dcolor(&ls->ambient_light, state->render_states[WINED3D_RS_AMBIENT]); - ls->legacy_lighting = !!legacy_lighting; - ls->normalise = !!state->render_states[WINED3D_RS_NORMALIZENORMALS]; - ls->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER]; + ls->lighting = !!compute_lighting; + ls->fog_mode = state->render_states[WINED3D_RS_FOGVERTEXMODE]; + ls->fog_coord_mode = state->render_states[WINED3D_RS_RANGEFOGENABLE] + ? WINED3D_FFP_VS_FOG_RANGE : WINED3D_FFP_VS_FOG_DEPTH; + ls->fog_start = wined3d_get_float_state(state, WINED3D_RS_FOGSTART); + ls->fog_end = wined3d_get_float_state(state, WINED3D_RS_FOGEND); + ls->fog_density = wined3d_get_float_state(state, WINED3D_RS_FOGDENSITY); + + if (ls->fog_mode == WINED3D_FOG_NONE && !compute_lighting) + return;
multiply_matrix(&ls->modelview_matrix, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(0)]); + + if (!compute_lighting) + return; + compute_normal_matrix(&ls->normal_matrix._11, legacy_lighting, &ls->modelview_matrix);
+ wined3d_color_from_d3dcolor(&ls->ambient_light, state->render_states[WINED3D_RS_AMBIENT]); + ls->legacy_lighting = !!legacy_lighting; + ls->normalise = !!state->render_states[WINED3D_RS_NORMALIZENORMALS]; + ls->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER]; + for (i = 0, index = 0; i < LIGHTMAP_SIZE && index < ARRAY_SIZE(lights); ++i) { LIST_FOR_EACH_ENTRY(light_info, &state->light_state.light_map[i], struct wined3d_light_info, entry) @@ -3430,21 +3450,28 @@ static void update_light_diffuse_specular(struct wined3d_color *diffuse, struct wined3d_color_rgb_mul_add(specular, &light->specular, att * powf(t, material_shininess)); }
+static void light_set_vertex_data(struct lights_settings *ls, + const struct wined3d_vec4 *position) +{ + if (ls->fog_mode == WINED3D_FOG_NONE && !ls->lighting) + return; + + wined3d_vec4_transform(&ls->position_transformed, position, &ls->modelview_matrix); + wined3d_vec3_scale((struct wined3d_vec3 *)&ls->position_transformed, 1.0f / ls->position_transformed.w); +} + static void compute_light(struct wined3d_color *ambient, struct wined3d_color *diffuse, - struct wined3d_color *specular, const struct lights_settings *ls, const struct wined3d_vec3 *normal, - const struct wined3d_vec4 *position, float material_shininess) + struct wined3d_color *specular, struct lights_settings *ls, const struct wined3d_vec3 *normal, + float material_shininess) { struct wined3d_vec3 position_transformed_normalised; struct wined3d_vec3 normal_transformed = {0.0f}; - struct wined3d_vec4 position_transformed; const struct light_transformed *light; struct wined3d_vec3 dir, dst; unsigned int i, index; float att;
- wined3d_vec4_transform(&position_transformed, position, &ls->modelview_matrix); - wined3d_vec3_scale((struct wined3d_vec3 *)&position_transformed, 1.0f / position_transformed.w); - position_transformed_normalised = *(const struct wined3d_vec3 *)&position_transformed; + position_transformed_normalised = *(const struct wined3d_vec3 *)&ls->position_transformed; wined3d_vec3_normalise(&position_transformed_normalised);
if (normal) @@ -3472,9 +3499,9 @@ static void compute_light(struct wined3d_color *ambient, struct wined3d_color *d for (i = 0; i < ls->point_light_count; ++i, ++index) { light = &ls->lights[index]; - dir.x = light->position.x - position_transformed.x; - dir.y = light->position.y - position_transformed.y; - dir.z = light->position.z - position_transformed.z; + dir.x = light->position.x - ls->position_transformed.x; + dir.y = light->position.y - ls->position_transformed.y; + dir.z = light->position.z - ls->position_transformed.z;
dst.z = wined3d_vec3_dot(&dir, &dir); dst.y = sqrtf(dst.z); @@ -3510,9 +3537,9 @@ static void compute_light(struct wined3d_color *ambient, struct wined3d_color *d
light = &ls->lights[index];
- dir.x = light->position.x - position_transformed.x; - dir.y = light->position.y - position_transformed.y; - dir.z = light->position.z - position_transformed.z; + dir.x = light->position.x - ls->position_transformed.x; + dir.y = light->position.y - ls->position_transformed.y; + dir.z = light->position.z - ls->position_transformed.z;
dst.z = wined3d_vec3_dot(&dir, &dir); dst.y = sqrtf(dst.z); @@ -3563,6 +3590,46 @@ static void compute_light(struct wined3d_color *ambient, struct wined3d_color *d } }
+static float wined3d_calculate_fog_factor(float fog_coord, const struct lights_settings *ls) +{ + switch (ls->fog_mode) + { + case WINED3D_FOG_NONE: + return fog_coord; + case WINED3D_FOG_LINEAR: + return (ls->fog_end - fog_coord) / (ls->fog_end - ls->fog_start); + case WINED3D_FOG_EXP: + return expf(-fog_coord * ls->fog_density); + case WINED3D_FOG_EXP2: + return expf(-fog_coord * fog_coord * ls->fog_density * ls->fog_density); + } +} + +static void update_fog_factor(float *fog_factor, struct lights_settings *ls) +{ + float fog_coord; + + if (ls->fog_mode == WINED3D_FOG_NONE) + return; + + switch (ls->fog_coord_mode) + { + case WINED3D_FFP_VS_FOG_RANGE: + fog_coord = sqrtf(wined3d_vec3_dot((const struct wined3d_vec3 *)&ls->position_transformed, + (const struct wined3d_vec3 *)&ls->position_transformed)); + break; + + case WINED3D_FFP_VS_FOG_DEPTH: + fog_coord = fabsf(ls->position_transformed.z); + break; + + default: + ERR("Unhandled fog coordinate mode %#x.\n", ls->fog_coord_mode); + return; + } + *fog_factor = wined3d_calculate_fog_factor(fog_coord, ls); +} + /* Context activation is done by the caller. */ #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size) static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount, @@ -3661,17 +3728,24 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO output_colour_format = wined3d_get_format(device->adapter, WINED3DFMT_B8G8R8A8_UNORM, 0); material_specular_state_colour = state->render_states[WINED3D_RS_SPECULARENABLE] ? &state->material.specular : &black; - if (lighting) - init_transformed_lights(&ls, state, - device->adapter->d3d_info.wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING); + init_transformed_lights(&ls, state, device->adapter->d3d_info.wined3d_creation_flags + & WINED3D_LEGACY_FFP_LIGHTING, lighting);
for (i = 0; i < dwCount; ++i) { const struct wined3d_stream_info_element *position_element = &stream_info->elements[WINED3D_FFP_POSITION]; const float *p = (const float *)&position_element->data.addr[i * position_element->stride]; struct wined3d_color ambient, diffuse, specular; + struct wined3d_vec4 position; unsigned int tex_index;
+ position.x = p[0]; + position.y = p[1]; + position.z = p[2]; + position.w = 1.0f; + + light_set_vertex_data(&ls, &position); + if ( ((dst_fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) || ((dst_fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) { /* The position first */ @@ -3783,14 +3857,8 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO if (lighting) { const struct wined3d_stream_info_element *element; - struct wined3d_vec4 position; struct wined3d_vec3 *normal;
- position.x = p[0]; - position.y = p[1]; - position.z = p[2]; - position.w = 1.0f; - if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL)) { element = &stream_info->elements[WINED3D_FFP_NORMAL]; @@ -3800,7 +3868,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO { normal = NULL; } - compute_light(&ambient, &diffuse, &specular, &ls, normal, &position, + compute_light(&ambient, &diffuse, &specular, &ls, normal, state->render_states[WINED3D_RS_SPECULARENABLE] ? state->material.power : 0.0f); }
@@ -3853,6 +3921,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO { specular_colour = material_specular; } + update_fog_factor(&specular_colour.a, &ls); wined3d_color_clamp(&specular_colour, &specular_colour, 0.0f, 1.0f); *((DWORD *)dest_ptr) = wined3d_format_convert_from_float(output_colour_format, &specular_colour); dest_ptr += sizeof(DWORD); diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 6dcb0693c5..68ef9e13dd 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4945,6 +4945,19 @@ static inline void context_release(struct wined3d_context *context) context->device->adapter->adapter_ops->adapter_release_context(context); }
+static inline float wined3d_get_float_state(const struct wined3d_state *state, enum wined3d_render_state rs) +{ + union + { + DWORD d; + float f; + } + tmpvalue; + + tmpvalue.d = state->render_states[rs]; + return tmpvalue.f; +} + /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */ #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/ddraw/tests/ddraw7.c | 184 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+)
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index ce741253ae..5641a8fc18 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -9513,6 +9513,189 @@ static void test_fog_interpolation(void) DestroyWindow(window); }
+static void test_fog_process_vertices(void) +{ + static D3DMATRIX view_matrix = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + static D3DMATRIX model_matrix = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.75f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + static D3DMATRIX identity_matrix = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + static D3DLIGHT7 directional_light = + { + D3DLIGHT_DIRECTIONAL, + {{0.0f}, {0.0f}, {0.0f}, {0.0f}}, + {{1.0f}, {1.0f}, {1.0f}, {0.0f}}, + {{0.0f}, {0.0f}, {0.0f}, {0.0f}}, + {{0.0f}, {0.0f}, {0.0f}}, + {{0.0f}, {0.0f}, {1.0f}}, + }; + + struct vertex + { + struct vec3 position; + struct vec3 normal; + }; + static const struct + { + struct vertex vertex; + D3DFOGMODE fog_vertex_mode, fog_table_mode; + BOOL range_fog; + D3DCOLOR expected_color, expected_broken; + } + tests[] = + { + /* Some drivers ignore ranged fog state without an obvious reason, even with D3DPRASTERCAPS_FOGRANGE + * set, while some others (including WARP driver on Windows 10) favour it. + * Vertex fog result does not depend on table fog settings. */ + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, FALSE, 0x8000ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_LINEAR, FALSE, 0x8000ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, FALSE, 0xaf00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, FALSE, 0xde00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, FALSE, 0x9f00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_LINEAR, FALSE, 0x9f00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_NONE, D3DFOG_NONE, TRUE, 0x8000ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_NONE, TRUE, 0x8800ff00, 0xaf00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP2, D3DFOG_NONE, TRUE, 0xad00ff00, 0xde00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_NONE, TRUE, 0x6000ff00, 0x9f00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_LINEAR, D3DFOG_EXP, TRUE, 0x6000ff00, 0x9f00ff00}, + {{{0.5f, 0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}}, D3DFOG_EXP, D3DFOG_LINEAR, TRUE, 0x8800ff00, 0xaf00ff00}, + }; + + struct + { + struct vec4 position; + D3DCOLOR diffuse, specular; + } + *dst_data; + + IDirect3DVertexBuffer7 *src_vb, *dst_vb; + D3DVERTEXBUFFERDESC vb_desc; + IDirect3DDevice7 *device; + struct vertex *src_data; + D3DMATERIAL7 material; + IDirect3D7 *d3d; + ULONG refcount; + unsigned int i; + HWND window; + HRESULT hr; + + window = create_window(); + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + hr = IDirect3DDevice7_GetDirect3D(device, &d3d); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &model_matrix); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &view_matrix); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &identity_matrix); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + memset(&vb_desc, 0, sizeof(vb_desc)); + vb_desc.dwSize = sizeof(vb_desc); + vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL; + vb_desc.dwNumVertices = 1; + hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &src_vb, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + memset(&vb_desc, 0, sizeof(vb_desc)); + vb_desc.dwSize = sizeof(vb_desc); + vb_desc.dwFVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR; + vb_desc.dwNumVertices = 1; + hr = IDirect3D7_CreateVertexBuffer(d3d, &vb_desc, &dst_vb, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice7_LightEnable(device, 0, TRUE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DDevice7_SetLight(device, 0, &directional_light); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + memset(&material, 0, sizeof(material)); + U1(U2(material).specular).r = 0.0f; + U2(U2(material).specular).g = 1.0f; + U3(U2(material).specular).b = 0.0f; + U4(U2(material).specular).a = 0.5f; + U4(material).power = 5.0f; + hr = IDirect3DDevice7_SetMaterial(device, &material); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, + tests[i].fog_vertex_mode); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, + tests[i].fog_table_mode); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_RANGEFOGENABLE, tests[i].range_fog); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DVertexBuffer7_Lock(src_vb, 0, (void **)&src_data, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + *src_data = tests[i].vertex; + hr = IDirect3DVertexBuffer7_Unlock(src_vb); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + memset(dst_data, 0, sizeof(*dst_data)); + hr = IDirect3DVertexBuffer7_Unlock(dst_vb); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + hr = IDirect3DVertexBuffer7_ProcessVertices(dst_vb, D3DVOP_TRANSFORM | D3DVOP_LIGHT, 0, + 1, src_vb, 0, device, 0); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + hr = IDirect3DVertexBuffer7_Lock(dst_vb, 0, (void **)&dst_data, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + + ok(compare_color(dst_data->specular, tests[i].expected_color, 1) + || broken(tests[i].expected_broken + && compare_color(dst_data->specular, tests[i].expected_broken, 1)), + "Expected color 0x%08x, got 0x%08x, test %u.\n", + tests[i].expected_color, dst_data->specular, i); + + hr = IDirect3DVertexBuffer7_Unlock(dst_vb); + ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr); + } + + IDirect3DVertexBuffer7_Release(dst_vb); + IDirect3DVertexBuffer7_Release(src_vb); + IDirect3D7_Release(d3d); + refcount = IDirect3DDevice7_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + static void test_negative_fixedfunction_fog(void) { HRESULT hr; @@ -16261,6 +16444,7 @@ START_TEST(ddraw7) test_resource_priority(); test_surface_desc_lock(); test_fog_interpolation(); + test_fog_process_vertices(); test_negative_fixedfunction_fog(); test_table_fog_zw(); test_signed_formats();
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=53443
Your paranoid android.
=== w1064v1507 (32 bit report) ===
ddraw: ddraw7.c:3871: Test failed: Lit quad without normals has color 0x00ff00ff, expected 0x00000000. ddraw7.c:3884: Test failed: Lit quad with normals has color 0x00ff00ff, expected 0x00000000. ddraw7.c:3929: Test failed: Lit quad with light has color 0x00ff00ff. ddraw7.c:3929: Test failed: Lit quad with singular world matrix has color 0x00ff00ff. ddraw7.c:3929: Test failed: Lit quad with transformation matrix has color 0x00ff00ff. ddraw7.c:3929: Test failed: Lit quad with non-affine matrix has color 0x00ff00ff.
=== w1064v1809 (32 bit report) ===
ddraw: 1a0c:ddraw7: unhandled exception c0000005 at 72A840F8
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com