[Mesa-dev] [PATCH] util: fix blitter/draw module interaction
Brian Paul
brianp at vmware.com
Mon Oct 6 14:51:37 PDT 2014
If a driver uses the blitter utility and the draw module's AA point/line/
etc. helpers we have to very careful when using the pipe_context::
create_fs_state(), bind_fs_state() and delete_fs_state() functions.
The draw module can override these driver functions.
This fixes the situation where the blitter's calls to create_fs_state()
and bind_fs_state() were calling the draw module functions but
delete_fs_state() was calling the driver's function. That mismatch led
to memory corruption and crashes.
The blitter code tries to avoid hitting the draw module functions.
But that's derailed when the util_make_*fragment*() functions are
called for creating shaders on demand. This patch adds new functions
to patch in and restore the pipe::create_fs_state() function. We
also call the ctx->bind_fs_state() function everywhere. Now we should
never accidentally call any of the draw module functions.
---
src/gallium/auxiliary/util/u_blitter.c | 82 ++++++++++++++++++++++++++++++--
1 file changed, 79 insertions(+), 3 deletions(-)
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c
index f3fe949..76fba24 100644
--- a/src/gallium/auxiliary/util/u_blitter.c
+++ b/src/gallium/auxiliary/util/u_blitter.c
@@ -137,10 +137,59 @@ struct blitter_context_priv
/* The Draw module overrides these functions.
* Always create the blitter before Draw. */
+ void * (*create_fs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
void (*bind_fs_state)(struct pipe_context *, void *);
void (*delete_fs_state)(struct pipe_context *, void *);
+
+ /* Only used between begin/end_create_fs_state() */
+ void * (*saved_create_fs_state)(struct pipe_context *,
+ const struct pipe_shader_state *);
};
+
+
+/**
+ * Need to call this before calling any of the util_make_*fragment*()
+ * functions.
+ * When we create/bind/delete fragment shaders we want to call the actual
+ * driver functions, not the draw module's functions. The draw modules for
+ * drawing AA points/lines can overide the driver's function so when we
+ * call util_make_*fragment*() we may wind up calling a draw module
+ * create_fs_state() function by mistake.
+ *
+ * This helper plugs in the real/driver create_fs_state() function into the
+ * pipe context.
+ *
+ * The alternative to this madness would be to pass a create_fs_state
+ * function into the util_make_*fragment*() functions to be explicit.
+ * But that's not simple either since the tgsi ureg code would need to be
+ * touched too.
+ */
+static INLINE void
+begin_create_fs(struct blitter_context_priv *ctx)
+{
+ struct pipe_context *pipe = ctx->base.pipe;
+ assert(ctx->saved_create_fs_state == NULL);
+ ctx->saved_create_fs_state = pipe->create_fs_state;
+ pipe->create_fs_state = ctx->create_fs_state;
+}
+
+
+/**
+ * Need to call this after calling any of the util_make_*fragment*()
+ * functions to restore the pipe's create_fs_state() function.
+ */
+static INLINE void
+end_create_fs(struct blitter_context_priv *ctx)
+{
+ struct pipe_context *pipe = ctx->base.pipe;
+ assert(ctx->saved_create_fs_state);
+ pipe->create_fs_state = ctx->saved_create_fs_state;
+ ctx->saved_create_fs_state = NULL;
+}
+
+
static struct pipe_surface *
util_blitter_get_next_surface_layer(struct pipe_context *pipe,
struct pipe_surface *surf);
@@ -163,6 +212,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe)
ctx->base.draw_rectangle = util_blitter_draw_rectangle;
ctx->base.get_next_surface_layer = util_blitter_get_next_surface_layer;
+ ctx->create_fs_state = pipe->create_fs_state;
ctx->bind_fs_state = pipe->bind_fs_state;
ctx->delete_fs_state = pipe->delete_fs_state;
@@ -356,10 +406,12 @@ static void bind_fs_empty(struct blitter_context_priv *ctx)
struct pipe_context *pipe = ctx->base.pipe;
if (!ctx->fs_empty) {
+ begin_create_fs(ctx);
ctx->fs_empty = util_make_empty_fragment_shader(pipe);
+ end_create_fs(ctx);
}
- pipe->bind_fs_state(pipe, ctx->fs_empty);
+ ctx->bind_fs_state(pipe, ctx->fs_empty);
}
static void bind_fs_write_one_cbuf(struct blitter_context_priv *ctx)
@@ -367,12 +419,14 @@ static void bind_fs_write_one_cbuf(struct blitter_context_priv *ctx)
struct pipe_context *pipe = ctx->base.pipe;
if (!ctx->fs_write_one_cbuf) {
+ begin_create_fs(ctx);
ctx->fs_write_one_cbuf =
util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
TGSI_INTERPOLATE_CONSTANT, FALSE);
+ end_create_fs(ctx);
}
- pipe->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
+ ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
}
static void bind_fs_write_all_cbufs(struct blitter_context_priv *ctx)
@@ -380,14 +434,18 @@ static void bind_fs_write_all_cbufs(struct blitter_context_priv *ctx)
struct pipe_context *pipe = ctx->base.pipe;
if (!ctx->fs_write_all_cbufs) {
+ begin_create_fs(ctx);
ctx->fs_write_all_cbufs =
util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
TGSI_INTERPOLATE_CONSTANT, TRUE);
+ end_create_fs(ctx);
}
- pipe->bind_fs_state(pipe, ctx->fs_write_all_cbufs);
+ ctx->bind_fs_state(pipe, ctx->fs_write_all_cbufs);
}
+void **special_addr = NULL;
+
void util_blitter_destroy(struct blitter_context *blitter)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
@@ -850,6 +908,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
shader = &ctx->fs_resolve[target][index][filter];
if (!*shader) {
+ begin_create_fs(ctx);
if (filter == PIPE_TEX_FILTER_LINEAR) {
*shader = util_make_fs_msaa_resolve_bilinear(pipe, tgsi_tex,
src_nr_samples,
@@ -860,6 +919,7 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
src_nr_samples,
is_uint, is_sint);
}
+ end_create_fs(ctx);
}
}
else {
@@ -870,7 +930,9 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
/* Create the fragment shader on-demand. */
if (!*shader) {
+ begin_create_fs(ctx);
*shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex);
+ end_create_fs(ctx);
}
}
@@ -880,8 +942,10 @@ static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
/* Create the fragment shader on-demand. */
if (!*shader) {
+ begin_create_fs(ctx);
*shader = util_make_fragment_tex_shader(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
+ end_create_fs(ctx);
}
return *shader;
@@ -905,8 +969,10 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
+ begin_create_fs(ctx);
*shader =
util_make_fs_blit_msaa_depth(pipe, tgsi_tex);
+ end_create_fs(ctx);
}
return *shader;
@@ -917,9 +983,11 @@ void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
+ begin_create_fs(ctx);
*shader =
util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
+ end_create_fs(ctx);
}
return *shader;
@@ -943,8 +1011,10 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
+ begin_create_fs(ctx);
*shader =
util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);
+ end_create_fs(ctx);
}
return *shader;
@@ -955,9 +1025,11 @@ void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
+ begin_create_fs(ctx);
*shader =
util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
+ end_create_fs(ctx);
}
return *shader;
@@ -981,8 +1053,10 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
+ begin_create_fs(ctx);
*shader =
util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);
+ end_create_fs(ctx);
}
return *shader;
@@ -993,9 +1067,11 @@ void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
+ begin_create_fs(ctx);
*shader =
util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
+ end_create_fs(ctx);
}
return *shader;
--
1.7.10.4
More information about the mesa-dev
mailing list