[PATCH 3/5] wined3d: Move tex_unit_map and friends into the context

Stefan Dösinger stefan at codeweavers.com
Fri Sep 13 05:40:34 CDT 2013


---
 dlls/wined3d/arb_program_shader.c    |   8 +-
 dlls/wined3d/ati_fragment_shader.c   |   2 +-
 dlls/wined3d/context.c               | 236 ++++++++++++++++++++++++++++++++++-
 dlls/wined3d/device.c                | 231 +---------------------------------
 dlls/wined3d/drawprim.c              |   4 +-
 dlls/wined3d/glsl_shader.c           |   5 +-
 dlls/wined3d/nvidia_texture_shader.c |   9 +-
 dlls/wined3d/state.c                 |  25 ++--
 dlls/wined3d/surface.c               |   7 +-
 dlls/wined3d/utils.c                 |   2 +-
 dlls/wined3d/volume.c                |   4 +-
 dlls/wined3d/wined3d_private.h       |  32 ++---
 12 files changed, 279 insertions(+), 286 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index ec4cb89..631c2ea 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -4574,7 +4574,7 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
         const struct wined3d_context *context, const struct wined3d_shader *shader,
         struct arb_vs_compile_args *args)
 {
-    struct wined3d_device *device = shader->device;
+    const struct wined3d_device *device = shader->device;
     const struct wined3d_adapter *adapter = device->adapter;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
@@ -4618,9 +4618,9 @@ static void find_arb_vs_compile_args(const struct wined3d_state *state,
             args->clip.boolclip.bools |= ( 1 << i);
     }
 
-    args->vertex.samplers[0] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 0];
-    args->vertex.samplers[1] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 1];
-    args->vertex.samplers[2] = device->texUnitMap[MAX_FRAGMENT_SAMPLERS + 2];
+    args->vertex.samplers[0] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 0];
+    args->vertex.samplers[1] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 1];
+    args->vertex.samplers[2] = context->tex_unit_map[MAX_FRAGMENT_SAMPLERS + 2];
     args->vertex.samplers[3] = 0;
 
     /* Skip if unused or local */
