[PATCH v2 1/7] wined3d: Use color source for output colors in process_vertices_strided().
Paul Gofman
gofmanp at gmail.com
Fri May 17 03:51:48 CDT 2019
Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
v2 changes:
- use wined3d_format_convert_from_float() instead of introducing d3dcolor_from_wined3d_color();
- renamed clamp_vec() to wined3d_color_clamp();
- do not assume D3DCOLOR format for input stream color value;
- introduced material_specular_state_color variable.
dlls/wined3d/device.c | 198 ++++++++++++++++++++++++++++++++++--------
1 file changed, 161 insertions(+), 37 deletions(-)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 5272e2ef23..81a76398a7 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3072,20 +3072,141 @@ static unsigned int wined3d_get_flexible_vertex_size(DWORD fvf)
return size;
}
+static void wined3d_format_get_color(const struct wined3d_format *format, const BYTE *data,
+ struct wined3d_color *color)
+{
+ static const struct wined3d_color default_color = {0.0f, 0.0f, 0.0f, 1.0f};
+ float *output = &color->r;
+ unsigned int i;
+
+ switch (format->id)
+ {
+ case WINED3DFMT_B8G8R8A8_UNORM:
+ wined3d_color_from_d3dcolor(color, *(const DWORD *)data);
+ break;
+
+ case WINED3DFMT_R8G8B8A8_UNORM:
+ {
+ DWORD value = *(const DWORD *)data;
+
+ color->r = (value & 0xff) / 255.0f;
+ color->g = ((value >> 8) & 0xff) / 255.0f;
+ color->b = ((value >> 16) & 0xff) / 255.0f;
+ color->a = ((value >> 24) & 0xff) / 255.0f;
+ break;
+ }
+
+ case WINED3DFMT_R16G16_UNORM:
+ case WINED3DFMT_R16G16B16A16_UNORM:
+ {
+ const unsigned short *ushort_data = (const unsigned short *)data;
+
+ *color = default_color;
+
+ for (i = 0; i < format->component_count; ++i)
+ output[i] = ushort_data[i] / 65535.0f;
+
+ break;
+ }
+
+ case WINED3DFMT_R32_FLOAT:
+ case WINED3DFMT_R32G32_FLOAT:
+ case WINED3DFMT_R32G32B32_FLOAT:
+ case WINED3DFMT_R32G32B32A32_FLOAT:
+ {
+ const float *float_data = (const float *)data;
+
+ for (i = 0; i < format->component_count; ++i)
+ output[i] = float_data[i];
+
+ break;
+ }
+
+ default:
+ {
+ static BOOL warned;
+
+ *color = default_color;
+
+ if (!warned)
+ {
+ FIXME("Unhandled color format conversion, format %s.\n", debug_d3dformat(format->id));
+ warned = TRUE;
+ }
+ break;
+ }
+ }
+}
+
+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:
+ color->r = color->g = color->b = color->a = 0.0f;
+ ERR("Invalid material color source %#x.\n", mcs);
+ return;
+ }
+ wined3d_format_get_color(element->format, element->data.addr + index * element->stride, color);
+}
+
+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 wined3d_color_clamp(struct wined3d_color *dst, const struct wined3d_color *src,
+ float min_value, float max_value)
+{
+ dst->r = clamp(src->r, min_value, max_value);
+ dst->g = clamp(src->g, min_value, max_value);
+ dst->b = clamp(src->b, min_value, max_value);
+ dst->a = clamp(src->a, 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;
+ const struct wined3d_color *material_specular_state_color;
struct wined3d_matrix mat, proj_mat, view_mat, world_mat;
+ const struct wined3d_state *state = &device->state;
+ const struct wined3d_format *output_color_format;
+ static const struct wined3d_color black;
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 +3216,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 +3277,37 @@ 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;
+ }
+ output_color_format = wined3d_get_format(device->adapter, WINED3DFMT_B8G8R8A8_UNORM, 0);
+ material_specular_state_color = state->render_states[WINED3D_RS_SPECULARENABLE]
+ ? &state->material.specular : &black;
+
for (i = 0; i < dwCount; i+= 1) {
unsigned int tex_index;
@@ -3278,47 +3425,24 @@ 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));
- }
+ wined3d_color_clamp(&material_diffuse, &material_diffuse, 0.0f, 1.0f);
+ *((DWORD *)dest_ptr) = wined3d_format_convert_from_float(output_color_format, &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;
- }
+ color_from_mcs(&material_specular, specular_source, material_specular_state_color, i, stream_info);
- *(DWORD *)dest_ptr = 0xff000000;
- dest_ptr += sizeof(DWORD);
- }
- else
- {
- copy_and_next(dest_ptr, color_s, sizeof(DWORD));
- }
+ wined3d_color_clamp(&material_specular, &material_specular, 0.0f, 1.0f);
+ *((DWORD *)dest_ptr) = wined3d_format_convert_from_float(output_color_format, &material_specular);
+ dest_ptr += sizeof(DWORD);
}
for (tex_index = 0; tex_index < numTextures; ++tex_index)
--
2.21.0
More information about the wine-devel
mailing list