wined3d: Make the shader backend responsible for controlling the fixed function fragment pipe.

This commit is contained in:
Henri Verbeet 2012-10-24 21:23:37 +02:00 committed by Alexandre Julliard
parent 2bf46c60fb
commit 17e33e9b27
7 changed files with 157 additions and 71 deletions

View File

@ -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 */

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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,

View File

@ -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])

View File

@ -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;