diff --git a/dlls/wined3d/ati_fragment_shader.c b/dlls/wined3d/ati_fragment_shader.c
index cf35f64..8fc7909 100644
--- a/dlls/wined3d/ati_fragment_shader.c
+++ b/dlls/wined3d/ati_fragment_shader.c
@@ -874,7 +874,7 @@ static void set_tex_op_atifs(struct wined3d_context *context, const struct wined
      */
     for (i = 0; i < desc->num_textures_used; ++i)
     {
-        mapped_stage = device->texUnitMap[i];
+        mapped_stage = context->tex_unit_map[i];
         if (mapped_stage != WINED3D_UNMAPPED_STAGE)
         {
             context_active_texture(context, gl_info, mapped_stage);
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index b69a520..a6f27dc 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1350,6 +1350,21 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
         goto out;
     }
 
+    /* Initialize the texture unit mapping to a 1:1 mapping */
+    for (s = 0; s < MAX_COMBINED_SAMPLERS; ++s)
+    {
+        if (s < gl_info->limits.fragment_samplers)
+        {
+            ret->tex_unit_map[s] = s;
+            ret->rev_tex_unit_map[s] = s;
+        }
+        else
+        {
+            ret->tex_unit_map[s] = WINED3D_UNMAPPED_STAGE;
+            ret->rev_tex_unit_map[s] = WINED3D_UNMAPPED_STAGE;
+        }
+    }
+
     if (!(hdc = GetDC(swapchain->win_handle)))
     {
         WARN("Failed to retireve device context, trying swapchain backup.\n");
@@ -1772,7 +1787,7 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
      */
     for (i = gl_info->limits.textures - 1; i > 0 ; --i)
     {
-        sampler = device->rev_tex_unit_map[i];
+        sampler = context->rev_tex_unit_map[i];
         context_active_texture(context, gl_info, i);
 
         if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
@@ -1802,7 +1817,7 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
     }
     context_active_texture(context, gl_info, 0);
 
-    sampler = device->rev_tex_unit_map[0];
+    sampler = context->rev_tex_unit_map[0];
 
     if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
     {
@@ -2328,6 +2343,221 @@ void context_state_fb(struct wined3d_context *context, const struct wined3d_stat
     }
 }
 
+static void context_map_stage(struct wined3d_context *context, DWORD stage, DWORD unit)
+{
+    DWORD i = context->rev_tex_unit_map[unit];
+    DWORD j = context->tex_unit_map[stage];
+
+    context->tex_unit_map[stage] = unit;
+    if (i != WINED3D_UNMAPPED_STAGE && i != stage)
+        context->tex_unit_map[i] = WINED3D_UNMAPPED_STAGE;
+
+    context->rev_tex_unit_map[unit] = stage;
+    if (j != WINED3D_UNMAPPED_STAGE && j != unit)
+        context->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE;
+}
+
+static void context_invalidate_texture_stage(struct wined3d_context *context, DWORD stage)
+{
+    DWORD i;
+
+    for (i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
+        context_invalidate_state(context, STATE_TEXTURESTAGE(stage, i));
+}
+
+static void context_update_fixed_function_usage_map(struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    UINT i;
+
+    context->fixed_function_usage_map = 0;
+    for (i = 0; i < MAX_TEXTURES; ++i)
+    {
+        enum wined3d_texture_op color_op = state->texture_states[i][WINED3D_TSS_COLOR_OP];
+        enum wined3d_texture_op alpha_op = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
+        DWORD color_arg1 = state->texture_states[i][WINED3D_TSS_COLOR_ARG1] & WINED3DTA_SELECTMASK;
+        DWORD color_arg2 = state->texture_states[i][WINED3D_TSS_COLOR_ARG2] & WINED3DTA_SELECTMASK;
+        DWORD color_arg3 = state->texture_states[i][WINED3D_TSS_COLOR_ARG0] & WINED3DTA_SELECTMASK;
+        DWORD alpha_arg1 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] & WINED3DTA_SELECTMASK;
+        DWORD alpha_arg2 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] & WINED3DTA_SELECTMASK;
+        DWORD alpha_arg3 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] & WINED3DTA_SELECTMASK;
+
+        /* Not used, and disable higher stages. */
+        if (color_op == WINED3D_TOP_DISABLE)
+            break;
+
+        if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3D_TOP_SELECT_ARG2)
+                || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3D_TOP_SELECT_ARG1)
+                || ((color_arg3 == WINED3DTA_TEXTURE)
+                    && (color_op == WINED3D_TOP_MULTIPLY_ADD || color_op == WINED3D_TOP_LERP))
+                || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG2)
+                || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG1)
+                || ((alpha_arg3 == WINED3DTA_TEXTURE)
+                    && (alpha_op == WINED3D_TOP_MULTIPLY_ADD || alpha_op == WINED3D_TOP_LERP)))
+            context->fixed_function_usage_map |= (1 << i);
+
+        if ((color_op == WINED3D_TOP_BUMPENVMAP || color_op == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
+                && i < MAX_TEXTURES - 1)
+            context->fixed_function_usage_map |= (1 << (i + 1));
+    }
+}
+
+static void context_map_fixed_function_samplers(struct wined3d_context *context,
+        const struct wined3d_state *state)
+{
+    unsigned int i, tex;
+    WORD ffu_map;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+
+    context_update_fixed_function_usage_map(context, state);
+    ffu_map = context->fixed_function_usage_map;
+
+    if (d3d_info->limits.ffp_textures == d3d_info->limits.ffp_blend_stages
+            || state->lowest_disabled_stage <= d3d_info->limits.ffp_textures)
+    {
+        for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+        {
+            if (!(ffu_map & 1))
+                continue;
+
+            if (context->tex_unit_map[i] != i)
+            {
+                context_map_stage(context, i, i);
+                context_invalidate_state(context, STATE_SAMPLER(i));
+                context_invalidate_texture_stage(context, i);
+            }
+        }
+        return;
+    }
+
+    /* Now work out the mapping */
+    tex = 0;
+    for (i = 0; ffu_map; ffu_map >>= 1, ++i)
+    {
+        if (!(ffu_map & 1))
+            continue;
+
+        if (context->tex_unit_map[i] != tex)
+        {
+            context_map_stage(context, i, tex);
+            context_invalidate_state(context, STATE_SAMPLER(i));
+            context_invalidate_texture_stage(context, i);
+        }
+
+        ++tex;
+    }
+}
+
+static void context_map_psamplers(struct wined3d_context *context, const struct wined3d_state *state)
+{
+    const enum wined3d_sampler_texture_type *sampler_type =
+            state->pixel_shader->reg_maps.sampler_type;
+    unsigned int i;
+    const struct wined3d_d3d_info *d3d_info = context->d3d_info;
+
+    for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
+    {
+        if (sampler_type[i] && context->tex_unit_map[i] != i)
+        {
+            context_map_stage(context, i, i);
+            context_invalidate_state(context, STATE_SAMPLER(i));
+            if (i < d3d_info->limits.ffp_blend_stages)
+                context_invalidate_texture_stage(context, i);
+        }
+    }
+}
+
+static BOOL context_unit_free_for_vs(const struct wined3d_context *context,
+        const enum wined3d_sampler_texture_type *pshader_sampler_tokens,
+        const enum wined3d_sampler_texture_type *vshader_sampler_tokens, DWORD unit)
+{
+    DWORD current_mapping = context->rev_tex_unit_map[unit];
+
+    /* Not currently used */
+    if (current_mapping == WINED3D_UNMAPPED_STAGE)
+        return TRUE;
+
+    if (current_mapping < MAX_FRAGMENT_SAMPLERS)
+    {
+        /* Used by a fragment sampler */
+
+        if (!pshader_sampler_tokens)
+        {
+            /* No pixel shader, check fixed function */
+            return current_mapping >= MAX_TEXTURES || !(context->fixed_function_usage_map & (1 << current_mapping));
+        }
+
+        /* Pixel shader, check the shader's sampler map */
+        return !pshader_sampler_tokens[current_mapping];
+    }
+
+    /* Used by a vertex sampler */
+    return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS];
+}
+
+static void context_map_vsamplers(struct wined3d_context *context, BOOL ps, const struct wined3d_state *state)
+{
+    const enum wined3d_sampler_texture_type *vshader_sampler_type =
+            state->vertex_shader->reg_maps.sampler_type;
+    const enum wined3d_sampler_texture_type *pshader_sampler_type = NULL;
+    const struct wined3d_gl_info *gl_info = context->gl_info;
+    int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1;
+    int i;
+
+    if (ps)
+    {
+        /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
+         * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
+        pshader_sampler_type = state->pixel_shader->reg_maps.sampler_type;
+    }
+
+    for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
+        DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
+        if (vshader_sampler_type[i])
+        {
+            if (context->tex_unit_map[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
+            {
+                /* Already mapped somewhere */
+                continue;
+            }
+
+            while (start >= 0)
+            {
+                if (context_unit_free_for_vs(context, pshader_sampler_type, vshader_sampler_type, start))
+                {
+                    context_map_stage(context, vsampler_idx, start);
+                    context_invalidate_state(context, STATE_SAMPLER(vsampler_idx));
+
+                    --start;
+                    break;
+                }
+
+                --start;
+            }
+        }
+    }
+}
+
+static void context_update_tex_unit_map(struct wined3d_context *context, const struct wined3d_state *state)
+{
+    BOOL vs = use_vs(state);
+    BOOL ps = use_ps(state);
+    /*
+     * Rules are:
+     * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
+     * that would be really messy and require shader recompilation
+     * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
+     * to be reset. Because of that try to work with a 1:1 mapping as much as possible
+     */
+    if (ps)
+        context_map_psamplers(context, state);
+    else
+        context_map_fixed_function_samplers(context, state);
+
+    if (vs)
+        context_map_vsamplers(context, ps, state);
+}
+
 /* Context activation is done by the caller. */
 void context_state_drawbuf(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
@@ -2576,7 +2806,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
     /* Preload resources before FBO setup. Texture preload in particular may
      * result in changes to the current FBO, due to using e.g. FBO blits for
      * updating a resource location. */
-    device_update_tex_unit_map(device);
+    context_update_tex_unit_map(context, state);
     device_preload_textures(device, context);
     if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC))
         context_update_stream_info(context, state);
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 13e62c7..97e499c 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -171,7 +171,7 @@ void device_preload_textures(const struct wined3d_device *device, struct wined3d
     }
     else
     {
-        WORD ffu_map = device->fixed_function_usage_map;
+        WORD ffu_map = context->fixed_function_usage_map;
 
         for (i = 0; ffu_map; ffu_map >>= 1, ++i)
         {
@@ -882,7 +882,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     struct wined3d_swapchain *swapchain = NULL;
     struct wined3d_context *context;
     HRESULT hr;
-    DWORD state;
 
     TRACE("device %p, swapchain_desc %p.\n", device, swapchain_desc);
 
@@ -894,21 +893,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
     device->fb.render_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
             sizeof(*device->fb.render_targets) * gl_info->limits.buffers);
 
-    /* Initialize the texture unit mapping to a 1:1 mapping */
-    for (state = 0; state < MAX_COMBINED_SAMPLERS; ++state)
-    {
-        if (state < gl_info->limits.fragment_samplers)
-        {
-            device->texUnitMap[state] = state;
-            device->rev_tex_unit_map[state] = state;
-        }
-        else
-        {
-            device->texUnitMap[state] = WINED3D_UNMAPPED_STAGE;
-            device->rev_tex_unit_map[state] = WINED3D_UNMAPPED_STAGE;
-        }
-    }
-
     if (FAILED(hr = device->shader_backend->shader_alloc_private(device,
             device->adapter->vertex_pipe, device->adapter->fragment_pipe)))
     {
@@ -2451,217 +2435,6 @@ HRESULT CDECL wined3d_device_get_vs_consts_f(const struct wined3d_device *device
     return WINED3D_OK;
 }
 
-static void device_invalidate_texture_stage(const struct wined3d_device *device, DWORD stage)
-{
-    DWORD i;
-
-    for (i = 0; i <= WINED3D_HIGHEST_TEXTURE_STATE; ++i)
-    {
-        device_invalidate_state(device, STATE_TEXTURESTAGE(stage, i));
-    }
-}
-
-static void device_map_stage(struct wined3d_device *device, DWORD stage, DWORD unit)
-{
-    DWORD i = device->rev_tex_unit_map[unit];
-    DWORD j = device->texUnitMap[stage];
-
-    device->texUnitMap[stage] = unit;
-    if (i != WINED3D_UNMAPPED_STAGE && i != stage)
-        device->texUnitMap[i] = WINED3D_UNMAPPED_STAGE;
-
-    device->rev_tex_unit_map[unit] = stage;
-    if (j != WINED3D_UNMAPPED_STAGE && j != unit)
-        device->rev_tex_unit_map[j] = WINED3D_UNMAPPED_STAGE;
-}
-
-static void device_update_fixed_function_usage_map(struct wined3d_device *device)
-{
-    UINT i;
-
-    device->fixed_function_usage_map = 0;
-    for (i = 0; i < MAX_TEXTURES; ++i)
-    {
-        const struct wined3d_state *state = &device->state;
-        enum wined3d_texture_op color_op = state->texture_states[i][WINED3D_TSS_COLOR_OP];
-        enum wined3d_texture_op alpha_op = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
-        DWORD color_arg1 = state->texture_states[i][WINED3D_TSS_COLOR_ARG1] & WINED3DTA_SELECTMASK;
-        DWORD color_arg2 = state->texture_states[i][WINED3D_TSS_COLOR_ARG2] & WINED3DTA_SELECTMASK;
-        DWORD color_arg3 = state->texture_states[i][WINED3D_TSS_COLOR_ARG0] & WINED3DTA_SELECTMASK;
-        DWORD alpha_arg1 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] & WINED3DTA_SELECTMASK;
-        DWORD alpha_arg2 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] & WINED3DTA_SELECTMASK;
-        DWORD alpha_arg3 = state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] & WINED3DTA_SELECTMASK;
-
-        /* Not used, and disable higher stages. */
-        if (color_op == WINED3D_TOP_DISABLE)
-            break;
-
-        if (((color_arg1 == WINED3DTA_TEXTURE) && color_op != WINED3D_TOP_SELECT_ARG2)
-                || ((color_arg2 == WINED3DTA_TEXTURE) && color_op != WINED3D_TOP_SELECT_ARG1)
-                || ((color_arg3 == WINED3DTA_TEXTURE)
-                    && (color_op == WINED3D_TOP_MULTIPLY_ADD || color_op == WINED3D_TOP_LERP))
-                || ((alpha_arg1 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG2)
-                || ((alpha_arg2 == WINED3DTA_TEXTURE) && alpha_op != WINED3D_TOP_SELECT_ARG1)
-                || ((alpha_arg3 == WINED3DTA_TEXTURE)
-                    && (alpha_op == WINED3D_TOP_MULTIPLY_ADD || alpha_op == WINED3D_TOP_LERP)))
-            device->fixed_function_usage_map |= (1 << i);
-
-        if ((color_op == WINED3D_TOP_BUMPENVMAP || color_op == WINED3D_TOP_BUMPENVMAP_LUMINANCE)
-                && i < MAX_TEXTURES - 1)
-            device->fixed_function_usage_map |= (1 << (i + 1));
-    }
-}
-
-static void device_map_fixed_function_samplers(struct wined3d_device *device, const struct wined3d_d3d_info *d3d_info)
-{
-    unsigned int i, tex;
-    WORD ffu_map;
-
-    device_update_fixed_function_usage_map(device);
-    ffu_map = device->fixed_function_usage_map;
-
-    if (d3d_info->limits.ffp_textures == d3d_info->limits.ffp_blend_stages
-            || device->state.lowest_disabled_stage <= d3d_info->limits.ffp_textures)
-    {
-        for (i = 0; ffu_map; ffu_map >>= 1, ++i)
-        {
-            if (!(ffu_map & 1)) continue;
-
-            if (device->texUnitMap[i] != i)
-            {
-                device_map_stage(device, i, i);
-                device_invalidate_state(device, STATE_SAMPLER(i));
-                device_invalidate_texture_stage(device, i);
-            }
-        }
-        return;
-    }
-
-    /* Now work out the mapping */
-    tex = 0;
-    for (i = 0; ffu_map; ffu_map >>= 1, ++i)
-    {
-        if (!(ffu_map & 1)) continue;
-
-        if (device->texUnitMap[i] != tex)
-        {
-            device_map_stage(device, i, tex);
-            device_invalidate_state(device, STATE_SAMPLER(i));
-            device_invalidate_texture_stage(device, i);
-        }
-
-        ++tex;
-    }
-}
-
-static void device_map_psamplers(struct wined3d_device *device, const struct wined3d_d3d_info *d3d_info)
-{
-    const enum wined3d_sampler_texture_type *sampler_type =
-            device->state.pixel_shader->reg_maps.sampler_type;
-    unsigned int i;
-
-    for (i = 0; i < MAX_FRAGMENT_SAMPLERS; ++i)
-    {
-        if (sampler_type[i] && device->texUnitMap[i] != i)
-        {
-            device_map_stage(device, i, i);
-            device_invalidate_state(device, STATE_SAMPLER(i));
-            if (i < d3d_info->limits.ffp_blend_stages)
-                device_invalidate_texture_stage(device, i);
-        }
-    }
-}
-
-static BOOL device_unit_free_for_vs(const struct wined3d_device *device,
-        const enum wined3d_sampler_texture_type *pshader_sampler_tokens,
-        const enum wined3d_sampler_texture_type *vshader_sampler_tokens, DWORD unit)
-{
-    DWORD current_mapping = device->rev_tex_unit_map[unit];
-
-    /* Not currently used */
-    if (current_mapping == WINED3D_UNMAPPED_STAGE) return TRUE;
-
-    if (current_mapping < MAX_FRAGMENT_SAMPLERS) {
-        /* Used by a fragment sampler */
-
-        if (!pshader_sampler_tokens) {
-            /* No pixel shader, check fixed function */
-            return current_mapping >= MAX_TEXTURES || !(device->fixed_function_usage_map & (1 << current_mapping));
-        }
-
-        /* Pixel shader, check the shader's sampler map */
-        return !pshader_sampler_tokens[current_mapping];
-    }
-
-    /* Used by a vertex sampler */
-    return !vshader_sampler_tokens[current_mapping - MAX_FRAGMENT_SAMPLERS];
-}
-
-static void device_map_vsamplers(struct wined3d_device *device, BOOL ps, const struct wined3d_gl_info *gl_info)
-{
-    const enum wined3d_sampler_texture_type *vshader_sampler_type =
-            device->state.vertex_shader->reg_maps.sampler_type;
-    const enum wined3d_sampler_texture_type *pshader_sampler_type = NULL;
-    int start = min(MAX_COMBINED_SAMPLERS, gl_info->limits.combined_samplers) - 1;
-    int i;
-
-    if (ps)
-    {
-        /* Note that we only care if a sampler is sampled or not, not the sampler's specific type.
-         * Otherwise we'd need to call shader_update_samplers() here for 1.x pixelshaders. */
-        pshader_sampler_type = device->state.pixel_shader->reg_maps.sampler_type;
-    }
-
-    for (i = 0; i < MAX_VERTEX_SAMPLERS; ++i) {
-        DWORD vsampler_idx = i + MAX_FRAGMENT_SAMPLERS;
-        if (vshader_sampler_type[i])
-        {
-            if (device->texUnitMap[vsampler_idx] != WINED3D_UNMAPPED_STAGE)
-            {
-                /* Already mapped somewhere */
-                continue;
-            }
-
-            while (start >= 0)
-            {
-                if (device_unit_free_for_vs(device, pshader_sampler_type, vshader_sampler_type, start))
-                {
-                    device_map_stage(device, vsampler_idx, start);
-                    device_invalidate_state(device, STATE_SAMPLER(vsampler_idx));
-
-                    --start;
-                    break;
-                }
-
-                --start;
-            }
-        }
-    }
-}
-
-void device_update_tex_unit_map(struct wined3d_device *device)
-{
-    const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
-    const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
-    const struct wined3d_state *state = &device->state;
-    BOOL vs = use_vs(state);
-    BOOL ps = use_ps(state);
-    /*
-     * Rules are:
-     * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
-     * that would be really messy and require shader recompilation
-     * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
-     * to be reset. Because of that try to work with a 1:1 mapping as much as possible
-     */
-    if (ps)
-        device_map_psamplers(device, d3d_info);
-    else
-        device_map_fixed_function_samplers(device, d3d_info);
-
-    if (vs)
-        device_map_vsamplers(device, ps, gl_info);
-}
-
 void CDECL wined3d_device_set_pixel_shader(struct wined3d_device *device, struct wined3d_shader *shader)
 {
     struct wined3d_shader *prev = device->update_state->pixel_shader;
@@ -4451,7 +4224,7 @@ HRESULT CDECL wined3d_device_set_cursor_properties(struct wined3d_device *device
 
             context = context_acquire(device, NULL);
 
-            invalidate_active_texture(device, context);
+            context_invalidate_active_texture(context);
             /* Create a new cursor texture */
             gl_info->gl_ops.gl.p_glGenTextures(1, &device->cursorTexture);
             checkGLcall("glGenTextures");
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 0b4b3f7..81d2aba 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -194,7 +194,7 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_
     for (textureNo = 0; textureNo < texture_stages; ++textureNo)
     {
         int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
-        DWORD texture_idx = device->texUnitMap[textureNo];
+        DWORD texture_idx = context->tex_unit_map[textureNo];
 
         if (!gl_info->supported[ARB_MULTITEXTURE] && textureNo > 0)
         {
@@ -266,7 +266,7 @@ static void drawStridedSlow(const struct wined3d_device *device, struct wined3d_
             coord_idx = state->texture_states[texture][WINED3D_TSS_TEXCOORD_INDEX];
             ptr = texCoords[coord_idx] + (SkipnStrides * si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].stride);
 
-            texture_idx = device->texUnitMap[texture];
+            texture_idx = context->tex_unit_map[texture];
             ops->texcoord[si->elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->emit_idx](
                     GL_TEXTURE0_ARB + texture_idx, ptr);
         }
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 67de5ea..f30cd47 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -5783,7 +5783,6 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
     GLhandleARB gs_id = 0;
     GLhandleARB ps_id = 0;
     struct list *ps_list, *vs_list;
-    struct wined3d_device *device = context->swapchain->device;
 
     if (!(context->shader_update_mask & (1 << WINED3D_SHADER_TYPE_VERTEX)))
     {
@@ -5985,8 +5984,8 @@ static void set_glsl_shader_program(const struct wined3d_context *context, const
      * fixed function fragment processing setups. So once the program is linked these samplers
      * won't change.
      */
-    shader_glsl_load_vsamplers(gl_info, device->texUnitMap, programId);
-    shader_glsl_load_psamplers(gl_info, device->texUnitMap, programId);
+    shader_glsl_load_vsamplers(gl_info, context->tex_unit_map, programId);
+    shader_glsl_load_psamplers(gl_info, context->tex_unit_map, programId);
 
     entry->constant_update_mask = 0;
     if (vshader)
diff --git a/dlls/wined3d/nvidia_texture_shader.c b/dlls/wined3d/nvidia_texture_shader.c
index 7d4817e..285952a 100644
--- a/dlls/wined3d/nvidia_texture_shader.c
+++ b/dlls/wined3d/nvidia_texture_shader.c
@@ -477,9 +477,8 @@ void set_tex_op_nvrc(const struct wined3d_gl_info *gl_info, const struct wined3d
 static void nvrc_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    const struct wined3d_device *device = context->swapchain->device;
-    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
-    DWORD mapped_stage = device->texUnitMap[stage];
+    BOOL tex_used = context->fixed_function_usage_map & (1 << stage);
+    DWORD mapped_stage = context->tex_unit_map[stage];
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
     TRACE("Setting color op for stage %u.\n", stage);
@@ -584,7 +583,7 @@ static void nvrc_colorop(struct wined3d_context *context, const struct wined3d_s
 static void nvts_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD sampler = state_id - STATE_SAMPLER(0);
-    DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
+    DWORD mapped_stage = context->tex_unit_map[sampler];
 
     /* No need to enable / disable anything here for unused samplers. The tex_colorop
     * handler takes care. Also no action is needed with pixel shaders, or if tex_colorop
@@ -602,7 +601,7 @@ static void nvts_texdim(struct wined3d_context *context, const struct wined3d_st
 static void nvts_bumpenvmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    DWORD mapped_stage = context->swapchain->device->texUnitMap[stage + 1];
+    DWORD mapped_stage = context->tex_unit_map[stage + 1];
     const struct wined3d_gl_info *gl_info = context->gl_info;
     float mat[2][2];
 
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 36d9108..59c03a2 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3130,9 +3130,8 @@ static void set_tex_op(const struct wined3d_gl_info *gl_info, const struct wined
 static void tex_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    const struct wined3d_device *device = context->swapchain->device;
-    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
-    DWORD mapped_stage = device->texUnitMap[stage];
+    BOOL tex_used = context->fixed_function_usage_map & (1 << stage);
+    DWORD mapped_stage = context->tex_unit_map[stage];
     const struct wined3d_gl_info *gl_info = context->gl_info;
 
     TRACE("Setting color op for stage %d\n", stage);
@@ -3192,9 +3191,8 @@ static void tex_colorop(struct wined3d_context *context, const struct wined3d_st
 void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    const struct wined3d_device *device = context->swapchain->device;
-    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
-    DWORD mapped_stage = device->texUnitMap[stage];
+    BOOL tex_used = context->fixed_function_usage_map & (1 << stage);
+    DWORD mapped_stage = context->tex_unit_map[stage];
     const struct wined3d_gl_info *gl_info = context->gl_info;
     DWORD op, arg1, arg2, arg0;
 
@@ -3295,7 +3293,7 @@ void transform_texture(struct wined3d_context *context, const struct wined3d_sta
     DWORD texUnit = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
     const struct wined3d_device *device = context->swapchain->device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    DWORD mapped_stage = device->texUnitMap[texUnit];
+    DWORD mapped_stage = context->tex_unit_map[texUnit];
     BOOL generated;
     int coordIdx;
 
@@ -3351,7 +3349,6 @@ static void unload_tex_coords(const struct wined3d_gl_info *gl_info)
 static void load_tex_coords(const struct wined3d_context *context, const struct wined3d_stream_info *si,
         GLuint *curVBO, const struct wined3d_state *state)
 {
-    const struct wined3d_device *device = context->swapchain->device;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     unsigned int mapped_stage = 0;
     unsigned int textureNo = 0;
@@ -3360,7 +3357,7 @@ static void load_tex_coords(const struct wined3d_context *context, const struct
     {
         int coordIdx = state->texture_states[textureNo][WINED3D_TSS_TEXCOORD_INDEX];
 
-        mapped_stage = device->texUnitMap[textureNo];
+        mapped_stage = context->tex_unit_map[textureNo];
         if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
 
         if (mapped_stage >= gl_info->limits.texture_coords)
@@ -3411,13 +3408,12 @@ static void load_tex_coords(const struct wined3d_context *context, const struct
 static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
-    const struct wined3d_device *device = context->swapchain->device;
     static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
     static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
     static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
     static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
     const struct wined3d_gl_info *gl_info = context->gl_info;
-    DWORD mapped_stage = device->texUnitMap[stage];
+    DWORD mapped_stage = context->tex_unit_map[stage];
 
     if (mapped_stage == WINED3D_UNMAPPED_STAGE)
     {
@@ -3605,24 +3601,21 @@ void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_sta
 
         if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
         {
-            const struct wined3d_device *device = context->swapchain->device;
-
             if (texIsPow2)
                 context->lastWasPow2Texture |= 1 << sampler;
             else
                 context->lastWasPow2Texture &= ~(1 << sampler);
 
             transform_texture(context, state,
-                    STATE_TEXTURESTAGE(device->texUnitMap[sampler], WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
+                    STATE_TEXTURESTAGE(context->tex_unit_map[sampler], WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
         }
     }
 }
 
 static void sampler(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
-    const struct wined3d_device *device = context->swapchain->device;
     DWORD sampler = state_id - STATE_SAMPLER(0);
-    DWORD mapped_stage = device->texUnitMap[sampler];
+    DWORD mapped_stage = context->tex_unit_map[sampler];
     const struct wined3d_gl_info *gl_info = context->gl_info;
     union {
         float f;
diff --git a/dlls/wined3d/surface.c b/dlls/wined3d/surface.c
index ab15870..22a2976 100644
--- a/dlls/wined3d/surface.c
+++ b/dlls/wined3d/surface.c
@@ -659,7 +659,6 @@ static void surface_bind(struct wined3d_surface *surface, struct wined3d_context
 static void surface_bind_and_dirtify(struct wined3d_surface *surface,
         struct wined3d_context *context, BOOL srgb)
 {
-    struct wined3d_device *device = surface->resource.device;
     DWORD active_sampler;
 
     /* We don't need a specific texture unit, but after binding the texture
@@ -671,10 +670,10 @@ static void surface_bind_and_dirtify(struct wined3d_surface *surface,
      * called from sampler() in state.c. This means we can't touch anything
      * other than whatever happens to be the currently active texture, or we
      * would risk marking already applied sampler states dirty again. */
-    active_sampler = device->rev_tex_unit_map[context->active_texture];
+    active_sampler = context->rev_tex_unit_map[context->active_texture];
 
     if (active_sampler != WINED3D_UNMAPPED_STAGE)
-        device_invalidate_state(device, STATE_SAMPLER(active_sampler));
+        context_invalidate_state(context, STATE_SAMPLER(active_sampler));
     surface_bind(surface, context, srgb);
 }
 
@@ -2254,7 +2253,7 @@ HRESULT surface_upload_from_surface(struct wined3d_surface *dst_surface, const P
 
     surface_upload_data(dst_surface, gl_info, src_format, src_rect, src_pitch, dst_point, FALSE, &data);
 
-    invalidate_active_texture(dst_surface->resource.device, context);
+    context_invalidate_active_texture(context);
 
     context_release(context);
 
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 9a56031..6eafb85 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -3497,7 +3497,7 @@ void texture_activate_dimensions(const struct wined3d_texture *texture, const st
 void sampler_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     DWORD sampler = state_id - STATE_SAMPLER(0);
-    DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
+    DWORD mapped_stage = context->tex_unit_map[sampler];
 
     /* No need to enable / disable anything here for unused samplers. The
      * tex_colorop handler takes care. Also no action is needed with pixel
diff --git a/dlls/wined3d/volume.c b/dlls/wined3d/volume.c
index 7f2dbf9..e9408f0 100644
--- a/dlls/wined3d/volume.c
+++ b/dlls/wined3d/volume.c
@@ -42,10 +42,10 @@ static void volume_bind_and_dirtify(const struct wined3d_volume *volume,
      * from sampler() in state.c. This means we can't touch anything other than
      * whatever happens to be the currently active texture, or we would risk
      * marking already applied sampler states dirty again. */
-    active_sampler = volume->resource.device->rev_tex_unit_map[context->active_texture];
+    active_sampler = context->rev_tex_unit_map[context->active_texture];
 
     if (active_sampler != WINED3D_UNMAPPED_STAGE)
-        device_invalidate_state(volume->resource.device, STATE_SAMPLER(active_sampler));
+        context_invalidate_state(context, STATE_SAMPLER(active_sampler));
 
     container->texture_ops->texture_bind(container, context, srgb);
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e98499c..686b97f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1086,6 +1086,8 @@ struct wined3d_context
     DWORD use_immediate_mode_draw : 1;
     DWORD texShaderBumpMap : 8;         /* MAX_TEXTURES, 8 */
     DWORD lastWasPow2Texture : 8;       /* MAX_TEXTURES, 8 */
+    DWORD fixed_function_usage_map : 8; /* MAX_TEXTURES, 8 */
+    DWORD padding : 24;
     DWORD shader_update_mask;
     DWORD constant_update_mask;
     DWORD                   numbered_array_mask;
@@ -1138,6 +1140,9 @@ struct wined3d_context
     struct wined3d_event_query *buffer_queries[MAX_ATTRIBS];
     unsigned int num_buffer_queries;
 
+    DWORD                     tex_unit_map[MAX_COMBINED_SAMPLERS];
+    DWORD                     rev_tex_unit_map[MAX_COMBINED_SAMPLERS];
+
     /* Extension emulation */
     GLint                   gl_fog_source;
     GLfloat                 fog_coord_value;
@@ -1882,18 +1887,18 @@ struct wined3d_device
 
     UINT instance_count;
 
-    WORD vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
-    WORD bCursorVisible : 1;
-    WORD d3d_initialized : 1;
-    WORD inScene : 1;                   /* A flag to check for proper BeginScene / EndScene call pairs */
-    WORD softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
-    WORD filter_messages : 1;
-    WORD padding : 10;
-
-    BYTE fixed_function_usage_map;      /* MAX_TEXTURES, 8 */
+    BYTE vertexBlendUsed : 1;           /* To avoid needless setting of the blend matrices */
+    BYTE bCursorVisible : 1;
+    BYTE d3d_initialized : 1;
+    BYTE inScene : 1;                   /* A flag to check for proper BeginScene / EndScene call pairs */
+    BYTE softwareVertexProcessing : 1;  /* process vertex shaders using software or hardware */
+    BYTE filter_messages : 1;
+    BYTE padding : 2;
 
     unsigned char           surface_alignment; /* Line Alignment of surfaces                      */
 
+    WORD padding2 : 16;
+
     struct wined3d_state state;
     struct wined3d_state *update_state;
     struct wined3d_stateblock *recording;
@@ -1934,10 +1939,6 @@ struct wined3d_device
     UINT dummy_texture_3d[MAX_COMBINED_SAMPLERS];
     UINT dummy_texture_cube[MAX_COMBINED_SAMPLERS];
 
-    /* With register combiners we can skip junk texture stages */
-    DWORD                     texUnitMap[MAX_COMBINED_SAMPLERS];
-    DWORD                     rev_tex_unit_map[MAX_COMBINED_SAMPLERS];
-
     /* Context management */
     struct wined3d_context **contexts;
     UINT context_count;
@@ -1958,7 +1959,6 @@ void device_resource_add(struct wined3d_device *device, struct wined3d_resource
 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_switch_onscreen_ds(struct wined3d_device *device, struct wined3d_context *context,
         struct wined3d_surface *depth_stencil) DECLSPEC_HIDDEN;
-void device_update_tex_unit_map(struct wined3d_device *device) DECLSPEC_HIDDEN;
 void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
@@ -1968,9 +1968,9 @@ static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD sta
     return context->isStateDirty[idx] & (1 << shift);
 }
 
-static inline void invalidate_active_texture(const struct wined3d_device *device, struct wined3d_context *context)
+static inline void context_invalidate_active_texture(struct wined3d_context *context)
 {
-    DWORD sampler = device->rev_tex_unit_map[context->active_texture];
+    DWORD sampler = context->rev_tex_unit_map[context->active_texture];
     if (sampler != WINED3D_UNMAPPED_STAGE)
         context_invalidate_state(context, STATE_SAMPLER(sampler));
 }
-- 
1.8.1.5




More information about the wine-patches mailing list