[PATCH 3/5] wined3d: Make the shader backend responsible for controlling the fixed function fragment pipe.
Henri Verbeet
hverbeet at codeweavers.com
Wed Oct 24 14:23:37 CDT 2012
---
dlls/wined3d/arb_program_shader.c | 36 ++++++++++++++-
dlls/wined3d/context.c | 11 +++--
dlls/wined3d/device.c | 85 ++++++++++++-------------------------
dlls/wined3d/glsl_shader.c | 32 +++++++++++++-
dlls/wined3d/shader.c | 56 +++++++++++++++++++++++-
dlls/wined3d/state.c | 2 +-
dlls/wined3d/wined3d_private.h | 6 ++-
7 files changed, 157 insertions(+), 71 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 0c0b22a..86b2c2f 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -326,6 +326,8 @@ struct shader_arb_priv
unsigned int highest_dirty_ps_const, highest_dirty_vs_const;
char *vshader_const_dirty, *pshader_const_dirty;
const struct wined3d_context *last_context;
+
+ const struct fragment_pipeline *fragment_pipe;
};
/* GL locking for state handlers is done by the caller. */
@@ -4166,6 +4168,7 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
{
const struct arb_vshader_private *shader_data = shader->backend_data;
const struct wined3d_shader_reg_maps *reg_maps = &shader->reg_maps;
+ struct shader_arb_priv *priv = shader->device->shader_priv;
const struct wined3d_shader_lconst *lconst;
const DWORD *function = shader->function;
GLuint ret;
@@ -4258,11 +4261,10 @@ static GLuint shader_arb_generate_vshader(const struct wined3d_shader *shader,
*/
if (!gl_info->supported[NV_VERTEX_PROGRAM])
{
- struct wined3d_device *device = shader->device;
const char *color_init = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_0001);
shader_addline(buffer, "MOV result.color.secondary, %s;\n", color_init);
- if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W && !device->frag_pipe->ffp_proj_control)
+ if (gl_info->quirks & WINED3D_QUIRK_SET_TEXCOORD_W && !priv->fragment_pipe->ffp_proj_control)
{
int i;
const char *one = arb_get_helper_value(WINED3D_SHADER_TYPE_VERTEX, ARB_ONE);
@@ -4876,9 +4878,17 @@ static const struct wine_rb_functions sig_tree_functions =
sig_tree_compare
};
-static HRESULT shader_arb_alloc(struct wined3d_device *device)
+static HRESULT shader_arb_alloc(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe)
{
struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv));
+ HRESULT hr;
+
+ if (FAILED(hr = fragment_pipe->alloc_private(device)))
+ {
+ ERR("Failed to initialize fragment pipe, hr %#x.\n", hr);
+ HeapFree(GetProcessHeap(), 0, priv);
+ return hr;
+ }
priv->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
@@ -4899,12 +4909,14 @@ static HRESULT shader_arb_alloc(struct wined3d_device *device)
ERR("RB tree init failed\n");
goto fail;
}
+ priv->fragment_pipe = fragment_pipe;
device->shader_priv = priv;
return WINED3D_OK;
fail:
HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
+ fragment_pipe->free_private(device);
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
}
@@ -4948,6 +4960,7 @@ static void shader_arb_free(struct wined3d_device *device)
wine_rb_destroy(&priv->signature_tree, release_signature, NULL);
HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
+ priv->fragment_pipe->free_private(device);
HeapFree(GetProcessHeap(), 0, device->shader_priv);
}
@@ -5589,6 +5602,21 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
shader_arb_add_instruction_modifiers(ins);
}
+static void shader_arb_enable_fragment_pipe(void *shader_priv,
+ const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+ struct shader_arb_priv *priv = shader_priv;
+
+ priv->fragment_pipe->enable_extension(gl_info, enable);
+}
+
+static BOOL shader_arb_has_ffp_proj_control(void *shader_priv)
+{
+ struct shader_arb_priv *priv = shader_priv;
+
+ return priv->fragment_pipe->ffp_proj_control;
+}
+
const struct wined3d_shader_backend_ops arb_program_shader_backend =
{
shader_arb_handle_instruction,
@@ -5605,6 +5633,8 @@ const struct wined3d_shader_backend_ops arb_program_shader_backend =
shader_arb_context_destroyed,
shader_arb_get_caps,
shader_arb_color_fixup_supported,
+ shader_arb_enable_fragment_pipe,
+ shader_arb_has_ffp_proj_control,
};
/* ARB_fragment_program fixed function pipeline replacement definitions */
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index 229632d..9ef0dff 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1569,7 +1569,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
{
GL_EXTCALL(glProvokingVertexEXT(GL_FIRST_VERTEX_CONVENTION_EXT));
}
- device->frag_pipe->enable_extension(gl_info, TRUE);
+ device->shader_backend->shader_enable_fragment_pipe(device->shader_priv, gl_info, TRUE);
/* If this happens to be the first context for the device, dummy textures
* are not created yet. In that case, they will be created (and bound) by
@@ -1865,7 +1865,7 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con
context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING));
set_blit_dimension(gl_info, rt_size.cx, rt_size.cy);
- device->frag_pipe->enable_extension(gl_info, FALSE);
+ device->shader_backend->shader_enable_fragment_pipe(device->shader_priv, gl_info, FALSE);
LEAVE_GL();
@@ -2225,7 +2225,7 @@ BOOL context_apply_clear_state(struct wined3d_context *context, const struct win
if (context->last_was_blit)
{
- device->frag_pipe->enable_extension(gl_info, TRUE);
+ device->shader_backend->shader_enable_fragment_pipe(device->shader_priv, gl_info, TRUE);
context->last_was_blit = FALSE;
}
@@ -2354,7 +2354,7 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
ENTER_GL();
if (context->last_was_blit)
- device->frag_pipe->enable_extension(context->gl_info, TRUE);
+ device->shader_backend->shader_enable_fragment_pipe(device->shader_priv, context->gl_info, TRUE);
for (i = 0; i < context->numDirtyEntries; ++i)
{
@@ -2494,7 +2494,8 @@ struct wined3d_context *context_acquire(const struct wined3d_device *device, str
else
{
ENTER_GL();
- device->frag_pipe->enable_extension(context->gl_info, !context->last_was_blit);
+ device->shader_backend->shader_enable_fragment_pipe(device->shader_priv,
+ context->gl_info, !context->last_was_blit);
LEAVE_GL();
}
}
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 45e861e..e01048b 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1241,6 +1241,17 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
}
}
+ if (FAILED(hr = device->shader_backend->shader_alloc_private(device, device->adapter->fragment_pipe)))
+ {
+ TRACE("Shader private data couldn't be allocated\n");
+ goto err_out;
+ }
+ if (FAILED(hr = device->blitter->alloc_private(device)))
+ {
+ TRACE("Blitter private data couldn't be allocated\n");
+ goto err_out;
+ }
+
/* Setup the implicit swapchain. This also initializes a context. */
TRACE("Creating implicit swapchain\n");
hr = device->device_parent->ops->create_swapchain(device->device_parent,
@@ -1277,25 +1288,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
if (device->fb.depth_stencil)
wined3d_surface_incref(device->fb.depth_stencil);
- hr = device->shader_backend->shader_alloc_private(device);
- if (FAILED(hr))
- {
- TRACE("Shader private data couldn't be allocated\n");
- goto err_out;
- }
- hr = device->frag_pipe->alloc_private(device);
- if (FAILED(hr))
- {
- TRACE("Fragment pipeline private data couldn't be allocated\n");
- goto err_out;
- }
- hr = device->blitter->alloc_private(device);
- if (FAILED(hr))
- {
- TRACE("Blitter private data couldn't be allocated\n");
- goto err_out;
- }
-
/* Set up some starting GL setup */
/* Setup all the devices defaults */
@@ -1356,8 +1348,6 @@ err_out:
wined3d_swapchain_decref(swapchain);
if (device->blit_priv)
device->blitter->free_private(device);
- if (device->fragment_priv)
- device->frag_pipe->free_private(device);
if (device->shader_priv)
device->shader_backend->shader_free_private(device);
@@ -1467,7 +1457,6 @@ HRESULT CDECL wined3d_device_uninit_3d(struct wined3d_device *device)
/* Destroy the shader backend. Note that this has to happen after all shaders are destroyed. */
device->blitter->free_private(device);
- device->frag_pipe->free_private(device);
device->shader_backend->shader_free_private(device);
/* Release the buffers (with sanity checks)*/
@@ -4895,7 +4884,6 @@ static void delete_opengl_contexts(struct wined3d_device *device, struct wined3d
LEAVE_GL();
device->blitter->free_private(device);
- device->frag_pipe->free_private(device);
device->shader_backend->shader_free_private(device);
destroy_dummy_textures(device, gl_info);
@@ -4917,11 +4905,26 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru
struct wined3d_surface *target;
HRESULT hr;
+ if (FAILED(hr = device->shader_backend->shader_alloc_private(device, device->adapter->fragment_pipe)))
+ {
+ ERR("Failed to allocate shader private data, hr %#x.\n", hr);
+ return hr;
+ }
+
+ if (FAILED(hr = device->blitter->alloc_private(device)))
+ {
+ ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
+ device->shader_backend->shader_free_private(device);
+ return hr;
+ }
+
/* Recreate the primary swapchain's context */
swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
if (!swapchain->context)
{
ERR("Failed to allocate memory for swapchain context array.\n");
+ device->blitter->free_private(device);
+ device->shader_backend->shader_free_private(device);
return E_OUTOFMEMORY;
}
@@ -4929,6 +4932,8 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru
if (!(context = context_create(swapchain, target, swapchain->ds_format)))
{
WARN("Failed to create context.\n");
+ device->blitter->free_private(device);
+ device->shader_backend->shader_free_private(device);
HeapFree(GetProcessHeap(), 0, swapchain->context);
return E_FAIL;
}
@@ -4938,40 +4943,7 @@ static HRESULT create_primary_opengl_context(struct wined3d_device *device, stru
create_dummy_textures(device, context);
context_release(context);
- hr = device->shader_backend->shader_alloc_private(device);
- if (FAILED(hr))
- {
- ERR("Failed to allocate shader private data, hr %#x.\n", hr);
- goto err;
- }
-
- hr = device->frag_pipe->alloc_private(device);
- if (FAILED(hr))
- {
- ERR("Failed to allocate fragment pipe private data, hr %#x.\n", hr);
- device->shader_backend->shader_free_private(device);
- goto err;
- }
-
- hr = device->blitter->alloc_private(device);
- if (FAILED(hr))
- {
- ERR("Failed to allocate blitter private data, hr %#x.\n", hr);
- device->frag_pipe->free_private(device);
- device->shader_backend->shader_free_private(device);
- goto err;
- }
-
return WINED3D_OK;
-
-err:
- context_acquire(device, NULL);
- destroy_dummy_textures(device, context->gl_info);
- context_release(context);
- context_destroy(device, context);
- HeapFree(GetProcessHeap(), 0, swapchain->context);
- swapchain->num_contexts = 0;
- return hr;
}
/* Do not call while under the GL lock. */
@@ -5487,7 +5459,6 @@ HRESULT device_init(struct wined3d_device *device, struct wined3d *wined3d,
device->vs_clipping = shader_caps.vs_clipping;
}
fragment_pipeline = adapter->fragment_pipe;
- device->frag_pipe = fragment_pipeline;
if (fragment_pipeline)
{
fragment_pipeline->get_caps(&adapter->gl_info, &ffp_caps);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 26a9a81..bf06aee 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -96,6 +96,8 @@ struct shader_glsl_priv {
GLhandleARB depth_blt_program_full[tex_type_count];
GLhandleARB depth_blt_program_masked[tex_type_count];
UINT next_constant_version;
+
+ const struct fragment_pipeline *fragment_pipe;
};
/* Struct to maintain data about a linked GLSL program */
@@ -5225,12 +5227,20 @@ static const struct wine_rb_functions wined3d_glsl_program_rb_functions =
glsl_program_key_compare,
};
-static HRESULT shader_glsl_alloc(struct wined3d_device *device)
+static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe)
{
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv));
SIZE_T stack_size = wined3d_log2i(max(gl_info->limits.glsl_vs_float_constants,
gl_info->limits.glsl_ps_float_constants)) + 1;
+ HRESULT hr;
+
+ if (FAILED(hr = fragment_pipe->alloc_private(device)))
+ {
+ ERR("Failed to initialize fragment pipe, hr %#x.\n", hr);
+ HeapFree(GetProcessHeap(), 0, priv);
+ return hr;
+ }
if (!shader_buffer_init(&priv->shader_buffer))
{
@@ -5264,6 +5274,7 @@ static HRESULT shader_glsl_alloc(struct wined3d_device *device)
}
priv->next_constant_version = 1;
+ priv->fragment_pipe = fragment_pipe;
device->shader_priv = priv;
return WINED3D_OK;
@@ -5273,6 +5284,7 @@ fail:
constant_heap_free(&priv->vconst_heap);
HeapFree(GetProcessHeap(), 0, priv->stack);
shader_buffer_free(&priv->shader_buffer);
+ fragment_pipe->free_private(device);
HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
}
@@ -5303,6 +5315,7 @@ static void shader_glsl_free(struct wined3d_device *device)
constant_heap_free(&priv->vconst_heap);
HeapFree(GetProcessHeap(), 0, priv->stack);
shader_buffer_free(&priv->shader_buffer);
+ priv->fragment_pipe->free_private(device);
HeapFree(GetProcessHeap(), 0, device->shader_priv);
device->shader_priv = NULL;
@@ -5500,6 +5513,21 @@ static void shader_glsl_handle_instruction(const struct wined3d_shader_instructi
shader_glsl_add_instruction_modifiers(ins);
}
+static void shader_glsl_enable_fragment_pipe(void *shader_priv,
+ const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+ struct shader_glsl_priv *priv = shader_priv;
+
+ priv->fragment_pipe->enable_extension(gl_info, enable);
+}
+
+static BOOL shader_glsl_has_ffp_proj_control(void *shader_priv)
+{
+ struct shader_glsl_priv *priv = shader_priv;
+
+ return priv->fragment_pipe->ffp_proj_control;
+}
+
const struct wined3d_shader_backend_ops glsl_shader_backend =
{
shader_glsl_handle_instruction,
@@ -5516,4 +5544,6 @@ const struct wined3d_shader_backend_ops glsl_shader_backend =
shader_glsl_context_destroyed,
shader_glsl_get_caps,
shader_glsl_color_fixup_supported,
+ shader_glsl_enable_fragment_pipe,
+ shader_glsl_has_ffp_proj_control,
};
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index b735b77..1ca79ce 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -1452,6 +1452,11 @@ static void shader_cleanup(struct wined3d_shader *shader)
shader->frontend->shader_free(shader->frontend_data);
}
+struct shader_none_priv
+{
+ const struct fragment_pipeline *fragment_pipe;
+};
+
static void shader_none_handle_instruction(const struct wined3d_shader_instruction *ins) {}
static void shader_none_select(const struct wined3d_context *context, BOOL usePS, BOOL useVS) {}
static void shader_none_select_depth_blt(void *shader_priv, const struct wined3d_gl_info *gl_info,
@@ -1463,10 +1468,40 @@ static void shader_none_load_constants(const struct wined3d_context *context, BO
static void shader_none_load_np2fixup_constants(void *shader_priv,
const struct wined3d_gl_info *gl_info, const struct wined3d_state *state) {}
static void shader_none_destroy(struct wined3d_shader *shader) {}
-static HRESULT shader_none_alloc(struct wined3d_device *device) {return WINED3D_OK;}
-static void shader_none_free(struct wined3d_device *device) {}
static void shader_none_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
+static HRESULT shader_none_alloc(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe)
+{
+ struct shader_none_priv *priv;
+ HRESULT hr;
+
+ if (!(priv = HeapAlloc(GetProcessHeap(), 0, sizeof(*priv))))
+ {
+ ERR("Failed to allocate private data.\n");
+ return E_OUTOFMEMORY;
+ }
+
+ if (FAILED(hr = fragment_pipe->alloc_private(device)))
+ {
+ ERR("Failed to initialize fragment pipe, hr %#x.\n", hr);
+ HeapFree(GetProcessHeap(), 0, priv);
+ return hr;
+ }
+
+ priv->fragment_pipe = fragment_pipe;
+ device->shader_priv = priv;
+
+ return WINED3D_OK;
+}
+
+static void shader_none_free(struct wined3d_device *device)
+{
+ struct shader_none_priv *priv = device->shader_priv;
+
+ priv->fragment_pipe->free_private(device);
+ HeapFree(GetProcessHeap(), 0, priv);
+}
+
static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
{
/* Set the shader caps to 0 for the none shader backend */
@@ -1498,6 +1533,21 @@ static BOOL shader_none_color_fixup_supported(struct color_fixup_desc fixup)
return FALSE;
}
+static void shader_none_enable_fragment_pipe(void *shader_priv,
+ const struct wined3d_gl_info *gl_info, BOOL enable)
+{
+ struct shader_none_priv *priv = shader_priv;
+
+ priv->fragment_pipe->enable_extension(gl_info, enable);
+}
+
+static BOOL shader_none_has_ffp_proj_control(void *shader_priv)
+{
+ struct shader_none_priv *priv = shader_priv;
+
+ return priv->fragment_pipe->ffp_proj_control;
+}
+
const struct wined3d_shader_backend_ops none_shader_backend =
{
shader_none_handle_instruction,
@@ -1514,6 +1564,8 @@ const struct wined3d_shader_backend_ops none_shader_backend =
shader_none_context_destroyed,
shader_none_get_caps,
shader_none_color_fixup_supported,
+ shader_none_enable_fragment_pipe,
+ shader_none_has_ffp_proj_control,
};
static HRESULT shader_set_function(struct wined3d_shader *shader, const DWORD *byte_code,
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index ebfdb7e..cab31f8 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -3348,7 +3348,7 @@ static void transform_texture(struct wined3d_context *context, const struct wine
device->strided_streams.use_map & (1 << (WINED3D_FFP_TEXCOORD0 + coordIdx))
? device->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format->id
: WINED3DFMT_UNKNOWN,
- device->frag_pipe->ffp_proj_control);
+ device->shader_backend->shader_has_ffp_proj_control(device->shader_priv));
/* The sampler applying function calls us if this changes */
if ((context->lastWasPow2Texture & (1 << texUnit)) && state->textures[texUnit])
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 2eb83c9..4a3779f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -784,6 +784,7 @@ struct vs_compile_args {
struct wined3d_context;
struct wined3d_state;
+struct fragment_pipeline;
struct wined3d_shader_backend_ops
{
@@ -798,11 +799,13 @@ struct wined3d_shader_backend_ops
void (*shader_load_np2fixup_constants)(void *shader_priv, const struct wined3d_gl_info *gl_info,
const struct wined3d_state *state);
void (*shader_destroy)(struct wined3d_shader *shader);
- HRESULT (*shader_alloc_private)(struct wined3d_device *device);
+ HRESULT (*shader_alloc_private)(struct wined3d_device *device, const struct fragment_pipeline *fragment_pipe);
void (*shader_free_private)(struct wined3d_device *device);
void (*shader_context_destroyed)(void *shader_priv, const struct wined3d_context *context);
void (*shader_get_caps)(const struct wined3d_gl_info *gl_info, struct shader_caps *caps);
BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);
+ void (*shader_enable_fragment_pipe)(void *shader_priv, const struct wined3d_gl_info *gl_info, BOOL enable);
+ BOOL (*shader_has_ffp_proj_control)(void *shader_priv);
};
extern const struct wined3d_shader_backend_ops glsl_shader_backend DECLSPEC_HIDDEN;
@@ -1704,7 +1707,6 @@ struct wined3d_device
struct StateEntry StateTable[STATE_HIGHEST + 1];
/* Array of functions for states which are handled by more than one pipeline part */
APPLYSTATEFUNC *multistate_funcs[STATE_HIGHEST + 1];
- const struct fragment_pipeline *frag_pipe;
const struct blit_shader *blitter;
unsigned int max_ffp_textures;
--
1.7.8.6
More information about the wine-patches
mailing list