[PATCH v3 2/8] wined3d: Use color source for output colors in process_vertices_strided().

Paul Gofman gofmanp at gmail.com
Mon May 20 04:56:37 CDT 2019


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
v2:
    - 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;
v3:
    - fix missing default color initialiazation in wined3d_format_get_color();
    - use wined3d_get_mcs() function.

 dlls/wined3d/device.c | 179 +++++++++++++++++++++++++++++++++---------
 1 file changed, 143 insertions(+), 36 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 5a94d03b9b..f1072f9cdb 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3072,20 +3072,143 @@ 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;
+
+            *color = default_color;
+
+            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 wined3d_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 = wined3d_clamp(src->r, min_value, max_value);
+    dst->g = wined3d_clamp(src->g, min_value, max_value);
+    dst->b = wined3d_clamp(src->b, min_value, max_value);
+    dst->a = wined3d_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, ambient_source, emissive_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;
+    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 +3218,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;
         /*
@@ -3161,6 +3284,13 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
 
     numTextures = (dst_fvf & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
 
+    wined3d_get_mcs(&diffuse_source, &emissive_source, &ambient_source, &specular_source,
+            state, stream_info);
+
+    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 +3408,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