Signed-off-by: Paul Gofman gofmanp@gmail.com --- dlls/wined3d/device.c | 127 +++++++++++++++++++++++---------- dlls/wined3d/wined3d_private.h | 10 +++ 2 files changed, 100 insertions(+), 37 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index 5272e2ef23..938c420f5b 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -3072,20 +3072,71 @@ static unsigned int wined3d_get_flexible_vertex_size(DWORD fvf) return size; }
+static void color_from_mcs(struct wined3d_color *color, enum wined3d_material_color_source mcs, + const struct wined3d_color *material_color, unsigned int index, + const struct wined3d_stream_info *stream_info) +{ + const struct wined3d_stream_info_element *element = NULL; + + switch (mcs) + { + case WINED3D_MCS_MATERIAL: + *color = *material_color; + return; + case WINED3D_MCS_COLOR1: + if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE))) + { + color->r = color->g = color->b = color->a = 1.0f; + return; + } + element = &stream_info->elements[WINED3D_FFP_DIFFUSE]; + break; + case WINED3D_MCS_COLOR2: + if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR))) + { + color->r = color->g = color->b = 0.0f; + color->a = 1.0f; + return; + } + element = &stream_info->elements[WINED3D_FFP_SPECULAR]; + break; + default: + ERR("Invalid material color source %#x.\n", mcs); + break; + } + wined3d_color_from_d3dcolor(color, element ? *(const DWORD *)(element->data.addr + index * element->stride) : 0); +} + +static float clamp(float value, float min_value, float max_value) +{ + return value < min_value ? min_value : value > max_value ? max_value : value; +} + +static void clamp_vec(float *dst, const float *src, unsigned int count, + float min_value, float max_value) +{ + unsigned int i; + + for (i = 0; i < count; ++i) + dst[i] = clamp(src[i], min_value, max_value); +} + /* 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, const struct wined3d_stream_info *stream_info, struct wined3d_buffer *dest, DWORD flags, DWORD dst_fvf) { + enum wined3d_material_color_source diffuse_source, specular_source; struct wined3d_matrix mat, proj_mat, view_mat, world_mat; + const struct wined3d_state *state = &device->state; struct wined3d_map_desc map_desc; struct wined3d_box box = {0}; struct wined3d_viewport vp; unsigned int vertex_size; + BOOL doClip, lighting; + DWORD numTextures; unsigned int i; BYTE *dest_ptr; - BOOL doClip; - DWORD numTextures; HRESULT hr;
if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL)) @@ -3095,11 +3146,11 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
if (!(stream_info->use_map & (1u << WINED3D_FFP_POSITION))) { - ERR("Source has no position mask\n"); + ERR("Source has no position mask.\n"); return WINED3DERR_INVALIDCALL; }
- if (device->state.render_states[WINED3D_RS_CLIPPING]) + if (state->render_states[WINED3D_RS_CLIPPING]) { static BOOL warned = FALSE; /* @@ -3156,11 +3207,34 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO TRACE("viewport x %.8e, y %.8e, width %.8e, height %.8e, min_z %.8e, max_z %.8e.\n", vp.x, vp.y, vp.width, vp.height, vp.min_z, vp.max_z);
+ lighting = state->render_states[WINED3D_RS_LIGHTING] + && (dst_fvf & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR)); + multiply_matrix(&mat,&view_mat,&world_mat); multiply_matrix(&mat,&proj_mat,&mat);
numTextures = (dst_fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
+ if (lighting) + { + if (state->render_states[WINED3D_RS_COLORVERTEX]) + { + diffuse_source = validate_material_colour_source(stream_info->use_map, + state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE]); + specular_source = validate_material_colour_source(stream_info->use_map, + state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE]); + } + else + { + diffuse_source = specular_source = WINED3D_MCS_MATERIAL; + } + } + else + { + diffuse_source = WINED3D_MCS_COLOR1; + specular_source = WINED3D_MCS_COLOR2; + } + for (i = 0; i < dwCount; i+= 1) { unsigned int tex_index;
@@ -3278,47 +3352,26 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
if (dst_fvf & WINED3DFVF_DIFFUSE) { - const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_DIFFUSE]; - const DWORD *color_d = (const DWORD *)(element->data.addr + i * element->stride); - if (!(stream_info->use_map & (1u << WINED3D_FFP_DIFFUSE))) - { - static BOOL warned = FALSE; + struct wined3d_color material_diffuse;
- if(!warned) { - ERR("No diffuse color in source, but destination has one\n"); - warned = TRUE; - } + color_from_mcs(&material_diffuse, diffuse_source, &state->material.diffuse, i, stream_info);
- *( (DWORD *) dest_ptr) = 0xffffffff; - dest_ptr += sizeof(DWORD); - } - else - { - copy_and_next(dest_ptr, color_d, sizeof(DWORD)); - } + clamp_vec(&material_diffuse.r, &material_diffuse.r, 4, 0.0f, 1.0f); + *((DWORD *)dest_ptr) = d3dcolor_from_wined3d_color(&material_diffuse); + dest_ptr += sizeof(DWORD); }
if (dst_fvf & WINED3DFVF_SPECULAR) { - /* What's the color value in the feedback buffer? */ - const struct wined3d_stream_info_element *element = &stream_info->elements[WINED3D_FFP_SPECULAR]; - const DWORD *color_s = (const DWORD *)(element->data.addr + i * element->stride); - if (!(stream_info->use_map & (1u << WINED3D_FFP_SPECULAR))) - { - static BOOL warned = FALSE; + struct wined3d_color material_specular;
- if(!warned) { - ERR("No specular color in source, but destination has one\n"); - warned = TRUE; - } + memset(&material_specular, 0, sizeof(material_specular)); + color_from_mcs(&material_specular, specular_source, state->render_states[WINED3D_RS_SPECULARENABLE] + ? &state->material.specular : &material_specular, i, stream_info);
- *(DWORD *)dest_ptr = 0xff000000; - dest_ptr += sizeof(DWORD); - } - else - { - copy_and_next(dest_ptr, color_s, sizeof(DWORD)); - } + clamp_vec(&material_specular.r, &material_specular.r, 4, 0.0f, 1.0f); + *((DWORD *)dest_ptr) = d3dcolor_from_wined3d_color(&material_specular); + dest_ptr += sizeof(DWORD); }
for (tex_index = 0; tex_index < numTextures; ++tex_index) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d76166690e..d59d466cb3 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1469,6 +1469,16 @@ static inline void wined3d_color_from_d3dcolor(struct wined3d_color *wined3d_col wined3d_color->a = D3DCOLOR_B_A(d3d_color) / 255.0f; }
+#define D3DCOLOR_R_B(dw) (((BYTE)(dw)) << 16) +#define D3DCOLOR_G_B(dw) (((BYTE)(dw)) << 8) +#define D3DCOLOR_A_B(dw) (((BYTE)(dw)) << 24) + +static inline DWORD d3dcolor_from_wined3d_color(const struct wined3d_color *wined3d_color) +{ + return D3DCOLOR_R_B(lrint(wined3d_color->r * 255.0f)) | D3DCOLOR_G_B(lrint(wined3d_color->g * 255.0f)) + | D3DCOLOR_B_B(lrint(wined3d_color->b * 255.0f)) | D3DCOLOR_A_B(lrint(wined3d_color->a * 255.0f)); +} + #define WINED3D_HIGHEST_TRANSFORM_STATE WINED3D_TS_WORLD_MATRIX(255) /* Highest value in wined3d_transform_state. */
void wined3d_check_gl_call(const struct wined3d_gl_info *gl_info,